Repository navigation
發佈 v1.0.0.8 #9
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| - "V*" | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: "Release version, for example 1.0.1 or v1.0.1" | |
| required: true | |
| type: string | |
| permissions: | |
| contents: write | |
| jobs: | |
| build-release: | |
| name: Build and publish release | |
| runs-on: windows-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup MSBuild | |
| uses: microsoft/setup-msbuild@v2 | |
| - name: Setup NuGet | |
| uses: NuGet/setup-nuget@v2 | |
| - name: Resolve release version | |
| id: release_version | |
| shell: pwsh | |
| run: | | |
| if ("${{ github.event_name }}" -eq "workflow_dispatch") { | |
| $rawVersion = "${{ inputs.version }}" | |
| } else { | |
| $rawVersion = "${{ github.ref_name }}" | |
| } | |
| $version = $rawVersion.Trim() | |
| if ($version.StartsWith("v", [System.StringComparison]::OrdinalIgnoreCase)) { | |
| $version = $version.Substring(1) | |
| } | |
| if ($version -notmatch '^\d+\.\d+\.\d+(\.\d+)?$') { | |
| throw "Release version must be n.n.n or n.n.n.n. Received: $rawVersion" | |
| } | |
| $tagName = "v$version" | |
| "version=$version" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8 | |
| "tag_name=$tagName" | Out-File -FilePath $env:GITHUB_OUTPUT -Append -Encoding utf8 | |
| - name: Verify assembly version matches release | |
| shell: pwsh | |
| run: | | |
| $assemblyInfoPath = ".\mySQLPunk\Properties\AssemblyInfo.cs" | |
| $assemblyInfo = Get-Content -LiteralPath $assemblyInfoPath -Raw -Encoding UTF8 | |
| if ($assemblyInfo -notmatch 'AssemblyFileVersion\("([^"]+)"\)') { | |
| throw "AssemblyFileVersion was not found in $assemblyInfoPath" | |
| } | |
| $assemblyVersion = [version]$Matches[1] | |
| $releaseVersion = [version]"${{ steps.release_version.outputs.version }}" | |
| if ($releaseVersion.Revision -lt 0) { | |
| $releaseVersion = [version]::new($releaseVersion.Major, $releaseVersion.Minor, $releaseVersion.Build, 0) | |
| } | |
| if ($assemblyVersion.Revision -lt 0) { | |
| $assemblyVersion = [version]::new($assemblyVersion.Major, $assemblyVersion.Minor, $assemblyVersion.Build, 0) | |
| } | |
| if ($assemblyVersion -ne $releaseVersion) { | |
| throw "AssemblyFileVersion $assemblyVersion does not match release version $releaseVersion. Update AssemblyInfo.cs before publishing." | |
| } | |
| - name: Restore packages | |
| shell: pwsh | |
| run: nuget restore .\mySQLPunk.sln -NonInteractive | |
| - name: Setup Inno Setup | |
| shell: pwsh | |
| run: | | |
| $candidates = @( | |
| "${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe", | |
| "$env:ProgramFiles\Inno Setup 6\ISCC.exe", | |
| "$env:LOCALAPPDATA\Programs\Inno Setup 6\ISCC.exe" | |
| ) | |
| if ($candidates | Where-Object { Test-Path -LiteralPath $_ } | Select-Object -First 1) { | |
| exit 0 | |
| } | |
| $installerPath = Join-Path $env:RUNNER_TEMP "innosetup-6.7.3.exe" | |
| $installerUrl = "https://github.com/jrsoftware/issrc/releases/download/is-6_7_3/innosetup-6.7.3.exe" | |
| $expectedSha256 = "9c73c3bae7ed48d44112a0f48e66742c00090bdb5bef71d9d3c056c66e97b732" | |
| Invoke-WebRequest -Uri $installerUrl -OutFile $installerPath | |
| $actualSha256 = (Get-FileHash -LiteralPath $installerPath -Algorithm SHA256).Hash.ToLowerInvariant() | |
| if ($actualSha256 -ne $expectedSha256) { | |
| throw "Inno Setup installer SHA-256 mismatch. Expected $expectedSha256, got $actualSha256." | |
| } | |
| $process = Start-Process -FilePath $installerPath -ArgumentList "/VERYSILENT", "/SUPPRESSMSGBOXES", "/NORESTART", "/CURRENTUSER" -Wait -PassThru | |
| if ($process.ExitCode -ne 0) { | |
| throw "Inno Setup installation failed with exit code $($process.ExitCode)." | |
| } | |
| $iscc = "$env:LOCALAPPDATA\Programs\Inno Setup 6\ISCC.exe" | |
| if (-not (Test-Path -LiteralPath $iscc)) { | |
| throw "ISCC.exe was not found after installing Inno Setup." | |
| } | |
| - name: Build and package | |
| shell: pwsh | |
| run: .\scripts\package-release.ps1 -Version "${{ steps.release_version.outputs.version }}" -Configuration Release -OutputRoot .\dist | |
| - name: Write release notes | |
| shell: pwsh | |
| run: .\scripts\New-ReleaseNotes.ps1 -Version "${{ steps.release_version.outputs.version }}" -OutputDirectory .\dist | |
| - name: Upload workflow artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: mySQLPunk-${{ steps.release_version.outputs.version }}-release-assets | |
| path: | | |
| dist/*-setup.exe | |
| dist/release-notes.md | |
| dist/release-title.txt | |
| - name: Create or update GitHub Release | |
| shell: pwsh | |
| env: | |
| GITHUB_TOKEN: ${{ github.token }} | |
| REPOSITORY: ${{ github.repository }} | |
| TAG_NAME: ${{ steps.release_version.outputs.tag_name }} | |
| run: | | |
| $headers = @{ | |
| Authorization = "Bearer $env:GITHUB_TOKEN" | |
| Accept = "application/vnd.github+json" | |
| "X-GitHub-Api-Version" = "2022-11-28" | |
| } | |
| $releaseName = (Get-Content -LiteralPath ".\dist\release-title.txt" -Raw -Encoding UTF8).Trim() | |
| $releaseNotes = Get-Content -LiteralPath ".\dist\release-notes.md" -Raw -Encoding UTF8 | |
| $releaseByTagUrl = "https://api.github.com/repos/$env:REPOSITORY/releases/tags/$env:TAG_NAME" | |
| $release = $null | |
| try { | |
| $release = Invoke-RestMethod -Method Get -Uri $releaseByTagUrl -Headers $headers | |
| } catch { | |
| $statusCode = 0 | |
| if ($_.Exception.Response -ne $null) { | |
| $statusCode = [int]$_.Exception.Response.StatusCode | |
| } | |
| if ($statusCode -ne 404) { | |
| throw | |
| } | |
| $body = @{ | |
| tag_name = $env:TAG_NAME | |
| target_commitish = $env:GITHUB_SHA | |
| name = $releaseName | |
| body = $releaseNotes | |
| draft = $false | |
| prerelease = $false | |
| } | ConvertTo-Json -Depth 4 | |
| $release = Invoke-RestMethod -Method Post -Uri "https://api.github.com/repos/$env:REPOSITORY/releases" -Headers $headers -Body $body -ContentType "application/json" | |
| } | |
| if ($null -ne $release -and ($release.name -ne $releaseName -or [string]$release.body -ne $releaseNotes)) { | |
| $body = @{ | |
| name = $releaseName | |
| body = $releaseNotes | |
| draft = $false | |
| prerelease = $false | |
| } | ConvertTo-Json -Depth 4 | |
| $release = Invoke-RestMethod -Method Patch -Uri "https://api.github.com/repos/$env:REPOSITORY/releases/$($release.id)" -Headers $headers -Body $body -ContentType "application/json" | |
| } | |
| $uploadBaseUrl = $release.upload_url -replace '\{.*\}$', '' | |
| $assets = @(Get-ChildItem -LiteralPath ".\dist" -Filter "*-setup.exe") | |
| if ($assets.Count -ne 1) { | |
| throw "Exactly one setup EXE is required, but found $($assets.Count)." | |
| } | |
| # A release intentionally has one downloadable file. Remove assets left by older runs. | |
| foreach ($existingAsset in @($release.assets)) { | |
| Invoke-RestMethod -Method Delete -Uri $existingAsset.url -Headers $headers | Out-Null | |
| } | |
| foreach ($asset in $assets) { | |
| $assetName = [uri]::EscapeDataString($asset.Name) | |
| $assetLabel = [uri]::EscapeDataString("Windows x64 單一安裝程式") | |
| $uploadUrl = "${uploadBaseUrl}?name=$assetName&label=$assetLabel" | |
| Invoke-RestMethod -Method Post -Uri $uploadUrl -Headers $headers -InFile $asset.FullName -ContentType "application/octet-stream" | Out-Null | |
| } |