11name : release
22
33on :
4- push :
4+ # Release only after the CI workflow succeeds on main so Docker publishes
5+ # are tied to a CI-validated commit instead of any direct branch push.
6+ workflow_run :
7+ workflows :
8+ - ci
9+ types :
10+ - completed
511 branches :
612 - main
713 workflow_dispatch :
@@ -10,11 +16,59 @@ permissions:
1016 contents : read
1117
1218concurrency :
13- group : release-${{ github.ref }}
19+ group : release-${{ github.event.workflow_run.head_sha || github.sha }}
1420 cancel-in-progress : true
1521
1622jobs :
23+ guard :
24+ runs-on : ubuntu-latest
25+ outputs :
26+ target_sha : ${{ steps.resolve.outputs.target_sha }}
27+ target_ref : ${{ steps.resolve.outputs.target_ref }}
28+ steps :
29+ - name : Validate release trigger and resolve target
30+ id : resolve
31+ env :
32+ EVENT_NAME : ${{ github.event_name }}
33+ WORKFLOW_CONCLUSION : ${{ github.event.workflow_run.conclusion }}
34+ WORKFLOW_HEAD_SHA : ${{ github.event.workflow_run.head_sha }}
35+ WORKFLOW_HEAD_BRANCH : ${{ github.event.workflow_run.head_branch }}
36+ GITHUB_REF_VALUE : ${{ github.ref }}
37+ GITHUB_SHA_VALUE : ${{ github.sha }}
38+ run : |
39+ if [ "$EVENT_NAME" = "workflow_run" ]; then
40+ if [ "$WORKFLOW_CONCLUSION" != "success" ]; then
41+ echo "Release requires successful CI on main; got conclusion=$WORKFLOW_CONCLUSION" >&2
42+ exit 1
43+ fi
44+
45+ if [ -z "$WORKFLOW_HEAD_SHA" ] || [ -z "$WORKFLOW_HEAD_BRANCH" ]; then
46+ echo "workflow_run payload missing head SHA or branch" >&2
47+ exit 1
48+ fi
49+
50+ echo "target_sha=$WORKFLOW_HEAD_SHA" >> "$GITHUB_OUTPUT"
51+ echo "target_ref=refs/heads/$WORKFLOW_HEAD_BRANCH" >> "$GITHUB_OUTPUT"
52+ exit 0
53+ fi
54+
55+ if [ "$EVENT_NAME" = "workflow_dispatch" ]; then
56+ if [ "$GITHUB_REF_VALUE" != "refs/heads/main" ]; then
57+ echo "Manual release is restricted to refs/heads/main; got $GITHUB_REF_VALUE" >&2
58+ exit 1
59+ fi
60+
61+ echo "target_sha=$GITHUB_SHA_VALUE" >> "$GITHUB_OUTPUT"
62+ echo "target_ref=$GITHUB_REF_VALUE" >> "$GITHUB_OUTPUT"
63+ exit 0
64+ fi
65+
66+ echo "Unsupported event: $EVENT_NAME" >&2
67+ exit 1
68+
1769 release :
70+ needs :
71+ - guard
1872 runs-on : ubuntu-latest
1973 permissions :
2074 contents : write
2579 steps :
2680 - uses : actions/checkout@v6
2781 with :
82+ ref : ${{ needs.guard.outputs.target_sha }}
2883 fetch-depth : 0
2984
3085 - name : Run release-please
@@ -54,15 +109,17 @@ jobs:
54109 docker-publish :
55110 if : needs.release.outputs.release_created == 'true'
56111 needs :
112+ - guard
57113 - release
58114 runs-on : ubuntu-latest
59115 env :
60116 IMAGE_NAME : html2rss/web
61- TAG_SHA : ${{ github.sha }}
117+ TAG_SHA : ${{ needs.guard.outputs.target_sha }}
62118 RELEASE_TAG : ${{ needs.release.outputs.tag_name }}
63119 steps :
64120 - uses : actions/checkout@v6
65121 with :
122+ ref : ${{ needs.guard.outputs.target_sha }}
66123 fetch-depth : 0
67124
68125 - name : Setup pnpm
@@ -135,7 +192,7 @@ jobs:
135192 tags : ${{ steps.tags.outputs.tags }}
136193 build-args : |
137194 BUILD_TAG=${{ env.RELEASE_VERSION }}
138- GIT_SHA=${{ github.sha }}
195+ GIT_SHA=${{ needs.guard.outputs.target_sha }}
139196 platforms : linux/amd64,linux/arm64
140197 cache-from : type=local,src=/tmp/.buildx-cache
141198 cache-to : type=local,dest=/tmp/.buildx-cache-new
@@ -145,7 +202,7 @@ jobs:
145202 org.opencontainers.image.created=${{ env.TIMESTAMP_ISO }}
146203 org.opencontainers.image.description=Generates RSS feeds of any website & serves to the web!
147204 org.opencontainers.image.ref.name=${{ env.RELEASE_TAG }}
148- org.opencontainers.image.revision=${{ github.sha }}
205+ org.opencontainers.image.revision=${{ needs.guard.outputs.target_sha }}
149206 org.opencontainers.image.source=https://github.com/${{ github.repository }}
150207 org.opencontainers.image.title=html2rss-web
151208 org.opencontainers.image.url=https://github.com/${{ github.repository }}/releases/tag/${{ env.RELEASE_TAG }}
0 commit comments