1010 workflow_dispatch :
1111 inputs :
1212 tag :
13- description : " Pre-release tag to publish and qualify (e.g. v0.0.4-pre.1)"
14- required : true
13+ description : " Existing prerelease tag (e.g. v0.0.4-pre.1); omit to create the next candidate on this branch "
14+ required : false
1515 type : string
1616
1717permissions :
1818 contents : read
1919
2020jobs :
21+ resolve :
22+ name : Resolve Prerelease Tag
23+ runs-on : ubuntu-latest
24+ timeout-minutes : 5
25+ permissions :
26+ contents : write
27+ concurrency :
28+ group : release-prerelease-tags
29+ cancel-in-progress : false
30+ queue : max
31+ outputs :
32+ tag : ${{ steps.tag.outputs.tag }}
33+ source-sha : ${{ steps.tag.outputs.source_sha }}
34+ steps :
35+ - uses : actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
36+ with :
37+ fetch-depth : 0
38+ persist-credentials : false
39+
40+ - uses : astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
41+ with :
42+ version : " 0.10.12"
43+ python-version : " 3.13"
44+ enable-cache : false
45+
46+ - name : Resolve or create candidate tag
47+ id : tag
48+ env :
49+ GH_TOKEN : ${{ github.token }}
50+ RELEASE_TAG : ${{ inputs.tag }}
51+ EVENT_NAME : ${{ github.event_name }}
52+ REF_TYPE : ${{ github.ref_type }}
53+ REF_NAME : ${{ github.ref_name }}
54+ run : |
55+ set -euo pipefail
56+ tag="${RELEASE_TAG}"
57+ if [[ "${EVENT_NAME}" == "push" ]]; then
58+ tag="${REF_NAME}"
59+ fi
60+ if [[ -z "${tag}" ]]; then
61+ test "${REF_TYPE}" = branch
62+ tag=$(uv run --no-project python tasks/scripts/next-prerelease-tag.py)
63+ source_sha=$(git rev-parse HEAD)
64+ gh api --method POST "repos/${GITHUB_REPOSITORY}/git/refs" \
65+ -f "ref=refs/tags/${tag}" -f "sha=${source_sha}"
66+ else
67+ if [[ ! "${tag}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+-pre\.[1-9][0-9]*$ ]]; then
68+ echo "Unsupported prerelease tag: ${tag}" >&2
69+ exit 1
70+ fi
71+ source_sha=$(git rev-parse "refs/tags/${tag}^{commit}")
72+ fi
73+ {
74+ echo "tag=${tag}"
75+ echo "source_sha=${source_sha}"
76+ } >> "${GITHUB_OUTPUT}"
77+ {
78+ echo "## Prerelease candidate"
79+ echo "- Tag: \`${tag}\`"
80+ echo "- Source commit: \`${source_sha}\`"
81+ } >> "${GITHUB_STEP_SUMMARY}"
82+
2183 build :
2284 name : Build
85+ needs : resolve
2386 permissions :
2487 actions : read
2588 contents : read
2689 packages : write
2790 uses : ./.github/workflows/release-build.yml
2891 with :
29- release-tag : ${{ inputs.tag || github.ref_name }}
92+ release-tag : ${{ needs.resolve.outputs.tag }}
93+ expected-source-sha : ${{ needs.resolve.outputs.source-sha }}
3094 is-prerelease : true
3195 secrets :
3296 CACHIX_AUTH_TOKEN : ${{ secrets.CACHIX_AUTH_TOKEN }}
3397
3498 release-notes :
3599 name : Preview Release Notes
36- needs : build
100+ needs : [resolve, build]
37101 permissions :
38102 contents : read
39103 pull-requests : read
40104 uses : ./.github/workflows/release-notes.yml
41105 with :
42- release-tag : ${{ inputs.tag || github.ref_name }}
106+ release-tag : ${{ needs.resolve.outputs.tag }}
43107 advisory : true
44108 secrets :
45109 LLM_INFERENCE_API_KEY : ${{ secrets.LLM_INFERENCE_API_KEY }}
46110
47111 publish :
48112 name : Publish
49- needs : build
113+ needs : [resolve, build]
50114 permissions :
51115 actions : read
52116 contents : write
57121 artifact-metadata : write
58122 uses : ./.github/workflows/release-publish.yml
59123 with :
60- release-tag : ${{ inputs.tag || github.ref_name }}
124+ release-tag : ${{ needs.resolve.outputs.tag }}
61125 source-sha : ${{ needs.build.outputs.source_sha }}
62126 semver : ${{ needs.build.outputs.semver }}
63127 python-version : ${{ needs.build.outputs.python_version }}
68132
69133 qualify :
70134 name : Qualify
71- needs : build
135+ needs : [resolve, build]
72136 permissions :
73137 actions : read
74138 contents : read
77141 pull-requests : read
78142 uses : ./.github/workflows/release-qualification.yml
79143 with :
80- release-tag : ${{ inputs.tag || github.ref_name }}
144+ release-tag : ${{ needs.resolve.outputs.tag }}
81145 source-sha : ${{ needs.build.outputs.source_sha }}
82146 is-prerelease : true
83147 secrets :
86150
87151 notify-prerelease-success :
88152 name : Notify Prerelease Success
89- needs : [build, publish, qualify]
153+ needs : [resolve, build, publish, qualify]
90154 if : success()
91155 runs-on : ubuntu-latest
92156 timeout-minutes : 2
@@ -95,10 +159,10 @@ jobs:
95159 - name : Send Slack notification
96160 continue-on-error : true
97161 env :
98- RELEASE_TAG : ${{ inputs.tag || github.ref_name }}
162+ RELEASE_TAG : ${{ needs.resolve.outputs.tag }}
99163 SLACK_WEBHOOK_URL : ${{ secrets.SLACK_OPENSHELL_TRIAGE_WEBHOOK_URL }}
100164 RUN_URL : ${{ format('{0}/{1}/actions/runs/{2}/attempts/{3}', github.server_url, github.repository, github.run_id, github.run_attempt) }}
101- TAG_URL : ${{ format('{0}/{1}/tree/{2}', github.server_url, github.repository, inputs.tag || github.ref_name ) }}
165+ TAG_URL : ${{ format('{0}/{1}/tree/{2}', github.server_url, github.repository, needs.resolve.outputs.tag ) }}
102166 run : |
103167 set -euo pipefail
104168 if [[ -z "${SLACK_WEBHOOK_URL}" ]]; then
@@ -114,7 +178,7 @@ jobs:
114178
115179 notify-prerelease-failure :
116180 name : Notify Prerelease Failure
117- needs : [build, publish, qualify]
181+ needs : [resolve, build, publish, qualify]
118182 if : failure()
119183 runs-on : ubuntu-latest
120184 timeout-minutes : 2
@@ -127,7 +191,7 @@ jobs:
127191 - name : Send Slack notification
128192 continue-on-error : true
129193 env :
130- RELEASE_TAG : ${{ inputs.tag || github.ref_name }}
194+ RELEASE_TAG : ${{ needs.resolve.outputs.tag || inputs.tag || github.ref_name }}
131195 PUBLICATION_RESULT : ${{ needs.publish.result }}
132196 SLACK_WEBHOOK_URL : ${{ secrets.SLACK_OPENSHELL_TRIAGE_WEBHOOK_URL }}
133197 SLACK_MENTION : ${{ secrets.SLACK_OPENSHELL_TRIAGE_MENTION }}
0 commit comments