Skip to content
164 changes: 164 additions & 0 deletions .claude/commands/release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
---
allowed-tools: Read, Write, Edit, Bash(*), WebSearch, WebFetch, Agent
description: Release orchestrator — builds a digest of what changed in a release PR, opens a changelog PR, and references the bump PR. Usage: /release PR_NUMBER
---

# Release Orchestrator

Your job is to orchestrate the release process for a given PR. This involves analyzing the PR's commits and changed files to build a structured digest of what changed, determining if there are any breaking changes, preparing a changelog, opening a PR to bump chart versions if needed, and updating the original PR description with the changelog and references to the new PRs.

---

## Phase 1: Collect — Build the release digest

1. Fetch PR metadata:
```
gh pr view $ARGUMENTS --json number,title,body,commits,files
```

2. For each commit SHA in the PR, inspect the changed files:
```
git show --name-only --format="%H %s" <sha>
```

3. Classify each commit to a component:
- Cortex shim: code touching the shim layer (internal/shim and cmd/shim)
- Cortex postgres: code touching the postgres docker image, or its helm chart
- Cortex core: core code touching anything else: the manager or external scheduler logic of cortex
- General: CI, tooling, docs, or other non-code changes

4. Finally, read through the cortex helm charts in the helm/ folder, and check which ones have updated appVersions, indicating a new Docker image is available and that the chart should be included in the release notes.

Produce a structured digest in this exact format — the subagents depend on it:

```
## Release Digest — PR #NNN "{title}"

### Changed Charts
- cortex v1.2.3 (sha-xxxxxxxx)
- cortex-postgres v1.2.3 (sha-xxxxxxxx)
- cortex-nova v1.2.3 — includes cortex v1.2.3, cortex-postgres v1.2.3

### Commits by Component

#### cortex core
- <sha> <subject>

#### cortex postgres
- <sha> <subject>

#### cortex shim
- <sha> <subject>

#### General
- <sha> <subject>
```

**Important**: Do NOT skip or shallow this phase. Read actual file diffs. The subagents depend entirely on the quality of this digest.

---

## Phase 2: Determine Breaking Changes and Prepare a Changelog

Reason for each change by looking at the commit's diff, if it is a breaking change that requires special attention.

**Important**: Do NOT skip or shallow this phase. Read actual file diffs. The PR reviewers depend entirely on the quality of this analysis to know what to focus on in their review.

### When is a change "breaking"?

A change should be classified as "breaking" if it meets any of the following criteria:

- It changes or removes the public API of any component (e.g., CRD schemas, CLI flags, or REST API endpoints). Note: additions to the public API are not breaking.
- It requires a config format change (e.g., renaming or removing a values.yaml key, changing the expected format of a value, etc)

Once the digest is complete, read each agent file, then dispatch all three **in parallel** using the Agent tool in a single message. Each subagent operates independently — do not wait for one before starting the others.

### Prepare the changelog

Generate a changelog following this template:

```markdown
# Changelog

## YYYY-MM-DD — [#NNN](<PR URL>)

### <chart-name> v<version> (<appVersion>)

Breaking changes:
- <bullet per meaningful change>

Non-breaking changes:
- <bullet per meaningful change>

... repeat for each changed chart ...

### General

Breaking changes:
- <bullet per meaningful change>

Non-breaking changes:
- <bullet per meaningful change>
```

One `###` section per changed chart only. For bundle sections, list which library versions they include, then any bundle-specific changes (values.yaml keys, template/CRD changes). Omit `### General` if empty. No commit SHAs, one line per bullet.

Example:
```markdown
# Changelog

## 2026-04-24 — [#123](https://github.com/cobaltcore-dev/cortex/pull/123)

### cortex v0.0.43 (sha-xxxxxxxx)

Breaking changes:
- Check hypervisor resources against reservations

Non-breaking changes:
- Commitments usage API uses postgres database instead of calling nova

### cortex-postgres v0.5.14 (sha-xxxxxxxx)

Non-breaking changes:
- Add commitments table migration

### cortex-nova v0.0.56 (sha-xxxxxxxx)

Includes updated charts cortex v0.0.43 and cortex-postgres v0.5.14.

Non-breaking changes:
- values.yaml: added `reservations.enabled` (default: false)

### General

Non-breaking changes:
- Update golangci-lint to v2.1.0
```

## Phase 3: Bump Chart Versions

Prepare chart version bumps so GitHub pushes bumped charts to the registry immediately after the release PR is merged.

For each changed library chart, patch-bump its `version` in `helm/library/<name>/Chart.yaml` (e.g. `0.0.43` → `0.1.0`), if there was no breaking change, otherwise minor-bump it. Do not touch `appVersion`. Then update the matching `dependencies[].version` entry in every `helm/bundles/*/Chart.yaml` that references it.

Open a single PR to `main` with all the bumps, branch `release/bump-charts-<NNN>`, noting in the body that it should be merged before the release PR. Use the pull-request-creator agent for this subtask, and include the chart changes in the motivation so they are included in the PR description.

## Phase 4: Update the PR Description

Use `gh pr edit` with `--body` to update the PR description with the changelog. It is fine for release pull request descriptions to utilize markdown formatting. Reference the opened bump PR in the description as well as a dependency.

## Phase 5: Create a Changelog PR

If the CHANGELOG.md does not exists, create it with a `# Changelog` header. Then create a new PR to `main` with branch `release/changelog-<NNN>`, title `Update changelog for release PR #<NNN>`, and a body noting it should be merged after the release PR. Use the pull-request-creator agent for this subtask.

## Phase 6: Summarize — Report what happened

After all subagents return, produce a short summary:

```
## Release #NNN Post-Open Summary

- PR description updated with changelog and bump PR reference
- Bump PR #XXX opened to update chart versions
- Changelog PR #YYY opened to update CHANGELOG.md
```
54 changes: 54 additions & 0 deletions .claude/commands/update-changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
allowed-tools: Read, Write, Edit, Bash(*), WebSearch, WebFetch
description: Create a changelog entry for a merged release PR and open a PR to main. Usage: /update-changelog PR_NUMBER
---

A release PR (#$ARGUMENTS) was merged into the `release` branch. Create a changelog entry for it and open a PR to `main`.

To build the entry, use the PR's commit subjects (no diffs) and the changed Helm charts as your sources. Only include charts whose Chart.yaml actually changed in this PR.

Format each entry as:

## {merged_at date in UTC, formatted YYYY-MM-DD} — {PR title} ([#NNN](https://github.com/cobaltcore-dev/cortex/pull/NNN))

One `###` section per changed chart: `### <chart-name> v<version> (<appVersion>)`
Under each section, bullet the commit subjects that relate to that chart.

Attribution: for each commit, inspect its changed files with `git show --name-only <sha>` and map to the chart whose files were touched:

- `postgres/**` → cortex-postgres
- `cmd/shim/**` or `internal/shim/**` → cortex-shim
- `helm/bundles/cortex-<name>/**` → that specific bundle chart
- anything else → cortex (core)

Commits that only touch CI, docs, or tooling go into `### General`. Skip commits containing "[skip ci]" or that are pure version-bump message.

For bundle chart sections (helm/bundles/*), add a note listing which library chart versions they now include (read the bundle's Chart.yaml dependencies). Then inspect the actual diff of the bundle's own files with `git show <sha> -- helm/bundles/<name>/` for any commit that touched that bundle, and surface specific changes:

- **values.yaml** changes: call out new, removed, or renamed keys and changed defaults
- **templates/** or **crds/** changes: call out added, removed, or modified resources by kind and name

Prepend the new entry below the `# Changelog` header in `CHANGELOG.md` (create the file if it doesn't exist). Then open a PR to `main` referencing this release PR.

## Example

```markdown
## 2026-04-24 — Release libs cortex v0.0.43 + bundles v0.0.56 ([#722](https://github.com/cobaltcore-dev/cortex/pull/722))

### cortex v0.0.43 (sha-xxxxxxxx)
- Commitments usage API uses postgres database instead of calling nova
- Check hypervisor resources against reservations
- Add committed resource reservations to capacity calculation

### cortex-postgres v0.5.14 (sha-xxxxxxxx)
- Add commitments table migration

### cortex-nova v0.0.56 (sha-xxxxxxxx)
- Update nova bundle for committed reservations support

### cortex-manila v0.0.56 (sha-xxxxxxxx)
- Update manila bundle for committed reservations support

### General
- Update golangci-lint to v2.1.0
```
2 changes: 1 addition & 1 deletion .coderabbit.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
reviews:
high_level_summary: false
high_level_summary: false
52 changes: 52 additions & 0 deletions .github/workflows/claude-release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Claude Code Release Orchestrator

on:
pull_request:
types: [opened, synchronize, reopened]
branches:
- release
Comment on lines +4 to +7
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Run this workflow only when the release PR is closed and merged.

Right now it runs on every update to a release PR, which can repeatedly reopen/update downstream automation PRs before release lands.

🔧 Suggested fix
 on:
   pull_request:
-    types: [opened, synchronize, reopened]
+    types: [closed]
     branches:
       - release

 jobs:
   release:
+    if: github.event.pull_request.merged == true
     runs-on: ubuntu-latest

Also applies to: 10-10

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/claude-on-release-merge.yaml around lines 4 - 7, The
workflow currently triggers on pull_request events for types [opened,
synchronize, reopened] against the release branch, causing it to run on every
update; change the trigger to only fire when a release PR is closed and merged
by replacing the types list with [closed] (keeping branches: - release) and add
a runtime guard to the workflow or jobs using the GitHub context check
github.event.pull_request.merged == true (e.g., add if:
github.event.pull_request.merged == true) so the workflow runs only after a
release PR is closed and confirmed merged.


jobs:
release:
if: false # Temporarily disabled
runs-on: ubuntu-latest
concurrency:
group: changelog-release
cancel-in-progress: false
permissions:
contents: write
pull-requests: write
id-token: write
Comment thread
SoWieMarkus marked this conversation as resolved.
steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'

- uses: ./.github/actions/setup-claude-code-action

- uses: ./.github/actions/start-litellm-proxy
env:
AICORE_RESOURCE_GROUP: ${{ secrets.AICORE_RESOURCE_GROUP }}
AICORE_BASE_URL: ${{ secrets.AICORE_BASE_URL }}
AICORE_AUTH_URL: ${{ secrets.AICORE_AUTH_URL }}
AICORE_CLIENT_ID: ${{ secrets.AICORE_CLIENT_ID }}
AICORE_CLIENT_SECRET: ${{ secrets.AICORE_CLIENT_SECRET }}

- uses: ./.claude-code-action
with:
claude_args: |
--max-turns 1000
--permission-mode auto
--allowedTools "Read,Write,Edit,Bash(*),WebSearch,WebFetch,Agent"
use_litellm: "true"
litellm_model: "sap/anthropic--claude-4.6-opus"
github_token: ${{ secrets.GITHUB_TOKEN }}
show_full_output: "true"
prompt: "/release ${{ github.event.pull_request.number }}"

- uses: ./.github/actions/stop-litellm-proxy
if: always()
Loading