Skip to content

Commit f98c313

Browse files
authored
fix(ci): validate the dispatch tag in release.yml (#71)
* fix(ci): validate the dispatch tag in release.yml Gap I introduced in #63, caught in review of the same port to hotdata-ibis (hotdata-dev/hotdata-ibis#44). publish.yml got a pre-checkout guard on the dispatch input; release.yml did not, despite needing it more. release.yml holds contents: write, and action-gh-release CREATES a tag when tag_name does not resolve to one. So an unvalidated `tag: main` checks out cleanly and then leaves refs/tags/main plus a release named for it, both needing manual cleanup. publish.yml at worst wastes a run. The push path is constrained by the v[0-9]* tag filter; the dispatch path had no constraint at all. Same guard and same strict form as publish.yml, so the input contract matches in both. sdk-python already had this -- its dispatch predates this work. * fix(ci): give publish.yml the same strict dispatch guard My description claimed parity between the two workflows and it was not true. In this repo publish.yml never gained a pre-checkout step -- #63 only switched its existing "Verify tag matches pyproject version" check to $TAG, which runs AFTER checkout and is looser (^v[0-9]). So `-f tag=v1.2` or `v1.2.3rc1` was accepted there and rejected in release.yml. Tightening publish.yml rather than loosening release.yml, since release.sh only ever produces X.Y.Z -- it enforces ^[0-9]+\.[0-9]+\.[0-9]+$ on explicit versions, so the strict form is the correct contract. Both workflows now validate the same input the same way, before fetching an arbitrary ref. The post-checkout version match stays: it catches a tag that is well-formed but does not match pyproject.
1 parent 14bcf5d commit f98c313

2 files changed

Lines changed: 33 additions & 0 deletions

File tree

‎.github/workflows/publish.yml‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,21 @@ jobs:
3131
# The tag being released, whether it arrived by push or by dispatch.
3232
TAG: ${{ inputs.tag || github.ref_name }}
3333
steps:
34+
# Before checkout, because checkout resolves the input as an arbitrary ref:
35+
# a branch or SHA is fetched first and only rejected later by the version
36+
# match below, which is also looser (`^v[0-9]`). Strict here so the dispatch
37+
# contract matches release.yml — release.sh only ever produces X.Y.Z.
38+
- name: Validate release tag format
39+
if: github.event_name == 'workflow_dispatch'
40+
env:
41+
INPUT_TAG: ${{ inputs.tag }}
42+
run: |
43+
set -euo pipefail
44+
if [[ ! "$INPUT_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
45+
echo "tag must look like vX.Y.Z, got: $INPUT_TAG" >&2
46+
exit 1
47+
fi
48+
3449
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
3550
with:
3651
ref: ${{ inputs.tag || github.ref_name }}

‎.github/workflows/release.yml‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,24 @@ jobs:
2525
# The tag being released, whether it arrived by push or by dispatch.
2626
TAG: ${{ inputs.tag || github.ref_name }}
2727
steps:
28+
# Before checkout, because checkout resolves the input as an arbitrary ref
29+
# — and this workflow needs the guard more than publish.yml does. It holds
30+
# `contents: write`, and action-gh-release CREATES a tag when tag_name does
31+
# not resolve to one, so an unvalidated `tag: main` would check out cleanly
32+
# and leave refs/tags/main plus a release named for it. The push path is
33+
# constrained by the v[0-9]* filter; the dispatch path was not constrained
34+
# at all.
35+
- name: Validate release tag format
36+
if: github.event_name == 'workflow_dispatch'
37+
env:
38+
INPUT_TAG: ${{ inputs.tag }}
39+
run: |
40+
set -euo pipefail
41+
if [[ ! "$INPUT_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
42+
echo "tag must look like vX.Y.Z, got: $INPUT_TAG" >&2
43+
exit 1
44+
fi
45+
2846
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
2947
with:
3048
ref: ${{ inputs.tag || github.ref_name }}

0 commit comments

Comments
 (0)