feat: add release automation script - #1992
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1992 +/- ##
==========================================
+ Coverage 87.26% 87.62% +0.36%
==========================================
Files 138 139 +1
Lines 5465 5681 +216
==========================================
+ Hits 4769 4978 +209
- Misses 415 420 +5
- Partials 281 283 +2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Adds a new scripts/release.sh automation script to codify the ORAS CLI release process into repeatable phases, and exposes those phases via make targets for convenience.
Changes:
- Added
scripts/release.shimplementingprep,tag,validate, andpublishrelease phases (with--dry-runsupport). - Added Makefile targets (
release-prep,release-tag,release-validate,release-publish) to invoke the script.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 9 comments.
| File | Description |
|---|---|
scripts/release.sh |
New bash script that automates version bump PR creation, tagging, CI/artifact validation, and publishing/signing steps. |
Makefile |
Adds convenience targets to run the release script phases via make. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
sabre1041
left a comment
There was a problem hiding this comment.
Overall looks really good. one small comment
Signed-off-by: Terry Howe <terrylhowe@gmail.com>
- Extract check_prerequisites() as shared function called from both do_prep and do_tag, ensuring GPG/gh/remote are validated before tagging - Add dirty working tree guard in do_prep before creating branch - Add portable checksum verification: prefer sha256sum over shasum with fallback and fatal error if neither is available - Use make SHELL=/bin/bash sign to avoid POSIX brace glob issue - Fix .asc upload to avoid glob expansion in dry-run mode - Fix snap workflow: use release-snap.yml with required version and isStable fields, pass --ref for correct trigger Signed-off-by: Terry Howe <terrylhowe@gmail.com>
Signed-off-by: Terry Howe <terrylhowe@gmail.com>
- Replace make fetch-dist with gh release download in validate phase so artifact fetching works against draft releases (curl on the public /releases/download/ URL returns 404 for drafts) - Add ORAS_REPO variable to Makefile so the repo is not hardcoded - Add gh CLI prerequisite check to fetch-dist target with install URL Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Terry Howe <terrylhowe@gmail.com>
- Replace make sign with a direct gpg loop covering all artifact types
including .zip (make sign only covered *.{gz,txt})
- Fail immediately if any gpg signing fails instead of swallowing errors
- Scope verify and upload globs to oras_<version>_* to avoid picking up
leftover files from prior releases
- Add --clobber to gh release upload so publish is safely retryable
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Terry Howe <terrylhowe@gmail.com>
Bash arithmetic (( expr )) exits with code 1 when the expression evaluates to 0. Post-increment (( n++ )) returns the old value, so the first increment from 0 to 1 silently kills the script under set -euo pipefail. Use $(( n + 1 )) assignment instead. Affected: attempt counter in validate and sig_count in publish. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Terry Howe <terrylhowe@gmail.com>
gpg consumes stdin during signing, leaving confirm's read at EOF which silently treats the response as empty (N) and aborts. Reading from /dev/tty ensures interactive prompts always reach the terminal. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Terry Howe <terrylhowe@gmail.com>
- Remove all confirm() calls and the confirm function itself; the script now runs non-interactively without pausing for user input - Replace the branch warning in prep with a hard failure: the current branch must be 'main' or 'release-X.Y' where X.Y matches the major.minor of the version being released (e.g. v1.3.2 requires main or release-1.3) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Terry Howe <terrylhowe@gmail.com>
validate and publish now read the version from internal/version/version.go when no version argument is supplied, so running just 'scripts/release.sh validate' or 'scripts/release.sh publish' works from the release branch without repeating the version string. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Terry Howe <terrylhowe@gmail.com>
When running prep from 'main', the version's major.minor must match MAIN_RELEASE_VERSION (default 2.0). This prevents accidentally cutting a 1.x patch release from main. Override with ORAS_MAIN_RELEASE_VERSION when the next main-branch series changes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Terry Howe <terrylhowe@gmail.com>
…N from validate/publish make targets - Remove redundant *Changelog:* line from the publish Slack announcement (it was the same URL as *Release:*) - Drop $(VERSION) from release-validate and release-publish Makefile targets since the script now reads the version from version.go Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Terry Howe <terrylhowe@gmail.com>
… docs - Auto-detect the canonical oras-project/oras remote by URL instead of assuming it is named 'upstream'; ORAS_REMOTE still overrides. - Target the release branch the PR is cut from (main or release-X.Y) so patch-release PRs no longer always target main. - Match the documented vote requirement (super-majority of ORAS maintainer approval) instead of the unspecified 72h / 3-binding-vote / veto rules. Signed-off-by: Terry Howe <terrylhowe@gmail.com>
Match the documented release note: use the full 40-char GPG fingerprint and attribute the signer via their GitHub handle (from the authenticated gh user), linking to their key at github.com/<handle>.gpg. Falls back gracefully when the handle cannot be resolved. Signed-off-by: Terry Howe <terrylhowe@gmail.com>
parse_global_flags ran inside a command substitution, so DRY_RUN=true was set only in the subshell and lost. --dry-run was silently ignored and prep ran for real (creating branches/PRs). Parse flags into a POSITIONAL_ARGS global in the current shell instead, so DRY_RUN sticks. Also point the release vote message at the #oras-maintainers Slack channel. Signed-off-by: Terry Howe <terrylhowe@gmail.com>
Signed-off-by: Terry Howe <terrylhowe@gmail.com>
Signed-off-by: Terry Howe <terrylhowe@gmail.com>
ea94983 to
fc91d0e
Compare
Five corrections, mostly from running the v1.3.4 release by hand: - publish no longer re-signs the artifacts. .goreleaser.yml now carries a "signs" block, so release-github.yml signs everything in CI with the ORAS project release key and the .asc files ship with the release. Signing locally produced signatures from whichever key gpg defaults to and uploaded them with --clobber, replacing the project key's signatures. publish now verifies the downloaded signatures against the project key instead, importing it from KEYS when it is missing from the keyring. - the Verification note recorded the wrong fingerprint. It read the first fpr: line out of the local keyring, which is not necessarily the key gpg signed with and is never the project key. It now names the project key, and is skipped when the notes already carry a Verification section. - check_prerequisites demanded a GPG secret key, but "git tag -s" honors gpg.format, which may be ssh or x509. The check both rejected maintainers who sign with SSH and passed maintainers whose GPG key git would never reach for. Signing is now checked separately, against the configured format, by the two phases that actually sign. - prep's in-place sed on the version file ran unguarded, so --dry-run rewrote version.go. run() cannot wrap it, so it is guarded explicitly. - the main release series was hardcoded to 3.0, which rejected every 1.3.x release from main unless ORAS_MAIN_RELEASE_VERSION was set. It is now derived from the version file on the current branch, so it tracks the branch, and cutting a new minor from main is allowed. The environment variable still overrides it. Signed-off-by: Terry Howe <terrylhowe@gmail.com>
Summary
Adds
scripts/release.sh, a bash release automation script that codifies the manual steps from https://oras.land/community/release-process into four repeatable phases.Phases
prep <version>- Validates semver format, checksgh/gpgprerequisites, updatesinternal/version/version.go(sets Version, clears BuildMetadata), creates branchchore/release-v<version>, commits, pushes, creates a PR titled "bump: tag and release ORAS CLI v<version>" targetingmain(or the release branch for patches), and prints the commit SHA with a Slack vote template.tag <version> <sha>- Validates that the commit at the given SHA contains the correct version and cleared BuildMetadata, creates a signed git tagv<version>, pushes the tag, and creates a release branch (e.g.release-X.Y) for new minor versions (patch==0, no pre-release suffix).validate <version>- Polls therelease-ghcrandrelease-githubGitHub Actions workflows until they complete, runsmake fetch-distto download artifacts, verifies checksums withshasum, and tests thelinux/amd64binary reports the expected version.publish <version>- Runsmake signto GPG-sign artifacts, verifies all GPG signatures, uploads.ascfiles to the GitHub release, appends signing key verification instructions to release notes, publishes the release (--draft=false), triggers the snap workflow, cleans up_dist/, and prints a post-release Slack template.Features
--dry-runflag for safe testingORAS_REMOTEenv var to configure the upstream remote (default:upstream)Makefile Targets
Also adds convenience Makefile targets:
release-prep,release-tag,release-validate,release-publish.Test plan
scripts/release.sh --helpto verify usage outputscripts/release.sh --dry-run prep 1.3.0to verify prep phase logicscripts/release.sh --dry-run tag 1.3.0 abc1234to verify tag phase logicscripts/release.sh --dry-run validate 1.3.0to verify validate phase logicscripts/release.sh --dry-run publish 1.3.0to verify publish phase logicmake helpshows the new release targets