Set up release versioning#17
Conversation
There was a problem hiding this comment.
Pull request overview
This PR refactors and extends the repository’s release automation by introducing reusable GitHub Actions workflows for version bumping and release creation, adding entrypoint workflows for automated/manual releases, and adding a helper script to synchronize manifest.json version fields.
Changes:
- Added reusable workflows for bumping the project version and creating a GitHub Release (including artifact build/upload/download).
- Added
publish.yaml(on push tomain) andmanual-release.yaml(workflow_dispatch) to orchestrate validate → bump → release. - Added
shell/scripts/sync-version.shto syncmanifest.jsonlatest/stablebased on a provided semver.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
shell/scripts/sync-version.sh |
New helper script to update manifest.json version fields. |
.github/workflows/validate.yaml |
Removes legacy validate entrypoint workflow. |
.github/workflows/publish.yaml |
New push-to-main release pipeline using reusable workflows. |
.github/workflows/manual-release.yaml |
New manually-triggered release pipeline with optional validation. |
.github/workflows/_security.yaml |
Ensures submodules/env initialization; changes govulncheck install method. |
.github/workflows/_lint.yaml |
Ensures submodules/env initialization for lint job. |
.github/workflows/_coverage.yaml |
Ensures submodules/env initialization for test/coverage job. |
.github/workflows/_bump_version.yaml |
New reusable workflow to compute, sync, commit, tag, and push version bumps. |
.github/workflows/_create_release.yaml |
New reusable workflow to build/upload artifact and publish a GitHub Release. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| [[ $# -eq 0 ]] && log "$USAGE" && exit 1 | ||
|
|
||
| case "$1" in | ||
| -h|--help) log "$USAGE" && exit 0 ;; | ||
| -*) fatal "Unknown option: $1" && log "$USAGE" && exit 1 ;; | ||
| esac | ||
|
|
There was a problem hiding this comment.
parse_args only validates the zero-arg case; if more than one positional argument is provided, the extras are silently ignored. It’s safer to enforce exactly one <version> argument (after option handling) and treat anything else as a usage error so mistakes don’t go unnoticed in CI or local runs.
| [[ $# -eq 0 ]] && log "$USAGE" && exit 1 | |
| case "$1" in | |
| -h|--help) log "$USAGE" && exit 0 ;; | |
| -*) fatal "Unknown option: $1" && log "$USAGE" && exit 1 ;; | |
| esac | |
| if [[ $# -eq 0 ]]; then | |
| log "$USAGE" | |
| exit 1 | |
| fi | |
| case "$1" in | |
| -h|--help) | |
| log "$USAGE" | |
| exit 0 | |
| ;; | |
| -*) | |
| fatal "Unknown option: $1" | |
| log "$USAGE" | |
| exit 1 | |
| ;; | |
| esac | |
| if [[ $# -ne 1 ]]; then | |
| fatal "Expected exactly one <version> argument, got: $#" | |
| log "$USAGE" | |
| exit 1 | |
| fi |
| - name: Upload artifact | ||
| uses: actions/upload-artifact@v6 | ||
| with: | ||
| name: violet-linux-amd64 | ||
| path: violet | ||
|
|
||
| release: | ||
| name: release | ||
| runs-on: ubuntu-24.04 | ||
| needs: build | ||
| permissions: | ||
| contents: write | ||
| outputs: | ||
| tag: ${{ steps.publish.outputs.tag }} | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| steps: | ||
| - name: Generate Auth Token | ||
| id: generate-token | ||
| uses: actions/create-github-app-token@v2 | ||
| with: | ||
| app-id: ${{ secrets.RELEASE_BOT_APP_ID }} | ||
| private-key: ${{ secrets.RELEASE_BOT_APP_PRIVATE_KEY }} | ||
|
|
||
| - uses: actions/checkout@v6 | ||
| with: | ||
| ref: main | ||
| token: ${{ steps.generate-token.outputs.token }} | ||
| submodules: recursive | ||
|
|
||
| - uses: ./shell/.shock/actions/envrc | ||
|
|
||
| - name: Download artifact | ||
| uses: actions/download-artifact@v7 | ||
| with: | ||
| name: violet-linux-amd64 | ||
|
|
There was a problem hiding this comment.
This workflow pins actions/upload-artifact@v6 and actions/download-artifact@v7, while the rest of the repo workflows use actions/upload-artifact@v4. If those major versions aren’t intentionally required here, consider standardizing on the same major versions across workflows to avoid unexpected behavior differences (and potential action-resolution failures if those majors aren’t available).
| - name: Download artifact | ||
| uses: actions/download-artifact@v7 | ||
| with: | ||
| name: violet-linux-amd64 | ||
|
|
||
| - name: Create GitHub Release | ||
| id: publish | ||
| run: | | ||
| TAG="v$(jq -r '.latest' manifest.json)" | ||
| echo "tag=$TAG" >> "$GITHUB_OUTPUT" | ||
| gh release create "$TAG" \ | ||
| --title "$TAG" \ | ||
| --generate-notes \ | ||
| violet |
There was a problem hiding this comment.
The downloaded artifact is unlikely to be available at ./violet as referenced by gh release create ... violet. actions/download-artifact typically extracts into a subdirectory named after the artifact (e.g. violet-linux-amd64/violet) unless you explicitly set a download path/merge behavior. Adjust the download step and/or the release asset path so the file you attach definitely matches the extracted location.
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| steps: | ||
| - name: Generate Auth Token | ||
| id: generate-token | ||
| uses: actions/create-github-app-token@v2 | ||
| with: | ||
| app-id: ${{ secrets.RELEASE_BOT_APP_ID }} | ||
| private-key: ${{ secrets.RELEASE_BOT_APP_PRIVATE_KEY }} | ||
|
|
||
| - uses: actions/checkout@v6 | ||
| with: | ||
| ref: main | ||
| token: ${{ steps.generate-token.outputs.token }} | ||
| submodules: recursive | ||
|
|
||
| - uses: ./shell/.shock/actions/envrc | ||
|
|
There was a problem hiding this comment.
gh release create is authenticated via GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}, but the caller workflows (publish.yaml, manual-release.yaml) don’t declare permissions: contents: write. If the repo’s default GITHUB_TOKEN permissions are read-only, this step will fail to create the release. Consider either (a) declaring explicit permissions in the caller workflows, or (b) using the generated GitHub App token for GH_TOKEN so the workflow doesn’t depend on GITHUB_TOKEN permissions.
| - uses: actions/checkout@v6 | ||
| with: | ||
| ref: main | ||
| submodules: recursive | ||
| - uses: ./shell/.shock/actions/envrc | ||
| - uses: actions/setup-go@v5 | ||
| with: | ||
| go-version-file: go.mod | ||
|
|
There was a problem hiding this comment.
Both jobs hardcode ref: main for checkout. That can make the release build non-deterministic if additional commits land on main while the workflow is running (you may build/ship a different commit than the one that was just version-bumped/tagged). Prefer checking out the exact SHA/tag produced by the bump step (e.g., pass it as an input/output between reusable workflows) to ensure the artifact matches the release tag.
| eval "${SHELLSHOCK_ENVRC:-}" | ||
|
|
||
| USAGE="$(cat <<EOF | ||
| Syncs the project manifest version fields. | ||
|
|
||
| Usage: sync-version.sh <version> | ||
|
|
||
| Arguments: | ||
| version The version to set as latest (must be valid semver). | ||
|
|
||
| Flags: | ||
| -h, --help Show this help text. | ||
| EOF | ||
| )" | ||
|
|
||
| import \ | ||
| "$PROJ/shell/.shock/lib/versions.api.sh" \ | ||
| "$PROJ/shell/.shock/lib/manifest.api.sh" |
There was a problem hiding this comment.
This script assumes the Shock environment has been initialized (e.g. SHELLSHOCK_ENVRC defines import and sets PROJ). If a user runs it outside that context, set -u will cause an immediate, unclear failure (e.g. PROJ: unbound variable / import: command not found). Add an explicit preflight check that required functions/vars are present and emit a clear error telling the user how to initialize/run the script.
This pull request introduces major improvements to the release automation and CI workflows by modularizing and enhancing the GitHub Actions configuration. The changes add reusable workflow files for version bumping and release creation, update existing workflows to use these new modules, and improve environment setup consistency and artifact handling. Additionally, a new shell script is included to synchronize version information in the project manifest, and several jobs now ensure submodules are checked out and the environment is properly initialized.
Release automation and workflow modularization:
_bump_version.yaml) and creating releases (_create_release.yaml), enabling standardized and maintainable release processes. [1] [2]manual-release.yaml,publish.yaml), both leveraging the new modular workflow components. [1] [2]validate.yamlworkflow, consolidating validation logic into reusable modules.Environment and build improvements:
envrcaction, improving reliability and reproducibility. [1] [2] [3]govulncheckin the security workflow to use a project-specific script for better control.Version synchronization:
shell/scripts/sync-version.sh, to reliably update version fields in the project manifest, supporting both release and pre-release versioning.