fix: verify release artifacts before publishing and make re-runs safe - #116
Draft
hllvc wants to merge 2 commits into
Draft
fix: verify release artifacts before publishing and make re-runs safe#116hllvc wants to merge 2 commits into
hllvc wants to merge 2 commits into
Conversation
Publish the GitHub release only after every artifact is downloaded back and checked against SHA256SUMS, so the Registry never ingests a release that has no assets attached yet. Switch goreleaser to mode: replace so re-runs stop dying on 422 already_exists, and add a preflight that refuses to re-release an already published tag. Also build 13 platforms instead of 6, take the version from the tag (main.version has to be a var for -ldflags to apply at all), migrate to goreleaser v2, and move every action onto a node24 release.
Release notes are generated when a release is published now, so mark CHANGELOG.md as a historical archive covering up to 0.1.0 and point the README at the releases page instead of a file that stopped 53 releases ago. CONTRIBUTING gets the tag-push release flow and the pre-release tag convention.
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Reworks the provider release pipeline so a GitHub release is only published after every artifact has been downloaded back and verified, and so a failed release can simply be re-run. Also unpins GoReleaser from the end-of-life v1 line, moves the workflows onto Node 24 runtimes, and expands the build matrix from 6 platforms to 13.
Motivation & Context
The release process had three defects that only show up under failure.
Releases went public before they had artifacts. The release was created by hand in the GitHub UI, which created the tag, which triggered the workflow. For
v1.12.1the release was published at 07:36:38 and GoReleaser finished uploading at 07:44:55 — roughly eight minutes during which the release existed, was marked "Latest", and contained nothing. The Terraform Registry ingests on the release webhook, so it could see a release with noSHA256SUMSand no archives. The acceptance-test job was wired as aneeds:dependency, which reads like a gate, but it ran after the release was already public: a test failure left a published, empty release for someone to notice and delete.A failed release could not be re-run. With
mode: append, every asset that already existed came back422 Validation Failed [already_exists], and GoReleaser's retry loop just re-issued the same doomed request. Run28953853165shows all nine assets failing within three seconds. Recovery meant deleting assets by hand.The toolchain was pinned to an end-of-life release.
goreleaser-action@v5.1.0resolves to GoReleaser v1.26.2, the last v1, and every release already loggedDEPRECATED: changelog.skip. Separately, every action in the release path targeted Node 20, which GitHub is removing.Changes Made
Release ordering and verification (
.github/workflows/release.yaml,.goreleaser.yml)provider-release_publishjob publishes it only after verification.draftandreplace_existing_draftpreviously had no effect, because GoReleaser was appending to a release a human had already created.sha256sum --check --strictoverSHA256SUMS, and asserts the expected archive count before flipping the release to published. The count check is separate on purpose: the checksum file only covers what GoReleaser actually built, so it cannot catch a silently shrunken matrix.provider-release_preflightjob rejects a run that is not on a tag, and refuses to re-release a tag whose release is already published — Registry versions are immutable, so replacing artifacts underneath one breaks every consumer that has it in a lock file. It runs ahead of the acceptance tests so both failures cost seconds rather than five minutes against the production API.release.modechanged fromappendtoreplace, making re-runs idempotent while a release is still a draft.Build matrix and version stamping (
.goreleaser.yml,main.go,internal/acctest/acctest.go)linux/386,linux/arm,windows/386and all fourfreebsdtargets. An uncovered platform is a hardterraform initfailure, not a degraded experience.darwin/386,darwin/armandwindows/armare explicitly ignored — they no longer exist in modern Go, and HashiCorp's scaffolding template only excludes the first.main.godeclaredconst Version = "0.0.1"while the ldflags targetedmain.version. The linker cannot write a const and silently ignores a missing symbol, so every release since has shipped reporting0.0.1. It is now avarand takes the value from the tag. The dead-X main.commitflag is dropped, since nothing surfaces a commit and the symbol was being stripped.acctest.gopasses"test"as the version, which is what the struct comment inprovider.goalready claimed happened.Toolchain (
.github/workflows/community.yml,.github/workflows/test.yaml,Makefile)version: 2,archives.formattoformats, andchangelog.skiptochangelog.disable. These are coupled — v2 rejects the old config and v1 rejects the new one, so the config and the action bump have to land together.community.ymlto a Node 24 release, keeping the existing SHA-pin-with-version-comment style.goreleaser-actionwas pinned by tag while its neighbours used SHAs; it is now consistent.test.yamlkeeps its floating-major style:checkout@v7,setup-go@v7,setup-terraform@v4.releasetarget in theMakefileused--rm-dist,--skip-publishand--skip-sign, all removed in v2. It now uses--clean --skip=publish,sign, so the local dry run matches what CI runs.Release notes and documentation (
CHANGELOG.md,README.md,CONTRIBUTING.md)changelog.use: github-nativeproduces the same body without a human step.CHANGELOG.mdlast changed in March 2024, 53 releases ago, whileREADME.mdstill pointed users at it for release notes. It is marked as a historical archive covering up to0.1.0, and the README points at the releases page.CONTRIBUTING.mdgains the tag-push release flow, the re-run rules, the pre-release tag convention, and a note thatEXPECTED_ZIPStracks the build matrix. The instruction to updateCHANGELOG.mdbefore merging is replaced with guidance that PR titles become the release notes, which is now literally true..github/workflows/.old/release-old.yml.Unrelated test fix, needed for CI to pass (
internal/resource/workflow_from_template,internal/resource/workflow_git)terraform_version = "1.6.0"with400: Terraform 1.6.0 is above the highest managed version (1.5.7). The same test literals passed onmainin the scheduled run on 24 Aug (32689518464), so the managed version list changed server-side rather than anything here. The nine affected literals are pinned to1.5.7, which keeps the update steps meaningful (they still move1.5.0to1.5.7) and matches the version already used by thestack_template_revisionandworkflow_template_revisiontests, both of which passed in the failing run. If the cap to 1.5.7 was not intentional, this pin hides a real regression and should be reverted in favour of an API fix.Testing
goreleaser checkpasses on v2.18.0; v1.26.2 now rejects the config, confirming the config and action bump cannot drift apartv9.9.9produces-X main.version=9.9.9and the string is presentactionlintclean on the release path; the two findings intest-api.yamlare pre-existinggo build,gofmtandmake testshow no regressions against unmodifiedmaintest.yamlruns green on this PR with the bumpedcheckout@v7/setup-go@v7/setup-terraform@v4actionsgithub-nativepath has never runRisks & Edge Cases
EXPECTED_ZIPSinrelease.yamlis manually coupled to the matrix in.goreleaser.yml. That is deliberate — it is what catches a silently shrunken build — but adding a platform without updating it will fail the release. Documented inCONTRIBUTING.md.goreleaser-action@v7.2.3defaults to~> v2. Artifact naming has been stable and the new verification step would catch drift, but it can be pinned to~> v2.18if reproducibility matters more.main, always with a400 Bad Requestreturned as an nginx HTML page during resource creation. That is a gateway-level rejection rather than a provider or test bug, so no retry was added — masking it would remove the signal. It does mean roughly one release in ten will need a re-run, which is now a single click.Deployment Notes
v1.13.0-beta.1, not-beta-1) so semantic versioning orders them numerically.GPG_PRIVATE_KEYand theSG_PRD_*values are unchanged.