diff --git a/.github/workflows/chocolatey.yml b/.github/workflows/chocolatey.yml index 209ad040597..1c1ced145f6 100644 --- a/.github/workflows/chocolatey.yml +++ b/.github/workflows/chocolatey.yml @@ -25,6 +25,11 @@ # once the archive has the file, or start this workflow from the Actions tab # with the version. # +# An installer the release vote did not cover is not on dist.apache.org, and +# so not in the archive either. For such a release, start this workflow from +# the Actions tab with installer_source set to github: the package then +# downloads the copy on the GitHub release. See doc/ReleaseManagement.md. +# # Nothing is pushed unless the CHOCO_API_KEY secret is set, to the API key of # an account that maintains the "thrift" package on the Chocolatey community # repository. See doc/ReleaseManagement.md. @@ -48,6 +53,14 @@ on: description: "Released version to package, for example 0.26.0. Taken from CMakeLists.txt when empty." required: false type: string + installer_source: + description: "Where the package downloads the installer from: archive (archive.apache.org) when the release vote covered the installer, github (the copy on the GitHub release) when it did not." + required: false + type: choice + options: + - archive + - github + default: archive concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -109,15 +122,21 @@ jobs: shell: pwsh env: VERSION: ${{ steps.version.outputs.version }} + INSTALLER_SOURCE: ${{ inputs.installer_source }} # A release and a manual run both push, so only a pull request # packages a placeholder. IS_PULL_REQUEST: ${{ github.event_name == 'pull_request' }} run: | + # Only a manual run has inputs. A release run uses the archive. + $source = if ($env:INSTALLER_SOURCE) { $env:INSTALLER_SOURCE } else { 'archive' } + Write-Host "Installer source: $source" + if ($env:IS_PULL_REQUEST -ne 'true') { # No checksum given, so the published installer is downloaded and # hashed. The package then cannot record a checksum the published # file does not have. - ./build/windows/build-chocolatey-package.ps1 -Version $env:VERSION -OutputDir chocolatey-package + ./build/windows/build-chocolatey-package.ps1 -Version $env:VERSION ` + -InstallerSource $source -OutputDir chocolatey-package } else { # Nothing is published for a pull request, so this packages an @@ -126,7 +145,7 @@ jobs: # does not upload it. Write-Host '::notice::Packaging with a placeholder checksum; this run cannot push.' ./build/windows/build-chocolatey-package.ps1 -Version $env:VERSION ` - -Sha256 ('DEADBEEF' * 8) -OutputDir chocolatey-package + -Sha256 ('DEADBEEF' * 8) -InstallerSource $source -OutputDir chocolatey-package } - name: Check the packed package @@ -150,7 +169,7 @@ jobs: name: Push to Chocolatey needs: package # A manual run is how a release gets pushed once the archive has the - # installer, so it pushes too. + # installer, or from the GitHub release, so it pushes too. if: ${{ github.event_name == 'workflow_dispatch' || (github.event_name == 'release' && !github.event.release.prerelease) }} runs-on: windows-2025 timeout-minutes: 20 diff --git a/.github/workflows/windows-packages.yml b/.github/workflows/windows-packages.yml index 3c4f458206c..339d2af7fce 100644 --- a/.github/workflows/windows-packages.yml +++ b/.github/workflows/windows-packages.yml @@ -35,7 +35,9 @@ # The installer that counts is the one on dist.apache.org, signed by a release # manager. What this workflow attaches to the GitHub release is an unsigned # convenience copy, so that the link is there straight away; the release -# manager overwrites it with the signed file afterwards. See +# manager overwrites it with the signed file afterwards. When the vote did not +# cover the installer, there is no signed file, and WinGet and Chocolatey +# download this copy instead, so it must then stay as it is. See # doc/ReleaseManagement.md. name: "Windows packages" @@ -343,4 +345,6 @@ jobs: # This is the unsigned convenience copy, around the voted compiler. # The release manager replaces it with the signed file from # dist.apache.org after the vote, which is also a --clobber upload. + # When the vote did not cover the installer, WinGet and Chocolatey + # download this copy, and it is not replaced. gh release upload "$RELEASE_TAG" "$installer" --clobber diff --git a/.github/workflows/winget.yml b/.github/workflows/winget.yml index ba01a9a2801..1152d1d0df5 100644 --- a/.github/workflows/winget.yml +++ b/.github/workflows/winget.yml @@ -24,6 +24,11 @@ # run until the release has been promoted and the archive has picked it up. If # the release run is too early, re-run it once the archive has the file, or # start this workflow from the Actions tab with the version and release date. +# +# An installer the release vote did not cover is not on dist.apache.org, and +# so not in the archive either. For such a release, start this workflow from +# the Actions tab with installer_source set to github: the manifest then points +# at the copy on the GitHub release. See doc/ReleaseManagement.md. name: "WinGet" @@ -48,6 +53,14 @@ on: description: "Release date as yyyy-MM-dd. Today when empty, which is only right on the day of the release." required: false type: string + installer_source: + description: "Where the manifest points for the installer: archive (archive.apache.org) when the release vote covered the installer, github (the copy on the GitHub release) when it did not." + required: false + type: choice + options: + - archive + - github + default: archive concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -133,16 +146,21 @@ jobs: env: VERSION: ${{ steps.version.outputs.version }} RELEASE_DATE: ${{ steps.version.outputs.release_date }} + INSTALLER_SOURCE: ${{ inputs.installer_source }} # A release and a manual run both submit, so only a pull request # renders with a placeholder. IS_PULL_REQUEST: ${{ github.event_name == 'pull_request' }} run: | + # Only a manual run has inputs. A release run uses the archive. + $source = if ($env:INSTALLER_SOURCE) { $env:INSTALLER_SOURCE } else { 'archive' } + Write-Host "Installer source: $source" + if ($env:IS_PULL_REQUEST -ne 'true') { # No checksum given, so the renderer downloads the published # installer and hashes that. The manifest then cannot claim a # checksum the published file does not have. ./build/windows/build-winget-manifests.ps1 -Version $env:VERSION ` - -ReleaseDate $env:RELEASE_DATE -OutputDir winget-manifests + -ReleaseDate $env:RELEASE_DATE -InstallerSource $source -OutputDir winget-manifests } else { # Nothing is published for a pull request, so the manifests are @@ -151,7 +169,8 @@ jobs: # and the job does not upload them. Write-Host '::notice::Rendering with a placeholder checksum; this run cannot submit.' ./build/windows/build-winget-manifests.ps1 -Version $env:VERSION ` - -ReleaseDate $env:RELEASE_DATE -Sha256 ('DEADBEEF' * 8) -OutputDir winget-manifests + -ReleaseDate $env:RELEASE_DATE -Sha256 ('DEADBEEF' * 8) -InstallerSource $source ` + -OutputDir winget-manifests } - name: Set up Python @@ -195,7 +214,7 @@ jobs: name: Submit to winget-pkgs needs: manifests # A manual run is how a release gets submitted once the archive has the - # installer, so it submits too. + # installer, or from the GitHub release, so it submits too. if: ${{ github.event_name == 'workflow_dispatch' || (github.event_name == 'release' && !github.event.release.prerelease) }} # wingetcreate only runs on Windows. runs-on: windows-2025 diff --git a/build/windows/README.md b/build/windows/README.md index a4768d6d16e..e9011640c93 100644 --- a/build/windows/README.md +++ b/build/windows/README.md @@ -212,10 +212,12 @@ PS C:\thrift> .\build\windows\build-chocolatey-package.ps1 -Version 0.26.0 The package does not carry the compiler. It downloads the installer published with the release and runs it silently for all users, so what a user installs is -what was voted on and signed, and no binary is redistributed through a third -party CDN. As with the WinGet manifest, the URL is `archive.apache.org` and the -checksum is computed from the file at that very URL, so the package cannot -record a checksum the published file does not have. +the voted compiler, and no binary is redistributed through a third party CDN. +As with the WinGet manifest, the URL is `archive.apache.org` and the checksum is +computed from the file at that very URL, so the package cannot record a +checksum the published file does not have. For a release whose vote did not +cover the installer, `-InstallerSource github` takes the copy on the GitHub +release instead. Pass `-StageOnly` to render the package without packing it, which works on a machine that has no Chocolatey. @@ -224,7 +226,8 @@ machine that has no Chocolatey. Tests the builder: that the URL, checksum and silent install arguments reach the install script, that no placeholder survives, that `LICENSE` and `NOTICE` -are staged and not empty, and that a malformed version or checksum is refused. +are staged and not empty, and that a malformed version or checksum, or an +unknown installer source, is refused. Given `-Package`, it also looks inside a packed `.nupkg` - including that it carries no executable, since the compiler is downloaded at install time. @@ -246,17 +249,21 @@ The manifest points at `archive.apache.org`, which keeps every release. would stop working at the next release and take every older version in winget-pkgs with it. +An installer the release vote did not cover is not on `dist.apache.org`, and so +not in the archive either. For such a release, `-InstallerSource github` points +the manifest at the copy on the GitHub release, whose URL is just as permanent. + Unless `-Sha256` is given, the installer is downloaded from the very URL that goes into the manifest and hashed, so the manifest cannot claim a checksum the published file does not have. That also means this cannot be run before the -release has reached the archive. +installer is there: for the archive, before the release has reached it. ### `winget/test-winget-manifests.ps1` Tests the renderer: that the values land where they belong, that no placeholder survives into a file that would be submitted verbatim, that the output is UTF-8 without a BOM and with LF endings, and that a malformed version, checksum or -date is refused. +date, or an unknown installer source, is refused. ### `winget/validate_manifests.py` diff --git a/build/windows/build-chocolatey-package.ps1 b/build/windows/build-chocolatey-package.ps1 index e398096881b..e1048952acf 100644 --- a/build/windows/build-chocolatey-package.ps1 +++ b/build/windows/build-chocolatey-package.ps1 @@ -26,16 +26,28 @@ The package does not carry the compiler. It downloads the installer published with the release and runs it, so that what a user installs is - what was voted on and signed. Unless a checksum is given, it is computed - from the file at that very URL, which means this cannot run before the - release has reached the archive. + the voted compiler. Unless a checksum is given, it is computed from the + file at that very URL, which means this cannot run before the installer is + there: for the archive, until the release has reached it. .PARAMETER Version The released version, for example 0.26.0. .PARAMETER InstallerUrl - Where the installer is published. Defaults to the Apache archive, which - keeps every release; downloads.apache.org only carries the current one. + Where the installer is published. Defaults to the URL -InstallerSource + names. + +.PARAMETER InstallerSource + Where the installer is taken from when -InstallerUrl is not given: + + - archive, the default: the Apache archive, which keeps every release. The + installer gets there through dist/release when the release vote + covered it. + - github: the convenience copy on the GitHub release, for a release whose + vote did not cover the installer, so that it is not on dist.apache.org. + + downloads.apache.org is not offered: it only carries the current release, + so a package naming it stops installing at the next one. .PARAMETER Sha256 The installer's SHA-256. Computed from the downloaded file when omitted. @@ -53,6 +65,9 @@ .EXAMPLE pwsh build/windows/build-chocolatey-package.ps1 -Version 0.26.0 + +.EXAMPLE + pwsh build/windows/build-chocolatey-package.ps1 -Version 0.25.0 -InstallerSource github #> [CmdletBinding()] @@ -60,6 +75,8 @@ param( [Parameter(Mandatory = $true)] [string] $Version, [string] $InstallerUrl = '', + [ValidateSet('archive', 'github')] + [string] $InstallerSource = 'archive', [string] $Sha256 = '', [string] $OutputDir = 'chocolatey-package', [string] $SourceRoot = '', @@ -71,8 +88,19 @@ $ErrorActionPreference = 'Stop' if ($Version -notmatch '^\d+\.\d+\.\d+$') { throw "Version '$Version' is not major.minor.patch." } +if ($InstallerUrl -and $PSBoundParameters.ContainsKey('InstallerSource')) { + throw 'Pass either -InstallerUrl or -InstallerSource, not both.' +} +$downloadHint = '' if (-not $InstallerUrl) { - $InstallerUrl = "https://archive.apache.org/dist/thrift/$Version/thrift-$Version-setup.exe" + if ($InstallerSource -eq 'github') { + $InstallerUrl = "https://github.com/apache/thrift/releases/download/v$Version/thrift-$Version-setup.exe" + $downloadHint = "The Windows packages workflow attaches the installer to the GitHub release v$Version." + } + else { + $InstallerUrl = "https://archive.apache.org/dist/thrift/$Version/thrift-$Version-setup.exe" + $downloadHint = 'If the release was just promoted, the Apache archive may not have picked it up yet. Wait and try again.' + } } if (-not $SourceRoot) { $SourceRoot = (Resolve-Path (Join-Path $PSScriptRoot '..\..')).Path @@ -97,8 +125,8 @@ else { Invoke-WebRequest -Uri $InstallerUrl -OutFile $download -MaximumRedirection 5 } catch { - throw ("Could not download $InstallerUrl : " + $_.Exception.Message + "`n" + - 'If the release was just promoted, the Apache archive may not have picked it up yet. Wait and try again.') + throw ("Could not download $InstallerUrl : " + $_.Exception.Message + + $(if ($downloadHint) { "`n$downloadHint" })) } $Sha256 = (Get-FileHash -Algorithm SHA256 -LiteralPath $download).Hash.ToUpperInvariant() Write-Host " sha256: $Sha256" diff --git a/build/windows/build-winget-manifests.ps1 b/build/windows/build-winget-manifests.ps1 index 063aa8660cb..5801ed31740 100644 --- a/build/windows/build-winget-manifests.ps1 +++ b/build/windows/build-winget-manifests.ps1 @@ -28,15 +28,27 @@ Unless a checksum is given, the installer is downloaded from the very URL that goes into the manifest and hashed, so that the manifest cannot claim a checksum the published file does not have. That also means this cannot run - before the release has reached the archive. + before the installer is there: for the archive, until the release has + reached it. .PARAMETER Version The released version, for example 0.26.0. .PARAMETER InstallerUrl - Where the installer is published. Defaults to the Apache archive, which - keeps every release; downloads.apache.org only carries the current one, so - a manifest naming it stops working at the next release. + Where the installer is published. Defaults to the URL -InstallerSource + names. + +.PARAMETER InstallerSource + Where the installer is taken from when -InstallerUrl is not given: + + - archive, the default: the Apache archive, which keeps every release. The + installer gets there through dist/release when the release vote + covered it. + - github: the convenience copy on the GitHub release, for a release whose + vote did not cover the installer, so that it is not on dist.apache.org. + + downloads.apache.org is not offered: it only carries the current release, + so a manifest naming it stops working at the next one. .PARAMETER Sha256 The installer's SHA-256. Computed from the downloaded file when omitted. @@ -51,6 +63,9 @@ .EXAMPLE pwsh build/windows/build-winget-manifests.ps1 -Version 0.26.0 + +.EXAMPLE + pwsh build/windows/build-winget-manifests.ps1 -Version 0.25.0 -InstallerSource github -ReleaseDate 2026-09-30 #> [CmdletBinding()] @@ -58,6 +73,8 @@ param( [Parameter(Mandatory = $true)] [string] $Version, [string] $InstallerUrl = '', + [ValidateSet('archive', 'github')] + [string] $InstallerSource = 'archive', [string] $Sha256 = '', [string] $ReleaseDate = '', [string] $OutputDir = 'winget-manifests' @@ -70,8 +87,19 @@ $PackageIdentifier = 'Apache.Thrift' if ($Version -notmatch '^\d+\.\d+\.\d+$') { throw "Version '$Version' is not major.minor.patch." } +if ($InstallerUrl -and $PSBoundParameters.ContainsKey('InstallerSource')) { + throw 'Pass either -InstallerUrl or -InstallerSource, not both.' +} +$downloadHint = '' if (-not $InstallerUrl) { - $InstallerUrl = "https://archive.apache.org/dist/thrift/$Version/thrift-$Version-setup.exe" + if ($InstallerSource -eq 'github') { + $InstallerUrl = "https://github.com/apache/thrift/releases/download/v$Version/thrift-$Version-setup.exe" + $downloadHint = "The Windows packages workflow attaches the installer to the GitHub release v$Version." + } + else { + $InstallerUrl = "https://archive.apache.org/dist/thrift/$Version/thrift-$Version-setup.exe" + $downloadHint = 'If the release was just promoted, the Apache archive may not have picked it up yet. Wait and try again.' + } } if (-not $ReleaseDate) { $ReleaseDate = (Get-Date).ToString('yyyy-MM-dd') @@ -94,8 +122,8 @@ else { Invoke-WebRequest -Uri $InstallerUrl -OutFile $download -MaximumRedirection 5 } catch { - throw ("Could not download $InstallerUrl : " + $_.Exception.Message + "`n" + - 'If the release was just promoted, the Apache archive may not have picked it up yet. Wait and try again.') + throw ("Could not download $InstallerUrl : " + $_.Exception.Message + + $(if ($downloadHint) { "`n$downloadHint" })) } $Sha256 = (Get-FileHash -Algorithm SHA256 -LiteralPath $download).Hash.ToUpperInvariant() Write-Host " sha256: $Sha256" diff --git a/build/windows/chocolatey/test-chocolatey-package.ps1 b/build/windows/chocolatey/test-chocolatey-package.ps1 index 98dee1e1c96..5e0e4d9a5a4 100644 --- a/build/windows/chocolatey/test-chocolatey-package.ps1 +++ b/build/windows/chocolatey/test-chocolatey-package.ps1 @@ -150,12 +150,29 @@ try { Assert-True 'a given download URL is used' ` ($customInstall -match "url64bit\s*=\s*'https://example\.invalid/thrift\.exe'") + # When the vote did not cover the installer, it is not on dist.apache.org, + # and the copy on the GitHub release is the one to download. + $github = & $builder -Version $version -Sha256 $sha -InstallerSource github ` + -OutputDir (Join-Path $workDir 'github') -StageOnly | Select-Object -Last 1 + $githubInstall = Get-Content -LiteralPath (Join-Path $github 'tools\chocolateyinstall.ps1') -Raw + $githubUrl = "https://github.com/apache/thrift/releases/download/v$version/thrift-$version-setup.exe" + Assert-True 'the download URL can be the asset on the GitHub release' ` + ($githubInstall -match "url64bit\s*=\s*'$([regex]::Escape($githubUrl))'") $githubInstall + Assert-Throws 'a version that is not major.minor.patch is refused' ` { & $builder -Version '1.2' -Sha256 $sha -OutputDir (Join-Path $workDir 'bad1') -StageOnly } 'major.minor.patch' Assert-Throws 'a checksum that is not 64 hex digits is refused' ` { & $builder -Version $version -Sha256 'nope' -OutputDir (Join-Path $workDir 'bad2') -StageOnly } 'hexadecimal' + # downloads.apache.org is the obvious third choice, and the wrong one. + Assert-Throws 'an unknown installer source is refused' ` + { & $builder -Version $version -Sha256 $sha -InstallerSource downloads -OutputDir (Join-Path $workDir 'bad3') -StageOnly } 'does not belong to the set' + + Assert-Throws 'an installer URL and an installer source together are refused' ` + { & $builder -Version $version -Sha256 $sha -InstallerUrl 'https://example.invalid/thrift.exe' ` + -InstallerSource github -OutputDir (Join-Path $workDir 'bad4') -StageOnly } 'not both' + # ---- an already packed package, when one was given --------------------- if ($Package) { diff --git a/build/windows/chocolatey/thrift.nuspec.in b/build/windows/chocolatey/thrift.nuspec.in index 41e99506ebc..6f713525fed 100644 --- a/build/windows/chocolatey/thrift.nuspec.in +++ b/build/windows/chocolatey/thrift.nuspec.in @@ -49,8 +49,9 @@ This package installs the Thrift compiler, which turns a `.thrift` interface definition into client and server code. The runtime libraries are distributed separately, through each language's own package manager. -The package downloads the Windows installer from the Apache archive and runs -it. The installer adds the compiler to `PATH`, so open a new shell afterwards. +The package downloads the Windows installer published with the Apache Thrift +release and runs it. The installer adds the compiler to `PATH`, so open a new +shell afterwards. ## Notes diff --git a/build/windows/chocolatey/tools/chocolateyinstall.ps1.in b/build/windows/chocolatey/tools/chocolateyinstall.ps1.in index c324ff4bad7..30e82046d51 100644 --- a/build/windows/chocolatey/tools/chocolateyinstall.ps1.in +++ b/build/windows/chocolatey/tools/chocolateyinstall.ps1.in @@ -24,9 +24,10 @@ $packageArgs = @{ packageName = 'thrift' fileType = 'exe' - # The installer published with the Apache Thrift release. The archive keeps - # every release; downloads.apache.org only carries the current one, so a - # package naming it would stop installing at the next release. + # The installer published with the Apache Thrift release, on the Apache + # archive or on the GitHub release. Both keep every release; + # downloads.apache.org only carries the current one, so a package naming it + # would stop installing at the next release. url64bit = '__INSTALLER_URL__' checksum64 = '__INSTALLER_SHA256__' checksumType64 = 'sha256' diff --git a/build/windows/winget/test-winget-manifests.ps1 b/build/windows/winget/test-winget-manifests.ps1 index 7ffe347e327..2b2fff10e3a 100644 --- a/build/windows/winget/test-winget-manifests.ps1 +++ b/build/windows/winget/test-winget-manifests.ps1 @@ -149,6 +149,15 @@ try { Assert-True 'a given installer URL is used' ` ($customInstaller -match 'InstallerUrl: https://example\.invalid/thrift\.exe') + # When the vote did not cover the installer, it is not on dist.apache.org, + # and the copy on the GitHub release is the one to point at. + $github = & $renderer -Version $version -Sha256 $sha -ReleaseDate $date -InstallerSource github ` + -OutputDir (Join-Path $workDir 'github') | Select-Object -Last 1 + $githubInstaller = Get-Content -LiteralPath (Join-Path $github 'Apache.Thrift.installer.yaml') -Raw + $githubUrl = "https://github.com/apache/thrift/releases/download/v$version/thrift-$version-setup.exe" + Assert-True 'the installer URL can be the asset on the GitHub release' ` + ($githubInstaller -match "InstallerUrl: $([regex]::Escape($githubUrl))") $githubInstaller + # winget-pkgs manifests are UTF-8 without a BOM, and PowerShell is happy to # write both a BOM and CRLF if left to itself. $bytes = [System.IO.File]::ReadAllBytes((Join-Path $targetDir 'Apache.Thrift.yaml')) @@ -166,6 +175,14 @@ try { Assert-Throws 'a release date that is not yyyy-MM-dd is refused' ` { & $renderer -Version $version -Sha256 $sha -ReleaseDate '20.09.2026' -OutputDir (Join-Path $workDir 'bad3') } 'yyyy-MM-dd' + + # downloads.apache.org is the obvious third choice, and the wrong one. + Assert-Throws 'an unknown installer source is refused' ` + { & $renderer -Version $version -Sha256 $sha -InstallerSource downloads -OutputDir (Join-Path $workDir 'bad4') } 'does not belong to the set' + + Assert-Throws 'an installer URL and an installer source together are refused' ` + { & $renderer -Version $version -Sha256 $sha -InstallerUrl 'https://example.invalid/thrift.exe' ` + -InstallerSource github -OutputDir (Join-Path $workDir 'bad5') } 'not both' } finally { Remove-Item -LiteralPath $workDir -Recurse -Force -ErrorAction SilentlyContinue diff --git a/doc/ReleaseManagement.md b/doc/ReleaseManagement.md index c9a073bc4b6..33d3285f4fa 100644 --- a/doc/ReleaseManagement.md +++ b/doc/ReleaseManagement.md @@ -516,34 +516,35 @@ signature checks out against `KEYS`. When the GitHub release is published, the workflow attaches the installer to it as an unsigned convenience copy, so that the download link is there -immediately. **One thing is left to do after the release:** overwrite that asset -with the signed file from `dist/release`, so that what people download from -GitHub is what the signatures on `dist.apache.org` cover. +immediately. If the vote covered the installer, **one thing is left to do after +the release:** overwrite that asset with the signed file from `dist/release`, so +that what people download from GitHub is what the signatures on +`dist.apache.org` cover. ```bash ~$ gh release upload v1.0.0 thrift-1.0.0-setup.exe --clobber --repo apache/thrift ``` -If the installer was not part of the release candidate, it is missing from -`dist/release` too, and the Chocolatey and WinGet runs of the release fail to -download it. To add it afterwards: - -1. Build it around the voted compiler. Run the `Windows packages` workflow from - the Actions tab with `compiler_url` set to the executable in `dist/release`, - for example `https://dist.apache.org/repos/dist/release/thrift/1.0.0/thrift-1.0.0.exe`, - and take its `windows-installer` artifact. It installs the `LICENSE` and - `NOTICE` of the release tag. To build it yourself instead, use Inno Setup - 6.3 or later in a checkout of the release tag: - - ```powershell - PS C:\thrift> .\build\windows\build-installer.ps1 -Version 1.0.0 -Compiler C:\dist\thrift-1.0.0.exe -OutputDir dist - ``` - -1. Sign and checksum it the same way as the other release artifacts, and commit - it with its signature and checksums to `dist/release/thrift/1.0.0`. -1. Overwrite the asset on the GitHub release with it, as shown above. -1. Once `archive.apache.org` has the file, run the [Chocolatey](#chocolatey) and - [WinGet](#winget) workflows again, as described below. +If the installer was not part of the release candidate, the vote did not cover +it. It is then missing from `dist/release`, and it is not added there after the +release either, since `dist/release` holds what the vote covered. The +Chocolatey and WinGet runs of the release fail to download it from the archive. +Point both at the convenience copy on the GitHub release instead: + +1. Make sure that copy is built around the voted compiler. The summary of the + release run of the `Windows packages` workflow names the compiler it + packaged, which has to be the executable in `dist/release`, not "built from + source". If it is not, run that workflow from the Actions tab with + `compiler_url` set to the executable in `dist/release`, for example + `https://dist.apache.org/repos/dist/release/thrift/1.0.0/thrift-1.0.0.exe`, + and upload its `windows-installer` artifact to the release with the + `gh release upload` command above. +1. Run the [Chocolatey](#chocolatey) and [WinGet](#winget) workflows from the + Actions tab with `installer_source` set to `github`. There is nothing to wait + for: the copy is on the GitHub release from the start. +1. Leave that asset alone from then on. Both package managers record its + SHA-256, so replacing it, even with another build around the same compiler, + breaks every installation of that version. ##### Chocolatey @@ -557,7 +558,10 @@ archive has the release - `downloads.apache.org` only carries the current release, and a package naming it would stop installing at the next one. If the release run was too early, re-run it once the archive has the file, which GitHub allows for 30 days, or start the workflow from the Actions tab (*Run workflow*) -with the released version. +with the released version. When the vote did not cover the installer, start it +with `installer_source` set to `github` instead, as described under +[Windows Packages](#windows-packages): the package then downloads the copy on +the GitHub release. The workflow pushes with the API key in the secret `CHOCO_API_KEY`, which has to belong to an account that maintains the `thrift` package on the Chocolatey @@ -575,13 +579,17 @@ It runs when the release is published, but it can only succeed once the release has been promoted to `dist.apache.org` **and** `archive.apache.org` has picked it up - the manifest points at the archive, because `downloads.apache.org` only carries the current release and a manifest naming it would stop working at the -next one. This is the same wait the Docker Official Image update has. +next one. This is the same wait the Docker Official Image update has. When the +vote did not cover the installer, the archive never gets it; the manifest then +points at the copy on the GitHub release, as described under +[Windows Packages](#windows-packages). So expect to run it again a while after the release. Re-running the release's run works for 30 days; starting the workflow from the Actions tab always works: 1. Actions → `WinGet` → *Run workflow*, entering the released version and its - release date. Without a date, the manifest records the day of the run. + release date. Without a date, the manifest records the day of the run. Set + `installer_source` to `github` when the vote did not cover the installer. 1. The workflow renders the manifests, downloads the published installer to compute its checksum, validates the manifests against the WinGet schemas, and opens a pull request against `microsoft/winget-pkgs`.