From 388167705a85dd0633686fa9191febebb93f86d1 Mon Sep 17 00:00:00 2001 From: MaysWind Date: Sat, 27 Sep 2025 14:55:30 +0800 Subject: [PATCH] build package for windows via github actions --- .github/workflows/build-release.yml | 77 +++++++++ .github/workflows/build-snapshot.yml | 75 +++++++++ build.ps1 | 231 +++++++++++++++++++++++++++ 3 files changed, 383 insertions(+) create mode 100644 build.ps1 diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index f19dbffd..afb772c9 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -101,3 +101,80 @@ jobs: name: ezbookkeeping-${{ github.ref_name }}-${{ matrix.arch_alias }} path: ezbookkeeping-${{ github.ref_name }}-${{ matrix.arch_alias }}.tar.gz if-no-files-found: error + + build-and-upload-windows-package: + needs: upload-linux-artifact + runs-on: windows-latest + env: + GO_VERSION: "1.25.1" + MINGW_VERSION: "14.2.0" + MINGW_REVISION: "v12-rev2" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Download linux-amd64 packaged files + uses: actions/download-artifact@v4 + with: + name: ezbookkeeping-${{ github.ref_name }}-linux-amd64 + path: artifacts + + - name: Extract frontend files from linux-amd64 package + run: | + New-Item -ItemType Directory -Path package + tar -xzf (Get-ChildItem artifacts\ezbookkeeping-v*-linux-amd64.tar.gz) -C package + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Install MinGW + run: | + $mingwVersion = "${{ env.MINGW_VERSION }}" + $mingwRevision = "${{ env.MINGW_REVISION }}" + $url = "https://github.com/niXman/mingw-builds-binaries/releases/download/${mingwVersion}-rt_${mingwRevision}/x86_64-${mingwVersion}-release-posix-seh-ucrt-rt_${mingwRevision}.7z" + $archive = "C:\mingw.7z" + $mingwDir = "C:\mingw64" + + Write-Host "Downloading MinGW from ${url}" + Invoke-WebRequest -Uri ${url} -OutFile ${archive} + + Remove-Item -Recurse -Force ${mingwDir} + New-Item -ItemType Directory -Path ${mingwDir} + + Write-Host "Extracting MinGW to ${mingwDir}" + 7z x ${archive} -oC:\ + "${mingwDir}\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + + - name: Build backend for windows-x64 + env: + RELEASE_BUILD: "1" + BUILD_PIPELINE: "1" + CHECK_3RD_API: ${{ vars.CHECK_3RD_API }} + SKIP_TESTS: ${{ vars.SKIP_TESTS }} + run: | + .\build.ps1 backend + + - name: Package Windows build + run: | + New-Item -ItemType Directory -Path "ezbookkeeping" + New-Item -ItemType Directory -Path "ezbookkeeping\data" + New-Item -ItemType Directory -Path "ezbookkeeping\storage" + New-Item -ItemType Directory -Path "ezbookkeeping\log" + Copy-Item ezbookkeeping.exe -Destination ezbookkeeping\ + Copy-Item -Recurse -Force package\public -Destination ezbookkeeping\public + Copy-Item -Recurse -Force conf -Destination ezbookkeeping\conf + Copy-Item -Recurse -Force templates -Destination ezbookkeeping\templates + Copy-Item .\LICENSE -Destination ezbookkeeping\ + Push-Location ezbookkeeping + 7z a -r -tzip -mx9 ..\ezbookkeeping-${{ github.ref_name }}-windows-x64.zip * + Pop-Location + Remove-Item -Recurse -Force ezbookkeeping + + - name: Upload Windows artifact + uses: actions/upload-artifact@v4 + with: + name: ezbookkeeping-${{ github.ref_name }}-windows-x64 + path: ezbookkeeping-v*-windows-x64.zip + diff --git a/.github/workflows/build-snapshot.yml b/.github/workflows/build-snapshot.yml index b0dde81e..f4939f75 100644 --- a/.github/workflows/build-snapshot.yml +++ b/.github/workflows/build-snapshot.yml @@ -100,3 +100,78 @@ jobs: name: ezbookkeeping-dev-${{ github.run_id }}-${{ matrix.arch_alias }} path: ezbookkeeping-dev-${{ github.run_id }}-${{ matrix.arch_alias }}.tar.gz if-no-files-found: error + + build-and-upload-windows-package: + needs: upload-linux-artifact + runs-on: windows-latest + env: + GO_VERSION: "1.25.1" + MINGW_VERSION: "14.2.0" + MINGW_REVISION: "v12-rev2" + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Download linux-amd64 packaged files + uses: actions/download-artifact@v4 + with: + name: ezbookkeeping-dev-${{ github.run_id }}-linux-amd64 + path: artifacts + + - name: Extract frontend files from linux-amd64 package + run: | + New-Item -ItemType Directory -Path package + tar -xzf (Get-ChildItem artifacts\ezbookkeeping-dev-*-linux-amd64.tar.gz) -C package + + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: ${{ env.GO_VERSION }} + + - name: Install MinGW + run: | + $mingwVersion = "${{ env.MINGW_VERSION }}" + $mingwRevision = "${{ env.MINGW_REVISION }}" + $url = "https://github.com/niXman/mingw-builds-binaries/releases/download/${mingwVersion}-rt_${mingwRevision}/x86_64-${mingwVersion}-release-posix-seh-ucrt-rt_${mingwRevision}.7z" + $archive = "C:\mingw.7z" + $mingwDir = "C:\mingw64" + + Write-Host "Downloading MinGW from ${url}" + Invoke-WebRequest -Uri ${url} -OutFile ${archive} + + Remove-Item -Recurse -Force ${mingwDir} + New-Item -ItemType Directory -Path ${mingwDir} + + Write-Host "Extracting MinGW to ${mingwDir}" + 7z x ${archive} -oC:\ + "${mingwDir}\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + + - name: Build backend for windows-x64 + env: + BUILD_PIPELINE: "1" + CHECK_3RD_API: ${{ vars.CHECK_3RD_API }} + SKIP_TESTS: ${{ vars.SKIP_TESTS }} + run: | + .\build.ps1 backend + + - name: Package Windows build + run: | + New-Item -ItemType Directory -Path "ezbookkeeping" + New-Item -ItemType Directory -Path "ezbookkeeping\data" + New-Item -ItemType Directory -Path "ezbookkeeping\storage" + New-Item -ItemType Directory -Path "ezbookkeeping\log" + Copy-Item ezbookkeeping.exe -Destination ezbookkeeping\ + Copy-Item -Recurse -Force package\public -Destination ezbookkeeping\public + Copy-Item -Recurse -Force conf -Destination ezbookkeeping\conf + Copy-Item -Recurse -Force templates -Destination ezbookkeeping\templates + Copy-Item .\LICENSE -Destination ezbookkeeping\ + Push-Location ezbookkeeping + 7z a -r -tzip -mx9 ..\ezbookkeeping-dev-${{ github.run_id }}-windows-x64.zip * + Pop-Location + Remove-Item -Recurse -Force ezbookkeeping + + - name: Upload Windows artifact + uses: actions/upload-artifact@v4 + with: + name: ezbookkeeping-dev-${{ github.run_id }}-windows-x64 + path: ezbookkeeping-dev-*-windows-x64.zip diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 00000000..637873b0 --- /dev/null +++ b/build.ps1 @@ -0,0 +1,231 @@ +param( + [string]$Type, + [switch]$NoLint, + [switch]$NoTest, + [string]$Output, + [switch]$Release, + [switch]$Help +) + +$script:SkipTests = $env:SKIP_TESTS +$script:ReleaseType = "unknown" +$script:Version = "" +$script:CommitHash = "" +$script:BuildUnixTime = "" +$script:BuildDate = "" + +function Write-Red($msg) { + Write-Host $msg -ForegroundColor Red +} + +function Check-Dependency { + param([string[]]$commands) + foreach ($cmd in $commands) { + if (-not (Get-Command $cmd -ErrorAction SilentlyContinue)) { + Write-Red "Error: `"$cmd`" is required." + exit 127 + } + } +} + +function Show-Help { + Write-Host "ezBookkeeping build script for Windows PowerShell" + Write-Host "" + Write-Host "Usage:" + Write-Host " build.ps1 type [options]" + Write-Host "" + Write-Host "Types:" + Write-Host " backend Build backend binary file" + Write-Host " frontend Build frontend files" + Write-Host " package Build package archive" + Write-Host "" + Write-Host "Options:" + Write-Host " -Release Build release (The script will use environment variable `"RELEASE_BUILD`" to detect whether this is release building by default)" + Write-Host " -Output Package file name (for `"package`" type only)" + Write-Host " -NoLint Do not execute lint check before building" + Write-Host " -NoTest Do not execute unit testing before building (You can use environment variable `"SKIP_TESTS`" to skip specified tests)" + Write-Host " -Help Show help" +} + +function Parse-Args { + if (-not $Type) { + Show-Help + exit 0 + } + + if ($Release -or $env:RELEASE_BUILD) { + $script:ReleaseType = "release" + } else { + $script:ReleaseType = "snapshot" + } +} + +function Check-Type-Dependencies { + Check-Dependency "git" + + switch ($Type.ToLower()) { + "backend" { + Check-Dependency "go","gcc" + } + "frontend" { + Check-Dependency "node","npm" + } + "package" { + Check-Dependency "go","gcc","node","npm","7z" + } + } +} + +function Set-Build-Parameters { + $script:Version = (Get-Content package.json | ConvertFrom-Json).version + $script:CommitHash = git rev-parse --short=7 HEAD + $script:BuildUnixTime = [int][double]::Parse((Get-Date -UFormat %s)) + $script:BuildDate = Get-Date -Format "yyyyMMdd" +} + +function Build-Backend { + Write-Host "Pulling backend dependencies..." + go get . + + if (-not $NoLint) { + Write-Host "Executing backend lint checking..." + go vet -v .\... + + if ($LASTEXITCODE -ne 0) { + Write-Red "Error: Failed to pass lint checking" + exit 1 + } + } + + if (-not $NoTest) { + Write-Host "Executing backend unit testing..." + go clean -cache + + if (-not $SkipTests) { + go test .\... -v + } else { + Write-Host "(Skip unit test `"$SkipTests`")" + go test .\... -v -skip "$SkipTests" + } + + if ($LASTEXITCODE -ne 0) { + Write-Red "Error: Failed to pass unit testing" + exit 1 + } + } + + $backend_build_extra_arguments = "-X main.Version=$Version " + $backend_build_extra_arguments = "$backend_build_extra_arguments -X main.CommitHash=$CommitHash" + + if (-not $Release) { + $backend_build_extra_arguments += " -X main.BuildUnixTime=$BuildUnixTime" + } + + Write-Host "Building backend binary file ($ReleaseType)..." + + $env:CGO_ENABLED = 1 + go build -a -v -trimpath -tags timetzdata -ldflags "-w -s -linkmode external -extldflags '-static' $backend_build_extra_arguments" -o ezbookkeeping.exe ezbookkeeping.go + + Remove-Item Env:\CGO_ENABLED -ErrorAction SilentlyContinue +} + +function Build-Frontend { + Write-Host "Pulling frontend dependencies..." + npm install + + if (-not $NoLint) { + Write-Host "Executing frontend lint checking..." + npm run lint + + if ($LASTEXITCODE -ne 0) { + Write-Red "Error: Failed to pass lint checking" + exit 1 + } + } + + if (-not $NoTest) { + Write-Host "Executing frontend unit testing..." + + npm run test + + if ($LASTEXITCODE -ne 0) { + Write-Red "Error: Failed to pass unit testing" + exit 1 + } + } + + Write-Host "Building frontend files ($ReleaseType)..." + + if (-not $Release) { + $env:buildUnixTime = $BuildUnixTime + npm run build + Remove-Item Env:\buildUnixTime -ErrorAction SilentlyContinue + } else { + npm run build + } +} + +function Build-Package { + $packageFileName = "ezbookkeeping-$Version" + + if (-not $Release) { + $packageFileName = "$packageFileName-$BuildDate" + } + + $packageFileName = "$packageFileName-windows.zip" + + if ($Output) { + $packageFileName = $Output + } + + Write-Host "Building package archive '$packageFileName' ($ReleaseType)..." + + Build-Backend + Build-Frontend + + Remove-Item package -Recurse -Force -ErrorAction SilentlyContinue + New-Item -ItemType Directory -Path "package" + New-Item -ItemType Directory -Path "package\data" + New-Item -ItemType Directory -Path "package\storage" + New-Item -ItemType Directory -Path "package\log" + + Copy-Item ezbookkeeping.exe package\ + Copy-Item dist package\public -Recurse + Copy-Item conf package\conf -Recurse + Copy-Item templates package\templates -Recurse + Copy-Item LICENSE package\ + + Push-Location package + 7z a -r -tzip -mx9 "..\$packageFileName" * + Pop-Location +} + +function Main { + if ($Help) { + Show-Help + exit 0 + } + + Parse-Args + Check-Type-Dependencies + Set-Build-Parameters + + switch ($Type) { + "backend" { + Build-Backend + } + "frontend" { + Build-Frontend + } + "package" { + Build-Package + } + default { + Write-Red "Invalid type: $Type" + Show-Help + exit 2 + } + } +} + +Main