-
Notifications
You must be signed in to change notification settings - Fork 14
DRIVERS-3601 Add a unified release workflow with semver tagging and GitHub Releases #115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
56a3fa6
Add next-version.sh to compute the next release version from tags
blink1073 faafeea
Add bump-major-version.sh to update version.txt on major releases
blink1073 84164d0
Run release script tests in CI
blink1073 e2fd785
Add release workflow for patch/minor/major version bumps
blink1073 a8c63ee
Fix release.yml v3 tag race and surface next-version diagnostics
blink1073 60edc5e
Replace update-action-tag workflow with the release workflow
blink1073 982c7d9
Rename shell-script test job to test-release-scripts
blink1073 9d8986f
Pin actions/checkout and actions/create-github-app-token to commit SHAs
blink1073 e820b8b
Use exact version numbers in SHA-pin comments
blink1073 fef4e09
Fix release.yml v3 tag race and surface next-version diagnostics
blink1073 424b3ab
Remove bootstrap-behavior doc note, covered by this ticket's first re…
blink1073 704f77f
Merge remote-tracking branch 'upstream/main' into actual-version
blink1073 079eb5a
Merge remote-tracking branch 'upstream/main' into actual-version
blink1073 8695d04
Tighten prose in CONTRIBUTING.md and README.md
blink1073 b64722a
Update .github/workflows/release.yml
blink1073 ace2ef0
Direct the floating-tag retirement warning to open a PR
blink1073 dadbe9e
Serialize releases, gate major bump on actual change, drop auto-boots…
blink1073 8854f6e
Remove the no-semver-tag guard; the first tag is created manually
blink1073 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| VERSION="${1:?Usage: bump-major-version.sh <version> [version_file]}" | ||
| VERSION_FILE="${2:-.github/workflows/version.txt}" | ||
| MAJOR="${VERSION%%.*}" | ||
|
|
||
| echo "$MAJOR" > "$VERSION_FILE" |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| BUMP_MAJOR_SH="$SCRIPT_DIR/bump-major-version.sh" | ||
| FAILURES=0 | ||
|
|
||
| assert_eq() { | ||
| local description="$1" expected="$2" actual="$3" | ||
| if [ "$expected" != "$actual" ]; then | ||
| echo "FAIL: $description (expected '$expected', got '$actual')" >&2 | ||
| FAILURES=$((FAILURES + 1)) | ||
| else | ||
| echo "PASS: $description" | ||
| fi | ||
| } | ||
|
|
||
| # Test: writes the major version number to the given file | ||
| tmp_file=$(mktemp) | ||
| bash "$BUMP_MAJOR_SH" "4.0.0" "$tmp_file" | ||
| assert_eq "writes major version" "4" "$(cat "$tmp_file")" | ||
| rm -f "$tmp_file" | ||
|
|
||
| # Test: multi-digit major version | ||
| tmp_file=$(mktemp) | ||
| bash "$BUMP_MAJOR_SH" "12.3.4" "$tmp_file" | ||
| assert_eq "writes multi-digit major version" "12" "$(cat "$tmp_file")" | ||
| rm -f "$tmp_file" | ||
|
|
||
| # Test: missing version argument fails | ||
| if bash "$BUMP_MAJOR_SH" >/dev/null 2>&1; then | ||
| echo "FAIL: expected failure with no version argument" >&2 | ||
| FAILURES=$((FAILURES + 1)) | ||
| else | ||
| echo "PASS: fails with no version argument" | ||
| fi | ||
|
|
||
| if [ "$FAILURES" -gt 0 ]; then | ||
| echo "$FAILURES test(s) failed" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "All bump-major-version.sh tests passed" |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| BUMP="${1:?Usage: next-version.sh <patch|minor|major>}" | ||
|
|
||
| case "$BUMP" in | ||
| patch|minor|major) ;; | ||
| *) | ||
| echo "Unknown bump type: $BUMP" >&2 | ||
| exit 1 | ||
| ;; | ||
| esac | ||
|
|
||
| LATEST_SEMVER=$(git tag -l 'v[0-9]*.[0-9]*.[0-9]*' \ | ||
| | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' \ | ||
| | sed 's/^v//' \ | ||
| | sort -t. -k1,1n -k2,2n -k3,3n \ | ||
| | tail -1) | ||
|
|
||
| MAJOR=$(echo "$LATEST_SEMVER" | cut -d. -f1) | ||
| MINOR=$(echo "$LATEST_SEMVER" | cut -d. -f2) | ||
| PATCH=$(echo "$LATEST_SEMVER" | cut -d. -f3) | ||
| PREVIOUS_MAJOR="$MAJOR" | ||
|
|
||
| case "$BUMP" in | ||
| major) | ||
| MAJOR=$((MAJOR + 1)) | ||
| MINOR=0 | ||
| PATCH=0 | ||
| ;; | ||
| minor) | ||
| MINOR=$((MINOR + 1)) | ||
| PATCH=0 | ||
| ;; | ||
| patch) | ||
| PATCH=$((PATCH + 1)) | ||
| ;; | ||
| esac | ||
|
|
||
| if [ "$MAJOR" != "$PREVIOUS_MAJOR" ]; then | ||
| MAJOR_BUMPED=true | ||
| else | ||
| MAJOR_BUMPED=false | ||
| fi | ||
|
|
||
| NEXT_VERSION="${MAJOR}.${MINOR}.${PATCH}" | ||
|
|
||
| if [ "$MAJOR" = "3" ]; then | ||
| IS_V3=true | ||
| else | ||
| IS_V3=false | ||
| fi | ||
|
|
||
| echo "NEXT_VERSION=${NEXT_VERSION}" | ||
| echo "IS_V3=${IS_V3}" | ||
| echo "MAJOR_BUMPED=${MAJOR_BUMPED}" |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| NEXT_VERSION_SH="$SCRIPT_DIR/next-version.sh" | ||
| FAILURES=0 | ||
|
|
||
| assert_eq() { | ||
| local description="$1" expected="$2" actual="$3" | ||
| if [ "$expected" != "$actual" ]; then | ||
| echo "FAIL: $description (expected '$expected', got '$actual')" >&2 | ||
| FAILURES=$((FAILURES + 1)) | ||
| else | ||
| echo "PASS: $description" | ||
| fi | ||
| } | ||
|
|
||
| new_temp_repo() { | ||
| local tmp | ||
| tmp=$(mktemp -d) | ||
| git init -q "$tmp" | ||
| git -C "$tmp" config user.email "test@example.com" | ||
| git -C "$tmp" config user.name "Test" | ||
| git -C "$tmp" commit -q --allow-empty -m "init" | ||
| echo "$tmp" | ||
| } | ||
|
|
||
| # Test: patch bump from full semver tag | ||
| repo=$(new_temp_repo) | ||
| git -C "$repo" tag v3.2.1 | ||
| OUTPUT=$(cd "$repo" && bash "$NEXT_VERSION_SH" patch) | ||
| assert_eq "patch bump" "$(printf 'NEXT_VERSION=3.2.2\nIS_V3=true\nMAJOR_BUMPED=false')" "$OUTPUT" | ||
| rm -rf "$repo" | ||
|
|
||
| # Test: minor bump resets patch | ||
| repo=$(new_temp_repo) | ||
| git -C "$repo" tag v3.2.1 | ||
| OUTPUT=$(cd "$repo" && bash "$NEXT_VERSION_SH" minor) | ||
| assert_eq "minor bump resets patch" "$(printf 'NEXT_VERSION=3.3.0\nIS_V3=true\nMAJOR_BUMPED=false')" "$OUTPUT" | ||
| rm -rf "$repo" | ||
|
|
||
| # Test: major bump resets minor/patch, flips IS_V3 to false, and reports a major bump | ||
| repo=$(new_temp_repo) | ||
| git -C "$repo" tag v3.2.1 | ||
| OUTPUT=$(cd "$repo" && bash "$NEXT_VERSION_SH" major) | ||
| assert_eq "major bump resets minor/patch" "$(printf 'NEXT_VERSION=4.0.0\nIS_V3=false\nMAJOR_BUMPED=true')" "$OUTPUT" | ||
| rm -rf "$repo" | ||
|
|
||
| # Test: a full semver tag takes priority over an existing floating tag | ||
| repo=$(new_temp_repo) | ||
| git -C "$repo" tag v3 | ||
| git -C "$repo" tag v3.2.1 | ||
| OUTPUT=$(cd "$repo" && bash "$NEXT_VERSION_SH" patch) | ||
| assert_eq "full semver tag wins over floating tag" "$(printf 'NEXT_VERSION=3.2.2\nIS_V3=true\nMAJOR_BUMPED=false')" "$OUTPUT" | ||
| rm -rf "$repo" | ||
|
|
||
| # Test: numeric sort, not lexicographic (v3.10.0 > v3.2.1) | ||
| repo=$(new_temp_repo) | ||
| git -C "$repo" tag v3.2.1 | ||
| git -C "$repo" tag v3.10.0 | ||
| OUTPUT=$(cd "$repo" && bash "$NEXT_VERSION_SH" patch) | ||
| assert_eq "numeric sort picks v3.10.0 over v3.2.1" "$(printf 'NEXT_VERSION=3.10.1\nIS_V3=true\nMAJOR_BUMPED=false')" "$OUTPUT" | ||
| rm -rf "$repo" | ||
|
|
||
| # Test: invalid bump type is rejected | ||
| repo=$(new_temp_repo) | ||
| git -C "$repo" tag v3.2.1 | ||
| if (cd "$repo" && bash "$NEXT_VERSION_SH" bogus) >/dev/null 2>&1; then | ||
| echo "FAIL: expected failure for invalid bump type" >&2 | ||
| FAILURES=$((FAILURES + 1)) | ||
| else | ||
| echo "PASS: rejects invalid bump type" | ||
| fi | ||
| rm -rf "$repo" | ||
|
|
||
| if [ "$FAILURES" -gt 0 ]; then | ||
| echo "$FAILURES test(s) failed" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "All next-version.sh tests passed" |
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,129 @@ | ||
| name: Release | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| bump: | ||
| description: Version part to bump | ||
| required: true | ||
| type: choice | ||
| options: | ||
| - patch | ||
| - minor | ||
| - major | ||
| dry_run: | ||
| description: Whether this is a dry run | ||
| required: true | ||
| type: boolean | ||
| default: true | ||
|
|
||
| concurrency: | ||
| group: release | ||
| cancel-in-progress: false | ||
|
|
||
| jobs: | ||
| release: | ||
| name: Release | ||
| runs-on: ubuntu-latest | ||
| environment: release | ||
| if: github.ref == 'refs/heads/main' | ||
| permissions: | ||
| contents: write | ||
| id-token: write | ||
|
|
||
| steps: | ||
| - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | ||
| id: app-token | ||
| with: | ||
| app-id: ${{ vars.APP_ID }} | ||
| private-key: ${{ secrets.APP_PRIVATE_KEY }} | ||
| permission-contents: write | ||
|
|
||
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | ||
| with: | ||
| token: ${{ steps.app-token.outputs.token }} | ||
| fetch-depth: 0 | ||
| # Needed to push the tag and version bump commit in later steps. | ||
| persist-credentials: true | ||
|
|
||
| - name: Setup | ||
| uses: $/setup | ||
| with: | ||
| aws_role_arn: ${{ secrets.AWS_ROLE_ARN }} | ||
| aws_region_name: ${{ vars.AWS_REGION_NAME }} | ||
| aws_secret_id: ${{ secrets.AWS_SECRET_ID }} | ||
|
|
||
| - name: Determine next version | ||
| shell: bash | ||
| run: | | ||
| set +e | ||
| bash .github/scripts/next-version.sh "${{ inputs.bump }}" > /tmp/next-version.out 2> /tmp/next-version.err | ||
| STATUS=$? | ||
| set -e | ||
| if [ -s /tmp/next-version.err ]; then | ||
| cat /tmp/next-version.err | ||
| cat /tmp/next-version.err >> "$GITHUB_STEP_SUMMARY" | ||
| fi | ||
| if [ "$STATUS" -ne 0 ]; then | ||
| exit "$STATUS" | ||
| fi | ||
| cat /tmp/next-version.out >> "$GITHUB_ENV" | ||
|
|
||
| - name: Bump the major version file | ||
| if: env.MAJOR_BUMPED == 'true' | ||
| uses: $/bump-version | ||
| with: | ||
| version: ${{ env.NEXT_VERSION }} | ||
| version_bump_script: "bash .github/scripts/bump-major-version.sh" | ||
| push_commit: ${{ inputs.dry_run == false }} | ||
|
|
||
|
|
||
| - name: Tag the version | ||
| uses: $/tag-version | ||
| with: | ||
| version: ${{ env.NEXT_VERSION }} | ||
| tag_template: "v${VERSION}" | ||
| push_tag: ${{ inputs.dry_run == false }} | ||
|
|
||
| - name: Report floating v3 tag update (dry run) | ||
| if: env.IS_V3 == 'true' && inputs.dry_run == true | ||
| shell: bash | ||
| run: | | ||
| echo "[dry-run] Would move floating tag v3 to $(git rev-parse HEAD)" >> "$GITHUB_STEP_SUMMARY" | ||
|
|
||
| - name: Create a new signed v3 tag | ||
| if: env.IS_V3 == 'true' && inputs.dry_run == false | ||
| uses: $/git-sign | ||
| with: | ||
| command: git tag -a "v3" -f -m "Update tag" -s --local-user=${{ env.GPG_KEY_ID }} | ||
|
|
||
| - name: Push the v3 tag | ||
| if: env.IS_V3 == 'true' && inputs.dry_run == false | ||
| shell: bash -eux {0} | ||
| run: | | ||
| git push --force origin refs/tags/v3:refs/tags/v3 | ||
|
|
||
| - name: Warn about floating tag retirement | ||
| if: env.IS_V3 != 'true' | ||
| shell: bash | ||
| run: | | ||
| MESSAGE="Release v${NEXT_VERSION} no longer uses floating tags. Open a PR removing the floating-tag-update steps (Create/Push v3 tag, and this warning) from .github/workflows/release.yml." | ||
| echo "::warning::$MESSAGE" | ||
| echo "$MESSAGE" >> "$GITHUB_STEP_SUMMARY" | ||
|
GromNaN marked this conversation as resolved.
|
||
|
|
||
| - name: Create GitHub Release | ||
| if: inputs.dry_run == false | ||
| shell: bash | ||
| env: | ||
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | ||
| run: | | ||
| if ! gh release create "v${NEXT_VERSION}" --title "v${NEXT_VERSION}" --generate-notes; then | ||
| echo "::error::Tag v${NEXT_VERSION} was already pushed, but creating its GitHub Release failed. Run 'gh release create v${NEXT_VERSION} --generate-notes' manually to finish; re-running this workflow would compute a new version instead." | ||
| exit 1 | ||
| fi | ||
| echo "Created release v${NEXT_VERSION}" >> "$GITHUB_STEP_SUMMARY" | ||
|
|
||
| - name: Report release (dry run) | ||
| if: inputs.dry_run == true | ||
| shell: bash | ||
| run: | | ||
| echo "[dry-run] Would create tag v${NEXT_VERSION} and GitHub Release v${NEXT_VERSION}" >> "$GITHUB_STEP_SUMMARY" | ||
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.