Skip to content

feat(nvca): add RC tagging process for release branches - #682

Closed
apartha-nv wants to merge 6 commits into
mainfrom
feat/nvca-rc-tagging-process-gh
Closed

feat(nvca): add RC tagging process for release branches#682
apartha-nv wants to merge 6 commits into
mainfrom
feat/nvca-rc-tagging-process-gh

Conversation

@apartha-nv

@apartha-nv apartha-nv commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Why

nvca releases currently go directly from dev tags on main to stable tags on the release branch with no intermediate RC bake period. This adds an RC tagging process so the team can validate images before cutting the final stable tag.

What changed

  • tools/ci/subproject-validations.yaml: added rc_prerelease: true to the nvca release config.
  • tools/generate-subproject-ci/main.go: added RCPrerelease field to releaseConfig and ReleaseRCPrerelease to releaseServiceView; updated .compute-next-release-version-service and .semantic-release-service shell templates so that on a release branch with RELEASE_RC_PRERELEASE=true they emit monotonically incrementing -rc.N tags instead of stable tags; added a promote-stable-<id> manual job template in the Release-Branch stage.
  • tools/ci/release-rc-promote: new Python script called by promote-stable-nvca; reads VERSION, verifies at least one -rc.N tag exists, checks no stable tag already exists, then creates the stable GitLab Release at the current release-branch HEAD via the Releases API.
  • tools/generate-subproject-ci/main_test.go: updated test fixture and assertions for the new RC output.
  • tools/ci/generated-release-jobs.yml: regenerated.

Behavior after this change

  • Every commit to release-src/compute-plane-services/nvca/vX.Y automatically creates X.Y.Z-rc.1, X.Y.Z-rc.2, etc. and stages images.
  • The promote-stable-nvca manual job button in the Release-Branch stage creates the final stable X.Y.Z tag and triggers a fresh image build.

Customer Release Notes

Not customer visible.

Plan Summary

Not applicable.

Usage

Trigger promote-stable-nvca in the Release-Branch stage of a release-branch pipeline when the RC images have been validated.

Testing

Generator tests pass (go test ./tools/generate-subproject-ci/...). Generated file regenerated and verified.

Notes

Follow-up: after the first stable release from a release branch, subsequent commits should produce patch releases (X.Y.1, X.Y.2) rather than more RCs. That behavior is tracked separately.

References

None

Related Merge Requests/Pull Requests

None

Dependencies

None

Summary by CodeRabbit

  • New Features

    • Added automated release promotion with validation for branches, versions, release candidates, and stable tags.
    • Added configurable CI workflows for subprojects, releases, container images, Helm charts, migrations, documentation, and UI checks.
    • Added prerelease workflows, staging and promotion, multi-architecture builds, release metadata, and notifications.
  • Reliability

    • Added comprehensive validation and testing for release workflows, generated pipelines, configuration, and edge cases.
    • Added end-to-end coverage for release candidate, stable, patch, and development-prerelease flows.

Every commit to a release-src/compute-plane-services/nvca/vX.Y branch
now creates an automatic RC tag (X.Y.Z-rc.N) instead of a stable tag.
A new manual promote-stable-nvca job in the Release-Branch stage creates
the final stable X.Y.Z tag and triggers a fresh image build.

Changes:
- tools/ci/subproject-validations.yaml: add rc_prerelease: true to nvca
- tools/generate-subproject-ci/main.go: add RCPrerelease field to
  releaseConfig and releaseServiceView; update compute-next and
  semantic-release shell templates to emit -rc.N on release branches
  when RELEASE_RC_PRERELEASE=true; emit promote-stable-<id> manual job
- tools/ci/release-rc-promote: new Python script that verifies at least
  one RC tag exists then creates the stable GitLab Release via the API
- tools/generate-subproject-ci/main_test.go: add RCPrerelease to test
  fixture and assert on new output strings
- tools/ci/generated-release-jobs.yml: regenerated
@apartha-nv
apartha-nv requested a review from a team as a code owner August 5, 2026 07:33
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: aa58986c-029d-4d78-96c0-a7379a36a465

📥 Commits

Reviewing files that changed from the base of the PR and between e90f0b4 and c80a4c9.

📒 Files selected for processing (1)
  • tools/ci/release-rc-promote
🚧 Files skipped from review as they are similar to previous changes (1)
  • tools/ci/release-rc-promote

📝 Walkthrough

Walkthrough

The change adds RC-to-stable GitLab release promotion, subproject CI configuration, and a Go generator for validation and release pipelines. It also adds tests for generated jobs, release flows, authentication, staging, and version transitions.

Changes

Release-candidate promotion

Layer / File(s) Summary
Validate and promote release tag
tools/ci/release-rc-promote
The utility validates configuration, versions, branches, RC tags, stable-tag conflicts, and GitLab release state before creating or reusing a stable release.
Exercise RC and stable version transitions
tools/ci/test-nvca-rc-flow
The Bash harness tests RC, stable, patch, same-SHA, conflicting-tag, and development-prerelease scenarios in a temporary Git repository.

Subproject CI generation

Layer / File(s) Summary
Model and validate subproject configuration
tools/ci/subproject-validations.yaml, tools/generate-subproject-ci/main.go, tools/generate-subproject-ci/main_test.go
The YAML defines subproject validation and release settings. The generator models and validates these settings. Tests cover configuration and authentication rules.
Render validation pipelines
tools/generate-subproject-ci/main.go, tools/generate-subproject-ci/main_test.go
The generator creates path-gated Go, Bazel, Helm, Dockerfile, workspace, and custom validation jobs. Tests cover generated jobs, artifacts, and workspace output.
Render release pipelines
tools/generate-subproject-ci/main.go, tools/generate-subproject-ci/main_test.go
The generator creates semantic-release, prerelease, staging, image, Dockerfile, Helm, notification, and downstream-release jobs. Tests cover release rendering and constraints.
Generate release metadata and outputs
tools/generate-subproject-ci/main.go
The CLI loads configuration and writes child pipelines, release pipelines, go.work, and GitHub release metadata.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ConfigYAML
  participant GenerateSubprojectCI
  participant ChildPipeline
  participant ReleasePipeline
  ConfigYAML->>GenerateSubprojectCI: load and validate subproject settings
  GenerateSubprojectCI->>ChildPipeline: render validation jobs
  GenerateSubprojectCI->>ReleasePipeline: render release jobs and metadata
Loading

Suggested reviewers: kristinapathak

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title uses valid Conventional Commits syntax and accurately describes the added NVCA release-candidate tagging process.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/nvca-rc-tagging-process-gh

Comment @coderabbitai help to get the list of available commands.

After promote-stable-nvca creates the stable X.Y.Z tag, subsequent
commits to the release branch produce patch releases (X.Y.(Z+1), ...)
instead of more RC tags. Both compute-next-release-version and
semantic-release now check for an existing stable tag before entering
RC mode.
- LAST_RC initialized to 0 so first RC tag is X.Y.Z-rc.1 (not rc.0)
- tools/ci/test-nvca-rc-flow: local harness covering RC phase,
  stable promotion, patch mode, idempotency, and dev prerelease

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (5)
tools/ci/release-rc-promote (3)

60-67: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Surface git stderr when a git command fails.

capture_output=True with check=True hides git stderr. When git tag -l, git fetch, or git rev-list fails, CalledProcessError prints the argv and the exit code but not the git message. This job runs manually during a release, so the operator needs the git message in the log.

The same pattern applies to git fetch at line 92 and git rev-list at lines 104-109.

♻️ Proposed helper that reports git stderr
 def git_tags_matching(pattern: str) -> list[str]:
-    result = subprocess.run(
-        ["git", "tag", "-l", pattern],
-        capture_output=True,
-        text=True,
-        check=True,
-    )
-    return [t for t in result.stdout.splitlines() if t]
+    return [t for t in run_git("tag", "-l", pattern).splitlines() if t]
+
+
+def run_git(*args: str) -> str:
+    result = subprocess.run(["git", *args], capture_output=True, text=True, check=False)
+    if result.returncode != 0:
+        raise SystemExit(
+            f"[rc-promote] ERROR: git {' '.join(args)} failed with exit {result.returncode}: "
+            f"{result.stderr.strip()}"
+        )
+    return result.stdout
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/ci/release-rc-promote` around lines 60 - 67, Update git_tags_matching
and the git fetch and git rev-list subprocess calls to surface captured stderr
when git raises CalledProcessError. Reuse or add a shared helper for these git
commands that logs or prints the command’s stderr before propagating the
failure, while preserving existing check and output behavior.

45-57: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Handle transport failures and transient 5xx responses.

api_request catches only urllib.error.HTTPError. A DNS failure, a connection reset, a TLS error, or the 30-second timeout raises urllib.error.URLError or TimeoutError. The script then exits with a raw traceback instead of the [rc-promote] ERROR: format used elsewhere.

The promotion job performs a single POST /releases write. If that request fails transiently, an operator must re-run the manual job. A short bounded retry on 5xx and transport errors makes the job self-healing. Keep the retry safe: on re-entry the existing-stable-tag check at lines 102-116 already returns 0 when the tag points at CI_COMMIT_SHA.

♻️ Proposed transport-error handling
-    request = urllib.request.Request(url, data=data, method=method, headers=headers)
-    try:
-        with urllib.request.urlopen(request, timeout=30) as response:
-            body = response.read()
-            if response.status not in ok:
-                raise SystemExit(f"{method} {path} returned HTTP {response.status}: {body.decode('utf-8', 'replace')}")
-            if not body:
-                return None
-            return json.loads(body.decode("utf-8"))
-    except urllib.error.HTTPError as err:
-        body = err.read().decode("utf-8", "replace")
-        if err.code in ok:
-            return None
-        raise SystemExit(f"{method} {path} returned HTTP {err.code}: {body}") from err
+    request = urllib.request.Request(url, data=data, method=method, headers=headers)
+    last_error = None
+    for attempt in range(3):
+        try:
+            with urllib.request.urlopen(request, timeout=30) as response:
+                body = response.read()
+                if response.status not in ok:
+                    raise SystemExit(
+                        f"[rc-promote] ERROR: {method} {path} returned HTTP {response.status}: "
+                        f"{body.decode('utf-8', 'replace')}"
+                    )
+                if not body:
+                    return None
+                return json.loads(body.decode("utf-8"))
+        except urllib.error.HTTPError as err:
+            body = err.read().decode("utf-8", "replace")
+            if err.code in ok:
+                return None
+            if err.code < 500:
+                raise SystemExit(f"[rc-promote] ERROR: {method} {path} returned HTTP {err.code}: {body}") from err
+            last_error = f"HTTP {err.code}: {body}"
+        except (urllib.error.URLError, TimeoutError) as err:
+            last_error = f"transport error: {err}"
+        if attempt < 2:
+            time.sleep(2 ** attempt)
+    raise SystemExit(f"[rc-promote] ERROR: {method} {path} failed after 3 attempts: {last_error}")

Add the import:

 import subprocess
 import sys
+import time
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/ci/release-rc-promote` around lines 45 - 57, Update api_request to
catch urllib.error.URLError and TimeoutError, reporting failures with the
script’s existing “[rc-promote] ERROR:” format instead of exposing tracebacks.
For the single POST /releases promotion request, add a short bounded retry
covering transport failures and transient HTTP 5xx responses, while preserving
existing success handling and the stable-tag idempotency check.

70-126: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add focused tests for tools/ci/release-rc-promote.

The existing test checks only the generated YAML entrypoint. Add tests for version validation, RC discovery, and stable-tag conflict handling.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/ci/release-rc-promote` around lines 70 - 126, Add focused tests
covering main() in release-rc-promote: reject invalid version_file contents,
discover and require matching RC tags before promotion, and handle an existing
stable tag by returning successfully when it points to current_sha or failing
when it points elsewhere. Mock environment variables, git helpers, subprocess
calls, and api_request so tests remain isolated while asserting the relevant
messages and outcomes.

Source: Coding guidelines

tools/generate-subproject-ci/main_test.go (1)

1256-1265: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extend the rules assertions to promote-stable-nvca.

The new assertions check the job name and the script line, but not the job's rules. The rules are the control that keeps a stable promotion off non-release refs: the cleanup-schedule skip, the release-branch ref pattern, and when: manual. Add promote-stable-nvca to this loop and assert the manual gate.

💚 Proposed test extension
 	for _, job := range []string{
 		"compute-next-release-version-nvca",
 		"semantic-release-nvca",
 		"release-branch-nvca",
+		"promote-stable-nvca",
 	} {
 		section := extractJobBlock(t, rendered, job)
 		if !strings.Contains(section, cleanupScheduleSkipRule) {
 			t.Errorf("%s should skip cleanup-only schedules\n---\n%s\n---", job, section)
 		}
 	}
+
+	promote := extractJobBlock(t, rendered, "promote-stable-nvca")
+	for _, want := range []string{
+		"stage: Release-Branch",
+		"if: $CI_COMMIT_BRANCH =~ /^release-src\\/compute-plane-services\\/nvca\\/v[0-9]+\\.[0-9]+$/",
+		"when: manual\n      allow_failure: true",
+	} {
+		if !strings.Contains(promote, want) {
+			t.Errorf("promote-stable-nvca missing %q\n---\n%s\n---", want, promote)
+		}
+	}

As per coding guidelines: "For changed tool behavior, add or update focused tests."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/generate-subproject-ci/main_test.go` around lines 1256 - 1265, Extend
the rules assertion loop covering release jobs to include promote-stable-nvca,
and assert its extracted job block contains the cleanup-schedule skip,
release-branch ref pattern, and when: manual gate. Preserve the existing
assertions for the other jobs.

Source: Coding guidelines

tools/generate-subproject-ci/main.go (1)

1290-1328: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Consider extracting the RC/patch version computation into the shared shell helper.

Lines 1290-1328 repeat lines 768-807 verbatim: the same RC-suffix scan, the same patch-suffix scan, and the same LAST_*/NEXT_* arithmetic. The two copies must stay in lockstep, because compute-next writes NEXT_VERSION and semantic-release recomputes it under the release lock and compares the two values (line 1329). A divergence between the copies would show up only as a confusing "recomputed NEXT_VERSION" log line.

release-tag-compat.sh is already the shared source for both jobs. Move the computation there as, for example, release_compute_branch_version, and call it from both places.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/generate-subproject-ci/main.go` around lines 1290 - 1328, The RC and
patch version calculations are duplicated between compute-next and
semantic-release. Extract the shared logic into a helper such as
release_compute_branch_version in release-tag-compat.sh, then replace both
inline computations near the existing NEXT_VERSION flows with calls to that
helper, preserving the current RC, patch, and VERSION results so both jobs
recompute identically.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tools/ci/release-rc-promote`:
- Around line 100-122: Update the RC tag ordering used by the reporting print
and the stable-tag payload description to sort rc_tags by the numeric RC suffix
rather than lexicographically. Introduce or reuse a key that extracts the
trailing RC number, then use it consistently for both sorted(rc_tags) references
while preserving current_sha and stable-tag behavior.

In `@tools/generate-subproject-ci/main.go`:
- Around line 3761-3765: Update validateRelease next to the existing
rel.DevPrerelease guard to reject configurations where rel.RCPrerelease is true
while rel.DevPrerelease is false, returning a validation error that identifies
the subproject and required relationship. Preserve the existing version_file
validation for dev prereleases.
- Around line 768-785: The stable-tag check in the RC prerelease branch must
only consider the current release tag prefix. Update the
`release_tag_for_version` probe in the `RELEASE_RC_PRERELEASE` condition to use
the current prefix explicitly, preventing legacy or synthesized alternate-prefix
tags from switching to patch mode while preserving `-rc.0` generation when no
current-prefix stable tag exists.

---

Nitpick comments:
In `@tools/ci/release-rc-promote`:
- Around line 60-67: Update git_tags_matching and the git fetch and git rev-list
subprocess calls to surface captured stderr when git raises CalledProcessError.
Reuse or add a shared helper for these git commands that logs or prints the
command’s stderr before propagating the failure, while preserving existing check
and output behavior.
- Around line 45-57: Update api_request to catch urllib.error.URLError and
TimeoutError, reporting failures with the script’s existing “[rc-promote]
ERROR:” format instead of exposing tracebacks. For the single POST /releases
promotion request, add a short bounded retry covering transport failures and
transient HTTP 5xx responses, while preserving existing success handling and the
stable-tag idempotency check.
- Around line 70-126: Add focused tests covering main() in release-rc-promote:
reject invalid version_file contents, discover and require matching RC tags
before promotion, and handle an existing stable tag by returning successfully
when it points to current_sha or failing when it points elsewhere. Mock
environment variables, git helpers, subprocess calls, and api_request so tests
remain isolated while asserting the relevant messages and outcomes.

In `@tools/generate-subproject-ci/main_test.go`:
- Around line 1256-1265: Extend the rules assertion loop covering release jobs
to include promote-stable-nvca, and assert its extracted job block contains the
cleanup-schedule skip, release-branch ref pattern, and when: manual gate.
Preserve the existing assertions for the other jobs.

In `@tools/generate-subproject-ci/main.go`:
- Around line 1290-1328: The RC and patch version calculations are duplicated
between compute-next and semantic-release. Extract the shared logic into a
helper such as release_compute_branch_version in release-tag-compat.sh, then
replace both inline computations near the existing NEXT_VERSION flows with calls
to that helper, preserving the current RC, patch, and VERSION results so both
jobs recompute identically.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c15debf2-80e5-4d7a-9703-bc811355b171

📥 Commits

Reviewing files that changed from the base of the PR and between efc98c7 and b7aac4e.

⛔ Files ignored due to path filters (1)
  • tools/ci/generated-release-jobs.yml is excluded by !tools/ci/generated-release-jobs.yml
📒 Files selected for processing (4)
  • tools/ci/release-rc-promote
  • tools/ci/subproject-validations.yaml
  • tools/generate-subproject-ci/main.go
  • tools/generate-subproject-ci/main_test.go

Comment thread tools/ci/release-rc-promote Outdated
Comment thread tools/generate-subproject-ci/main.go Outdated
Comment thread tools/generate-subproject-ci/main.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tools/ci/test-nvca-rc-flow`:
- Around line 197-245: The test flow incorrectly expects patch computation after
creating stable tag 3.1.0 at the same SHA and never exercises SKIP=true. Update
the phase around compute_next_version to assert the same-SHA stable-tag skip,
then create a new commit and update CI_COMMIT_SHA before asserting patch mode
selects 3.1.1; also add a retry scenario that pre-creates the computed tag and
verifies compute_next_version assigns SKIP=true, rather than only calling
release_tag_for_version directly.
- Around line 27-29: Configure repository-local Git identity in the temporary
repository setup before the initial commit: use git -C with ${CI_PROJECT_DIR} to
set both user.name and user.email, then preserve the existing empty commit flow.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 92eb9e6f-6753-4ac0-aabc-591260f0ba4e

📥 Commits

Reviewing files that changed from the base of the PR and between b7aac4e and dbc146f.

⛔ Files ignored due to path filters (1)
  • tools/ci/generated-release-jobs.yml is excluded by !tools/ci/generated-release-jobs.yml
📒 Files selected for processing (2)
  • tools/ci/test-nvca-rc-flow
  • tools/generate-subproject-ci/main.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • tools/generate-subproject-ci/main.go

Comment thread tools/ci/test-nvca-rc-flow
Comment thread tools/ci/test-nvca-rc-flow Outdated
- release-rc-promote: sort RC tags by numeric suffix (not lexicographic)
  so rc.10 sorts after rc.9; add run_git helper that surfaces stderr;
  add 3-attempt retry on 5xx/transport errors in api_request
- main.go: reject rc_prerelease: true without dev_prerelease: true at
  validation time; fix stable-tag check to use only the primary tag
  prefix (git rev-parse) so legacy nvca-v tags cannot prematurely
  switch the release branch out of RC mode
- main_test.go: assert promote-stable-nvca rules (stage, ref pattern,
  when: manual, allow_failure, script)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
tools/ci/release-rc-promote (1)

140-140: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Record the release-flow documentation assessment.

This tool adds an RC-to-stable release transition. Assess whether the architecture or sequence documentation needs an update, and record the result in the Pull Request.

As per coding guidelines, “When runtime behavior, data flow, or component interactions change, assess whether architecture or sequence diagrams need updating; prefer ASCII or Mermaid over binary images.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/ci/release-rc-promote` at line 140, Assess whether the RC-to-stable
promotion flow implemented by the release description generation needs
architecture or sequence documentation updates, and record that assessment in
the Pull Request. If documentation changes are warranted, update them using
ASCII or Mermaid diagrams; otherwise explicitly document that no update is
required.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tools/ci/release-rc-promote`:
- Around line 117-124: Update the RC selection flow around git_tags_matching,
rc_sort_key, and current_sha to retain only tags matching the numeric -rc.N
format and resolving to current_sha. Require this filtered set to be non-empty,
then select latest_rc and generate the summary output exclusively from the
filtered tags.
- Around line 57-81: Update the POST release-creation retry flow around the
request helper to reconcile ambiguous failures before retrying or exiting:
URL-encode stable_tag for tag and release lookups, verify the stable tag points
to CI_COMMIT_SHA, and verify the corresponding release matches stable_tag.
Return success only when both checks pass; otherwise preserve the existing retry
and failure behavior.

---

Nitpick comments:
In `@tools/ci/release-rc-promote`:
- Line 140: Assess whether the RC-to-stable promotion flow implemented by the
release description generation needs architecture or sequence documentation
updates, and record that assessment in the Pull Request. If documentation
changes are warranted, update them using ASCII or Mermaid diagrams; otherwise
explicitly document that no update is required.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b69f5356-4903-4005-9d9b-0f354c475f72

📥 Commits

Reviewing files that changed from the base of the PR and between dbc146f and 44a6125.

⛔ Files ignored due to path filters (1)
  • tools/ci/generated-release-jobs.yml is excluded by !tools/ci/generated-release-jobs.yml
📒 Files selected for processing (3)
  • tools/ci/release-rc-promote
  • tools/generate-subproject-ci/main.go
  • tools/generate-subproject-ci/main_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • tools/generate-subproject-ci/main.go

Comment thread tools/ci/release-rc-promote Outdated
Comment thread tools/ci/release-rc-promote Outdated
test-nvca-rc-flow:
- Set git user.name/email before initial commit so the harness
  works on CI runners with no global git identity
- Add advance_commit helper; Phase 3 now uses distinct commits per
  patch to model real cherry-picks (each tag at its own SHA)
- Update compute_next_version to do SHA-based SKIP check matching
  the real CI code (SKIP=true only when NEXT_VERSION exists at the
  current CI_COMMIT_SHA, error if it exists at a different SHA)
- Phase 2 now asserts SKIP=true on the same-SHA retry path (dotenv
  NEXT_VERSION=3.1.1 is found at CI_COMMIT_SHA)
- Phase 4 asserts SKIP=true for the patch retry scenario

release-rc-promote:
- Filter RC tags to numeric -rc.N tags that resolve to current_sha;
  RC tags from other commits or with non-numeric suffixes are rejected
- Reconcile 409 Conflict before failing: verify the tag and release
  already exist at current_sha via GET /repository/tags and
  GET /releases before treating it as success; retry 5xx and
  transport errors up to 3 times with reconciliation before each retry

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tools/ci/release-rc-promote (1)

191-200: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Verify the GitLab Release when the stable tag already exists.

Line 194 returns 0 when the local stable tag points at current_sha. It does not check that a Release exists for stable_tag. A previous run can create the tag without the Release record, for example when the POST is interrupted after tag creation. This path then reports "nothing to do" and no Release is ever created.

Query /releases/<encoded stable_tag> before returning 0, and continue to the POST when the Release is missing.

🩹 Proposed check for the existing Release
         if tag_sha == current_sha:
-            print(f"[rc-promote] {stable_tag} already points at {current_sha}; nothing to do")
-            return 0
+            encoded = urllib.parse.quote(stable_tag, safe="")
+            release_info = api_get(f"/releases/{encoded}")
+            if release_info and release_info.get("tag_name") == stable_tag:
+                print(f"[rc-promote] {stable_tag} already released at {current_sha}; nothing to do")
+                return 0
+            print(
+                f"[rc-promote] {stable_tag} exists at {current_sha} but has no Release; "
+                f"creating the Release"
+            )

Note: with this change the POST reuses the existing tag, so ref is ignored by GitLab and the Release is attached to the existing tag.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/ci/release-rc-promote` around lines 191 - 200, Update the existing-tag
branch in the stable-tag promotion flow to query the GitLab release for the
encoded stable_tag before returning 0. Only report “nothing to do” when the
release exists; when the release is missing, fall through to the existing
release-creation POST while preserving the current conflict error for tags
pointing to a different commit.
🧹 Nitpick comments (1)
tools/ci/test-nvca-rc-flow (1)

233-242: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the tag-existence check so the retry tests exercise the production path. Both retry scenarios inline a copy of the EXISTING check from compute_next_version (Lines 137-148). The copies map a SHA mismatch to SKIP=false, while the function sets SKIP=error, so a regression in the function is not detected.

  • tools/ci/test-nvca-rc-flow#L233-L242: replace the inline block with a call to a new helper, for example evaluate_existing_tag <version>, and call that helper from compute_next_version as well.
  • tools/ci/test-nvca-rc-flow#L289-L298: replace the second inline block with the same helper call.

As per coding guidelines, "For changed tool behavior, add or update focused tests."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/ci/test-nvca-rc-flow` around lines 233 - 242, Extract the existing-tag
evaluation into a shared helper, such as evaluate_existing_tag, preserving
compute_next_version’s SKIP=error behavior for a matching tag with a SHA
mismatch. Update compute_next_version and both retry scenarios at
tools/ci/test-nvca-rc-flow lines 233-242 and 289-298 to call the helper instead
of duplicating the check, and add or update focused tests covering the helper’s
outcomes.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tools/ci/release-rc-promote`:
- Around line 98-107: Update the retry handling in the release promotion flow to
reconcile after every failed attempt, including the final one, before raising
the failure. Replace the tag-only check using api_get with a non-fatal call to
_reconcile_existing_release so success requires both the stable tag and its
Release record, while preserving the existing retry delays and error reporting.

---

Outside diff comments:
In `@tools/ci/release-rc-promote`:
- Around line 191-200: Update the existing-tag branch in the stable-tag
promotion flow to query the GitLab release for the encoded stable_tag before
returning 0. Only report “nothing to do” when the release exists; when the
release is missing, fall through to the existing release-creation POST while
preserving the current conflict error for tags pointing to a different commit.

---

Nitpick comments:
In `@tools/ci/test-nvca-rc-flow`:
- Around line 233-242: Extract the existing-tag evaluation into a shared helper,
such as evaluate_existing_tag, preserving compute_next_version’s SKIP=error
behavior for a matching tag with a SHA mismatch. Update compute_next_version and
both retry scenarios at tools/ci/test-nvca-rc-flow lines 233-242 and 289-298 to
call the helper instead of duplicating the check, and add or update focused
tests covering the helper’s outcomes.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: bccd21de-8868-4008-9842-08e1209c0d64

📥 Commits

Reviewing files that changed from the base of the PR and between 44a6125 and e90f0b4.

📒 Files selected for processing (2)
  • tools/ci/release-rc-promote
  • tools/ci/test-nvca-rc-flow

Comment thread tools/ci/release-rc-promote Outdated
Reconciliation now runs after every failed POST /releases attempt,
including the third. Checks both the tag commit and the Release record
so a tag without a Release does not silently pass as success.
@apartha-nv

Copy link
Copy Markdown
Contributor Author

Team has decided to move towards patch builds and drop the rc. Closing the PR.

@apartha-nv apartha-nv closed this Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant