@@ -67,10 +67,115 @@ jobs:
6767 echo "tag=$tag" >> "$GITHUB_OUTPUT"
6868 echo "Resolved release tag: $tag"
6969
70+ release-preflight :
71+ name : Release preflight
72+ needs : resolve-release
73+ runs-on : ubuntu-latest
74+ outputs :
75+ public_assets_present : ${{ steps.public_assets.outputs.present }}
76+ steps :
77+ - uses : actions/checkout@v4
78+ with :
79+ ref : ${{ needs.resolve-release.outputs.tag }}
80+
81+ - name : Inspect existing public release assets
82+ id : public_assets
83+ env :
84+ RELEASE_TAG : ${{ needs.resolve-release.outputs.tag }}
85+ run : |
86+ set -euo pipefail
87+ tag="${RELEASE_TAG#v}"
88+ release_repo="${DURABLE_WORKFLOW_REPO:-durable-workflow/cli}"
89+ evidence="release-preflight-public-assets-evidence.json"
90+ present="false"
91+ status="missing_or_incomplete"
92+ message="No complete public CLI asset set was found for ${tag}."
93+
94+ if DURABLE_WORKFLOW_RELEASE_ASSET_ATTEMPTS=1 DURABLE_WORKFLOW_RELEASE_ASSET_RETRY_SLEEP=0 \
95+ scripts/verify-public-release-assets.sh "$tag"; then
96+ present="true"
97+ status="present"
98+ message="A complete public CLI asset set is already downloadable for ${tag}."
99+ fi
100+
101+ echo "present=${present}" >> "$GITHUB_OUTPUT"
102+
103+ checked_at="$(date -u +%FT%TZ)"
104+ node - "$evidence" "$tag" "$release_repo" "$status" "$message" "$checked_at" "$present" <<'NODE'
105+ const fs = require('fs');
106+
107+ const [path, tag, repo, status, message, checkedAt, present] = process.argv.slice(2);
108+ const assets = [
109+ 'dw.phar',
110+ 'dw-linux-x86_64',
111+ 'dw-linux-aarch64',
112+ 'dw-macos-aarch64',
113+ 'dw-windows-x86_64.exe',
114+ 'dw.rb',
115+ 'install.sh',
116+ 'install.ps1',
117+ 'verify-release.sh',
118+ 'SHA256SUMS',
119+ ];
120+
121+ const urls = assets.map((asset) => ({
122+ name: asset,
123+ url: `https://github.com/${repo}/releases/download/${tag}/${asset}`,
124+ }));
125+
126+ fs.writeFileSync(path, `${JSON.stringify({
127+ schema: 'durable-workflow.cli.public-release-assets-preflight',
128+ tag,
129+ repository: repo,
130+ checked_at: checkedAt,
131+ outcome: status,
132+ message,
133+ purpose: present === 'true'
134+ ? 'existing-public-assets-rerun-gate'
135+ : 'pre-upload-public-asset-presence-check',
136+ installable_artifacts: {
137+ complete_public_asset_set: present === 'true',
138+ version: tag,
139+ },
140+ assets: urls,
141+ }, null, 2)}\n`);
142+ NODE
143+
144+ if [ -n "${GITHUB_STEP_SUMMARY:-}" ]; then
145+ {
146+ printf '## Public CLI asset preflight\n\n'
147+ printf '%s\n\n' "$message"
148+ if [ "$present" = "true" ]; then
149+ printf 'Because the complete public asset set already exists, the live docs release-audit gate runs before any rebuild or upload.\n'
150+ else
151+ printf 'The live docs release-audit gate will run after this release publishes and verifies the public download surface.\n'
152+ fi
153+ } >> "$GITHUB_STEP_SUMMARY"
154+ fi
155+
156+ - name : Require live docs release audit for existing public assets
157+ if : steps.public_assets.outputs.present == 'true'
158+ env :
159+ DOCS_RELEASE_AUDIT_ARTIFACT : cli
160+ DOCS_RELEASE_AUDIT_VERSION : ${{ needs.resolve-release.outputs.tag }}
161+ DOCS_RELEASE_AUDIT_EVIDENCE : docs-release-audit-evidence.json
162+ run : scripts/ci/check-docs-release-audit.sh
163+
164+ - name : Upload release preflight evidence
165+ if : always()
166+ uses : actions/upload-artifact@v4
167+ with :
168+ name : release-preflight-evidence
169+ path : |
170+ release-preflight-public-assets-evidence.json
171+ docs-release-audit-evidence.json
172+ if-no-files-found : warn
173+
70174 build-phar :
71175 name : Build PHAR
72- needs : resolve-release
176+ needs : [ resolve-release, release-preflight]
73177 runs-on : ubuntu-latest
178+ if : ${{ always() && needs.resolve-release.result == 'success' && needs.release-preflight.result == 'success' && needs.release-preflight.outputs.public_assets_present != 'true' }}
74179 outputs :
75180 phar-name : dw.phar
76181 steps :
@@ -130,7 +235,8 @@ jobs:
130235
131236 build-binary :
132237 name : Build ${{ matrix.name }}
133- needs : [resolve-release, build-phar]
238+ needs : [resolve-release, release-preflight, build-phar]
239+ if : ${{ always() && needs.resolve-release.result == 'success' && needs.release-preflight.result == 'success' && needs.release-preflight.outputs.public_assets_present != 'true' && needs.build-phar.result == 'success' }}
134240 strategy :
135241 fail-fast : false
136242 matrix :
@@ -248,7 +354,8 @@ jobs:
248354
249355 build-binary-windows :
250356 name : Build windows-x86_64
251- needs : [resolve-release, build-phar]
357+ needs : [resolve-release, release-preflight, build-phar]
358+ if : ${{ always() && needs.resolve-release.result == 'success' && needs.release-preflight.result == 'success' && needs.release-preflight.outputs.public_assets_present != 'true' && needs.build-phar.result == 'success' }}
252359 runs-on : windows-latest
253360 steps :
254361 - uses : actions/checkout@v4
@@ -399,9 +506,9 @@ jobs:
399506 # Every supported standalone platform must publish before the release
400507 # asset list, SHA256SUMS, installers, and public download endpoints are
401508 # considered complete.
402- needs : [resolve-release, build-phar, build-binary, build-binary-windows]
509+ needs : [resolve-release, release-preflight, build-phar, build-binary, build-binary-windows]
403510 runs-on : ubuntu-latest
404- if : ${{ always() && needs.resolve-release.result == 'success' && needs.build-phar.result == 'success' && needs.build-binary.result == 'success' && needs.build-binary-windows.result == 'success' }}
511+ if : ${{ always() && needs.resolve-release.result == 'success' && needs.release-preflight.result == 'success' && needs.release-preflight.outputs.public_assets_present != 'true' && needs. build-phar.result == 'success' && needs.build-binary.result == 'success' && needs.build-binary-windows.result == 'success' }}
405512 steps :
406513 - uses : actions/checkout@v4
407514 with :
@@ -562,6 +669,7 @@ jobs:
562669 printf ' "tag": "%s",\n' "$tag"
563670 printf ' "commit": "%s",\n' "$release_commit"
564671 printf ' "artifact_versions": {"cli": "%s"},\n' "$tag"
672+ printf ' "installable_artifacts": {"verified_public_downloads": true, "version": "%s"},\n' "$tag"
565673 printf ' "verified_at": "%s",\n' "$verified_at"
566674 printf ' "outcome": "pass",\n'
567675 printf ' "assets": [\n'
@@ -588,15 +696,19 @@ jobs:
588696 DURABLE_WORKFLOW_BIN_NAME=dw-release-check sh "$installer"
589697 "$install_dir/dw-release-check" --version
590698
591- - name : Upload public download evidence
592- uses : actions/upload-artifact@v4
593- with :
594- name : release-public-download-evidence
595- path : release-public-download-evidence.json
596- if-no-files-found : error
597-
598- - name : Require live docs release audit refresh
699+ - name : Verify live docs release audit after public downloads
599700 env :
600701 DOCS_RELEASE_AUDIT_ARTIFACT : cli
601702 DOCS_RELEASE_AUDIT_VERSION : ${{ needs.resolve-release.outputs.tag }}
703+ DOCS_RELEASE_AUDIT_EVIDENCE : docs-release-audit-evidence.json
602704 run : scripts/ci/check-docs-release-audit.sh
705+
706+ - name : Upload release evidence
707+ if : always()
708+ uses : actions/upload-artifact@v4
709+ with :
710+ name : release-evidence
711+ path : |
712+ release-public-download-evidence.json
713+ docs-release-audit-evidence.json
714+ if-no-files-found : warn
0 commit comments