Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .github/workflows/pr-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ jobs:
- name: cargo clippy
run: cargo clippy --workspace --all-targets -- -D warnings

release-tag-validation:
name: release tag validation
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Check out repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false

- name: Test release tag resolver
run: scripts/test-resolve-release-tag.sh

test:
name: test (${{ matrix.toolchain }})
runs-on: ubuntu-latest
Expand Down
40 changes: 19 additions & 21 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,20 +78,19 @@ jobs:
contents: read
packages: write
steps:
- name: Check out workflow scripts
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false

- name: Resolve release tag
id: rel
env:
DISPATCH_TAG: ${{ inputs.docker_backfill_tag }}
RELEASE_TAG: ${{ needs.release-please.outputs.tag_name }}
run: |
set -euo pipefail
TAG="${DISPATCH_TAG:-$RELEASE_TAG}"
case "$TAG" in
v[0-9]*) ;;
*) echo "::error::'$TAG' does not look like a release tag (vX.Y.Z)"; exit 1 ;;
esac
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
scripts/resolve-release-tag.sh "${DISPATCH_TAG:-$RELEASE_TAG}"
# ghcr requires a lowercase repository path, and unlike metadata-action,
# buildx's `--output name=` does no lowercasing — a mixed-case owner
# makes the digest push fail with "invalid reference format".
Expand Down Expand Up @@ -173,22 +172,22 @@ jobs:
if: ${{ !cancelled() && needs.docker.result == 'success' }}
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Check out workflow scripts
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false

- name: Resolve release tag
id: rel
env:
DISPATCH_TAG: ${{ inputs.docker_backfill_tag }}
RELEASE_TAG: ${{ needs.release-please.outputs.tag_name }}
run: |
set -euo pipefail
TAG="${DISPATCH_TAG:-$RELEASE_TAG}"
case "$TAG" in
v[0-9]*) ;;
*) echo "::error::'$TAG' does not look like a release tag (vX.Y.Z)"; exit 1 ;;
esac
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
scripts/resolve-release-tag.sh "${DISPATCH_TAG:-$RELEASE_TAG}"

- name: Download digests
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
Expand Down Expand Up @@ -404,20 +403,19 @@ jobs:
contents: read
id-token: write # npm trusted publishing (OIDC) + provenance
steps:
- name: Check out workflow scripts
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false

- name: Resolve release tag
id: rel
env:
DISPATCH_TAG: ${{ inputs.npm_backfill_tag }}
RELEASE_TAG: ${{ needs.release-please.outputs.tag_name }}
run: |
set -euo pipefail
TAG="${DISPATCH_TAG:-$RELEASE_TAG}"
case "$TAG" in
v[0-9]*) ;;
*) echo "::error::'$TAG' does not look like a release tag (vX.Y.Z)"; exit 1 ;;
esac
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
scripts/resolve-release-tag.sh "${DISPATCH_TAG:-$RELEASE_TAG}"

- name: Checkout release tag
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
Expand Down
23 changes: 23 additions & 0 deletions scripts/resolve-release-tag.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -euo pipefail

tag="${1-}"
: "${GITHUB_OUTPUT:?GITHUB_OUTPUT must be set}"

case "$tag" in
""|*[!A-Za-z0-9._-]*)
printf '%s\n' "::error::release tag is empty or contains invalid characters" >&2
exit 1
;;
esac

case "$tag" in
v[0-9]*) ;;
*)
printf '%s\n' "::error::'$tag' does not look like a release tag (vX.Y.Z)" >&2
exit 1
;;
esac

printf '%s\n' "tag=$tag" >> "$GITHUB_OUTPUT"
printf '%s\n' "version=${tag#v}" >> "$GITHUB_OUTPUT"
46 changes: 46 additions & 0 deletions scripts/test-resolve-release-tag.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
set -euo pipefail

repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
resolver="$repo_root/scripts/resolve-release-tag.sh"
test_tmp="$(mktemp -d)"
trap 'rm -r -- "$test_tmp"' EXIT

valid_output="$test_tmp/valid-output"
GITHUB_OUTPUT="$valid_output" "$resolver" "v1.2.3"

expected_output="$test_tmp/expected-output"
printf '%s\n' "tag=v1.2.3" "version=1.2.3" > "$expected_output"
cmp "$expected_output" "$valid_output"

newline_output="$test_tmp/newline-output"
if GITHUB_OUTPUT="$newline_output" "$resolver" $'v1.2.3\nname=owned'; then
printf '%s\n' "newline-containing release tag unexpectedly passed" >&2
exit 1
fi
test ! -s "$newline_output"

empty_output="$test_tmp/empty-output"
if GITHUB_OUTPUT="$empty_output" "$resolver" ""; then
printf '%s\n' "empty release tag unexpectedly passed" >&2
exit 1
fi
test ! -s "$empty_output"
Comment thread
coderabbitai[bot] marked this conversation as resolved.

invalid_output="$test_tmp/invalid-output"
for invalid_tag in "v1.2.3 tag" "v1.2.3;name=owned" "release-1.2.3"; do
: > "$invalid_output"
if GITHUB_OUTPUT="$invalid_output" "$resolver" "$invalid_tag"; then
printf '%s\n' "invalid release tag unexpectedly passed: $invalid_tag" >&2
exit 1
fi
test ! -s "$invalid_output"
done

resolver_count="$(grep -c 'scripts/resolve-release-tag.sh' "$repo_root/.github/workflows/release.yml")"
if [[ "$resolver_count" -ne 3 ]]; then
printf '%s\n' "expected all 3 release tag steps to use the tested resolver; found $resolver_count" >&2
exit 1
fi

printf '%s\n' "release tag resolver tests passed"