-
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
Open
blink1073
wants to merge
16
commits into
main
Choose a base branch
from
actual-version
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
16 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 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,66 @@ | ||
| #!/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 || true) | ||
|
|
||
| if [ -n "$LATEST_SEMVER" ]; then | ||
| MAJOR=$(echo "$LATEST_SEMVER" | cut -d. -f1) | ||
| MINOR=$(echo "$LATEST_SEMVER" | cut -d. -f2) | ||
| PATCH=$(echo "$LATEST_SEMVER" | cut -d. -f3) | ||
|
|
||
| case "$BUMP" in | ||
| major) | ||
| MAJOR=$((MAJOR + 1)) | ||
| MINOR=0 | ||
| PATCH=0 | ||
| ;; | ||
| minor) | ||
| MINOR=$((MINOR + 1)) | ||
| PATCH=0 | ||
| ;; | ||
| patch) | ||
| PATCH=$((PATCH + 1)) | ||
| ;; | ||
| esac | ||
| else | ||
| LATEST_FLOATING=$(git tag -l 'v[0-9]*' \ | ||
| | grep -E '^v[0-9]+$' \ | ||
| | sed 's/^v//' \ | ||
| | sort -n \ | ||
| | tail -1 || true) | ||
|
|
||
| if [ -z "$LATEST_FLOATING" ]; then | ||
| echo "No version tags found (neither vX.Y.Z nor vN)." >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "No vX.Y.Z tag found; bootstrapping from floating tag v${LATEST_FLOATING}. Ignoring requested bump '${BUMP}'." >&2 | ||
| MAJOR="$LATEST_FLOATING" | ||
| MINOR=0 | ||
| PATCH=0 | ||
| 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}" |
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,98 @@ | ||
| #!/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: no tags at all -> non-zero exit | ||
| repo=$(new_temp_repo) | ||
| if (cd "$repo" && bash "$NEXT_VERSION_SH" patch) >/dev/null 2>&1; then | ||
| echo "FAIL: expected failure with no tags present" >&2 | ||
| FAILURES=$((FAILURES + 1)) | ||
| else | ||
| echo "PASS: fails with no tags present" | ||
| fi | ||
| rm -rf "$repo" | ||
|
|
||
| # Test: bootstrap from floating v3 tag, ignoring the requested bump | ||
| repo=$(new_temp_repo) | ||
| git -C "$repo" tag v3 | ||
| OUTPUT=$(cd "$repo" && bash "$NEXT_VERSION_SH" patch) | ||
| assert_eq "bootstrap ignores bump, uses floating major" "$(printf 'NEXT_VERSION=3.0.0\nIS_V3=true')" "$OUTPUT" | ||
| rm -rf "$repo" | ||
|
|
||
| # 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')" "$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')" "$OUTPUT" | ||
| rm -rf "$repo" | ||
|
|
||
| # Test: major bump resets minor/patch and flips IS_V3 to false | ||
| 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')" "$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')" "$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')" "$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,122 @@ | ||
| 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 | ||
|
|
||
| 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: inputs.bump == 'major' | ||
| 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" | ||
|
|
||
| - name: Create GitHub Release | ||
| if: inputs.dry_run == false | ||
| shell: bash | ||
| env: | ||
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | ||
| run: | | ||
| gh release create "v${NEXT_VERSION}" --title "v${NEXT_VERSION}" --generate-notes | ||
| 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" | ||
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This message may only be read by the person who creates the release. That doesn't seem very useful to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, it is mean a a signal for the releaser to remove the floating tag handling in the code.