Skip to content

Commit 0f5b4f0

Browse files
ci(release): reuse the promoted prerelease's release notes preview (#4754)
* ci(release): reuse the promoted prerelease's release notes preview Stable releases now publish the selected prerelease's release-notes artifact with the prerelease tag replaced by the stable tag. Release falls back to generating notes when the preview is missing, expired, or malformed, or when dispatched with regenerate-notes=true. The selection script exposes the qualified Pre-release run ID for the download. Closes #4753 Signed-off-by: Matthew Grossman <mgrossman@nvidia.com> * ci(release): reuse release notes from the promotion job Download and retag the preview in Select Qualified Prerelease, which already knows the qualified Pre-release run, instead of a separate job. Drop the regenerate-notes input and preview format checks. Signed-off-by: Matthew Grossman <mgrossman@nvidia.com> * ci(release): name the publish notes input after the caller's result Signed-off-by: Matthew Grossman <mgrossman@nvidia.com> --------- Signed-off-by: Matthew Grossman <mgrossman@nvidia.com>
1 parent ea265a2 commit 0f5b4f0

5 files changed

Lines changed: 48 additions & 9 deletions

File tree

‎.agents/skills/watch-github-actions/SKILL.md‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,10 @@ GitHub API failures; it requires `LLM_INFERENCE_API_KEY`, `ANTHROPIC_BASE_URL`,
196196
Pre-release also runs `release-notes.yml` after building, alongside publication
197197
and qualification, and keeps the notes only in the `release-notes` artifact.
198198
This job is advisory: a notes failure emits a warning without failing the
199-
prerelease run or blocking promotion. Stable publication requires successful
200-
notes generation.
199+
prerelease run or blocking promotion. Stable publication reuses the promoted
200+
prerelease's `release-notes` artifact, retagged, and generates notes only when
201+
that preview is unavailable. The `Select Qualified Prerelease` summary says
202+
which happened.
201203

202204
For `Codex Compatibility Review`, inspect its job summary and the
203205
`compatibility-review-run-<run-id>-attempt-<attempt>` artifact. Confirm the

‎.github/workflows/release-publish.yml‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ on:
1919
required: false
2020
default: false
2121
type: boolean
22+
release-notes-reused:
23+
description: Whether the calling run already uploaded release-notes from the promoted prerelease's preview
24+
required: false
25+
default: false
26+
type: boolean
2227
source-sha:
2328
description: Source commit of the built artifacts in the calling run
2429
required: true
@@ -329,7 +334,7 @@ jobs:
329334

330335
release-notes:
331336
name: Write Release Notes
332-
if: ${{ !inputs.is-prerelease }}
337+
if: ${{ !inputs.is-prerelease && !inputs.release-notes-reused }}
333338
permissions:
334339
contents: read
335340
pull-requests: read
@@ -342,7 +347,7 @@ jobs:
342347
release:
343348
name: Publish Release Assets
344349
needs: [assemble, release-helm, release-notes]
345-
if: ${{ !cancelled() && needs.assemble.result == 'success' && needs.release-helm.result == 'success' && (inputs.is-prerelease || needs.release-notes.result == 'success') }}
350+
if: ${{ !cancelled() && needs.assemble.result == 'success' && needs.release-helm.result == 'success' && (inputs.is-prerelease || inputs.release-notes-reused || needs.release-notes.result == 'success') }}
346351
runs-on: linux-amd64-cpu8
347352
timeout-minutes: 10
348353
permissions:

‎.github/workflows/release.yml‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ jobs:
4949
tag: ${{ steps.candidate.outputs.tag }}
5050
source-sha: ${{ steps.candidate.outputs.source_sha }}
5151
make-latest: ${{ steps.candidate.outputs.make_latest }}
52+
notes-reused: ${{ steps.notes.outputs.reused }}
5253
steps:
5354
- name: Require a release branch
5455
env:
@@ -91,6 +92,32 @@ jobs:
9192
retention-days: 90
9293
if-no-files-found: error
9394

95+
# Without a preview (missing or expired), Publish generates the notes instead.
96+
- name: Reuse the prerelease notes preview
97+
id: notes
98+
env:
99+
GH_TOKEN: ${{ github.token }}
100+
RUN_ID: ${{ steps.candidate.outputs.qualification_run_id }}
101+
CANDIDATE_TAG: ${{ steps.candidate.outputs.candidate_tag }}
102+
RELEASE_TAG: ${{ steps.candidate.outputs.tag }}
103+
run: |
104+
set -euo pipefail
105+
if gh run download "${RUN_ID}" -R "${GITHUB_REPOSITORY}" -n release-notes -D notes; then
106+
sed -i "s/${CANDIDATE_TAG//./\\.}\b/${RELEASE_TAG}/g" notes/release-notes.md
107+
echo "reused=true" >> "${GITHUB_OUTPUT}"
108+
echo "Release notes are reused from the \`${CANDIDATE_TAG}\` preview." >> "${GITHUB_STEP_SUMMARY}"
109+
else
110+
echo "Release notes will be regenerated; the \`${CANDIDATE_TAG}\` preview is unavailable." >> "${GITHUB_STEP_SUMMARY}"
111+
fi
112+
113+
- name: Upload release notes
114+
if: ${{ steps.notes.outputs.reused == 'true' }}
115+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
116+
with:
117+
name: release-notes
118+
path: notes/release-notes.md
119+
if-no-files-found: error
120+
94121
- name: Create stable tag at the qualified commit
95122
env:
96123
GH_TOKEN: ${{ github.token }}
@@ -140,6 +167,7 @@ jobs:
140167
npm-version: ${{ needs.build.outputs.npm_version }}
141168
is-prerelease: false
142169
make-latest: ${{ needs.promote.outputs.make-latest == 'true' }}
170+
release-notes-reused: ${{ needs.promote.outputs.notes-reused == 'true' }}
143171
secrets:
144172
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }}
145173
FERN_TOKEN: ${{ secrets.FERN_TOKEN }}

‎CI.md‎

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -339,9 +339,12 @@ identity belongs in the release manifest. The run ID and attempt distinguish
339339
reruns without overwriting earlier evidence.
340340

341341
`release-notes.yml` uses Claude Code Action through NVIDIA Inference Hub to
342-
summarize PRs since the previous stable tag. Stable releases require successful
343-
generation and publish the notes; prereleases retain a `release-notes` artifact,
344-
with advisory failures. Configure the `LLM_INFERENCE_API_KEY` Actions secret and
342+
summarize PRs since the previous stable tag. Prereleases retain a `release-notes`
343+
artifact, with advisory failures. Stable releases publish the promoted
344+
prerelease's preview with the prerelease tag replaced by the stable tag. If that
345+
preview is missing or expired, stable publication generates new notes and
346+
requires generation to succeed. The promotion summary states whether notes were
347+
reused or regenerated. Configure the `LLM_INFERENCE_API_KEY` Actions secret and
345348
the `ANTHROPIC_BASE_URL` and `ANTHROPIC_MODEL` Actions variables.
346349

347350
To preview notes without building or publishing:
@@ -633,11 +636,11 @@ These workflows run after merge to publish dev/tagged artifacts and verify them.
633636
| File | Role |
634637
|---|---|
635638
| `.github/workflows/release-dev.yml` | Publishes the rolling `dev` build on every push to `main`. Builds gateway, sandbox, and supervisor images and binaries, packages, wheels, and pushes the Helm chart as `oci://ghcr.io/nvidia/openshell/helm-chart:0.0.0-dev` (plus an immutable `0.0.0-dev.<sha>` pin). Also dispatchable manually. |
636-
| `.github/workflows/release.yml` | Manually promote the latest qualified prerelease for a version and branch, create its stable tag, then rebuild and publish. Support releases preserve shared latest channels. The notes-only mode generates a release notes preview artifact. |
639+
| `.github/workflows/release.yml` | Manually promote the latest qualified prerelease for a version and branch, create its stable tag, then rebuild and publish. Support releases preserve shared latest channels. Publishes the prerelease's notes preview, retagged, or generates notes when it is unavailable. The notes-only mode generates a release notes preview artifact. |
637640
| `.github/workflows/release-prerelease.yml` | Pre-release orchestrator, triggered by prerelease tag pushes or dispatched by Release Auto-Tag or manually: build, then publish and qualify in parallel. Qualification failure fails the run and sends the failure notification; published artifacts remain available. |
638641
| `.github/workflows/release-build.yml` | Shared version computation, binary and image builds, and package builds. Validates that the tag matches the caller's release kind. |
639642
| `.github/workflows/release-publish.yml` | Shared artifact assembly, OCI image tags and Helm chart publication, and package publication. Stable releases also publish to GitHub Releases, snap, npm, PyPI, and Fern. |
640-
| `.github/workflows/release-notes.yml` | Shared prompt-driven release notes generation through Inference Hub, used by stable publication and notes-only previews. |
643+
| `.github/workflows/release-notes.yml` | Shared prompt-driven release notes generation through Inference Hub, used by prerelease previews, notes-only previews, and stable publication when no preview is reused. |
641644
| `.github/workflows/release-qualification.yml` | Reusable qualification suites and result aggregation. Runs security scans, conformance and feature integration, Docker and VM E2E, protobuf compatibility, and advisory compatibility review. |
642645
| `.github/workflows/snap-package.yml` | Builds snap and component artifacts for Release Dev, Release, and Pre-release without Store credentials or publication. |
643646
| `.github/workflows/snap-publish.yml` | Uploads existing snap and component artifacts to the Store without rebuilding. Release Dev calls it directly for `latest/edge` after snap builds and requires it to succeed before creating the dev release. Release calls it through `release-publish.yml` for `latest/stable` after qualification and release publication succeed. |

‎tasks/scripts/select-release-candidate.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ def select_candidate(tag: str, branch: str) -> dict:
134134
"tag": tag,
135135
"candidate_tag": candidate,
136136
"source_sha": sha,
137+
"qualification_run_id": run["id"],
137138
"qualification_run_url": f"{run['html_url']}/attempts/{attempt}",
138139
"qualification_artifact_id": artifact["id"],
139140
"make_latest": is_latest(tag),

0 commit comments

Comments
 (0)