Skip to content

ci: add release workflow and script - #248

Merged
psjostrom merged 11 commits into
mainfrom
ci/release-workflow
Jul 25, 2026
Merged

ci: add release workflow and script#248
psjostrom merged 11 commits into
mainfrom
ci/release-workflow

Conversation

@psjostrom

@psjostrom psjostrom commented Jul 25, 2026

Copy link
Copy Markdown
Owner
## ci: add release workflow and script

Automate release PR creation via `workflow_dispatch` GitHub Actions. New files:

- **`scripts/release.sh`** — bumps `versionName`, generates AI changelog (GitHub Models / gpt-4o-mini), updates `CHANGELOG.md`. Works locally and in CI (`--prepare` mode).
- **`.github/workflows/create-release-pr.yml`** — manual trigger with version/bump/model inputs. Creates verified commit + PR via GitHub API. Idempotent on re-run.

Existing `release.yml` (tag → build → publish) untouched.

### How to use

**Local:** `scripts/release.sh --bump minor` or `scripts/release.sh --version 1.4.0`
**CI:** Actions → "Create release PR" → Run workflow
**After merge:** `git tag -a vX.Y.Z -m "vX.Y.Z" && git push origin vX.Y.Z`

Testing

  • CI passes
  • Verify workflow_dispatch inputs appear in Actions tab
  • Test local: scripts/release.sh --bump patch --prepare (dry run)
  • Merge PR

Summary by CodeRabbit

  • New Features
    • Added a Create release PR workflow with optional prerelease (RC) handling, version bumping, and AI-assisted release notes.
    • Added a Tag release workflow that tags releases on merged release PRs after validating branch/title/version safety rules.
    • Added a local release automation script to prepare and submit release PRs and update versionName and changelog.
  • Documentation
    • Updated release instructions with a preferred automated path and a streamlined manual fallback.
    • Added internal release automation documentation.
  • Tests
    • Added a test harness covering stable/RC transitions and AI changelog fallback behavior.

Automate release PR creation via GitHub Actions workflow_dispatch.
Script handles version bump, AI changelog (GitHub Models / gpt-4o-mini),
and CHANGELOG.md update. Works locally and in CI (--prepare mode).
Existing tag-push release.yml untouched.
@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 594fcd27-e10f-4a3a-a840-4f5e9ddd65b3

📥 Commits

Reviewing files that changed from the base of the PR and between d6284ea and 0cead1e.

📒 Files selected for processing (2)
  • docs/internal/release-automation.md
  • scripts/test-release.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/internal/release-automation.md

📝 Walkthrough

Walkthrough

Release automation now resolves stable and prerelease versions, generates changelogs, updates release files, supports local or CI preparation, creates release pull requests through GitHub Actions, validates merged release PRs before tagging, and adds automated script coverage and documentation.

Changes

Release automation

Layer / File(s) Summary
Release inputs, versioning, and changelog generation
scripts/release.sh
Adds argument validation, stable and prerelease version resolution, previous-tag detection, commit collection, and AI or raw changelog generation.
Repository updates and execution modes
scripts/release.sh
Updates versionName and CHANGELOG.md, emits GitHub Actions outputs in prepare mode, or creates and pushes a local release branch and pull request.
GitHub Actions integration and release guidance
.github/workflows/create-release-pr.yml, .agents/skills/release/SKILL.md, AGENTS.md
Adds prerelease workflow handling, verified commit and pull request creation, and automated and manual release instructions.
Post-merge release tagging
.github/workflows/tag-release.yml
Validates merged release pull requests and safely creates or reuses an annotated tag.
Release validation and reference documentation
scripts/test-release.sh, docs/internal/release-automation.md
Adds isolated tests for versioning, prerelease handling, validation, file updates, and changelog fallback, plus internal pipeline documentation.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Maintainer
  participant GitHubActions
  participant release.sh
  participant GitHubAPI
  Maintainer->>GitHubActions: dispatch release workflow
  GitHubActions->>release.sh: prepare version and changelog
  release.sh-->>GitHubActions: return release metadata and updated files
  GitHubActions->>GitHubAPI: create verified commit and release branch
  GitHubAPI-->>GitHubActions: create or update pull request
Loading
sequenceDiagram
  participant GitHub
  participant TagReleaseWorkflow
  participant Git
  GitHub->>TagReleaseWorkflow: notify merged release pull request
  TagReleaseWorkflow->>TagReleaseWorkflow: validate repository, branch, and version
  TagReleaseWorkflow->>Git: create or verify annotated tag
  Git-->>TagReleaseWorkflow: push tag to origin
Loading
🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the change and testing, but it does not follow the required template headings or checklist items. Add a ## What does this PR do? section and the exact checklist items from the template, including builds, tests, device testing, and signed commits.
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main release workflow and script changes.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/release-workflow

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

Adds --rc flag to release.sh and prerelease boolean input to the
workflow. When set, appends -rc.1 (or increments if already RC).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🤖 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 @.github/workflows/create-release-pr.yml:
- Around line 36-40: Update the Checkout step using actions/checkout@v4 to
disable credential persistence by setting persist-credentials to false, while
preserving the existing fetch-depth and ref configuration.
- Around line 78-128: Update the release commit flow around getCommit and
createCommit to resolve refs/heads/main explicitly and use that main commit SHA
instead of context.sha. Ensure both the base tree lookup and the new commit’s
parents reference the resolved main branch commit, preserving the existing blob
and tree creation.

In `@scripts/release.sh`:
- Around line 228-264: Update both release PR body templates in the PREPARE CI
mode and local mode paths to wrap CHANGELOG_SECTION in the required markdown
fenced block, including the opening ```markdown and closing ``` markers. Keep
the checklist outside the fence, and extract or reuse a shared template/helper
if appropriate so both generated BODY_FILE contents remain consistent.
- Around line 266-305: Make the local-mode release flow idempotent like the CI
path: reuse or reset the existing local $BRANCH instead of unconditionally
running checkout -b, and push updates with a safe force strategy when the remote
branch already exists or diverges. Before gh pr create, look up an existing open
PR for $BRANCH and update it when found; create a new PR only when none exists.
- Around line 70-81: Update bump_version so the patch case detects a pre-release
suffix in the current version and returns the same major.minor.patch version
without the suffix, promoting it to stable; only increment patch for
already-stable versions. Preserve the existing major and minor behavior and
invalid bump-kind handling.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 21f2da29-04c5-4c87-9d1d-95469c7684d5

📥 Commits

Reviewing files that changed from the base of the PR and between 2078f4a and d522fad.

📒 Files selected for processing (3)
  • .agents/skills/release/SKILL.md
  • .github/workflows/create-release-pr.yml
  • scripts/release.sh

Comment thread .github/workflows/create-release-pr.yml
Comment thread .github/workflows/create-release-pr.yml
Comment thread scripts/release.sh
Comment thread scripts/release.sh
Comment thread scripts/release.sh Outdated
When --rc is set and input version matches current base:
- If current is already RC (e.g. 1.3.1-rc.1) → increment to rc.2
- If current is stable (e.g. 1.3.1) → error: already released

Also fix grep -oP (GNU-only) to sed for macOS compatibility.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@scripts/release.sh`:
- Around line 99-124: Update the RC handling logic in the release script to
reject any TARGET_VERSION whose base version already has a
refs/tags/v<base-version> tag, not only when it matches the current stable
version. Perform this tag-existence check before incrementing or appending an RC
suffix, while preserving the existing behavior for untagged versions.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 38463142-ebfb-46ac-950b-c10f09f66b8f

📥 Commits

Reviewing files that changed from the base of the PR and between d522fad and 21603cc.

📒 Files selected for processing (2)
  • .github/workflows/create-release-pr.yml
  • scripts/release.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/create-release-pr.yml

Comment thread scripts/release.sh

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@AGENTS.md`:
- Line 108: Update the automated release flow around scripts/release.sh so its
generated changelog uses the fenced markdown release-notes contract expected by
the extractor in .github/workflows/release.yml. Ensure the AI-generated
changelog is enclosed in the required markdown fence and remains available as
the GitHub Release notes, or update both producer and extractor consistently
while preserving the documented contract.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 5ae7412f-cb4c-4cd9-a51f-4f8e74672ad3

📥 Commits

Reviewing files that changed from the base of the PR and between 21603cc and 8c3576e.

📒 Files selected for processing (1)
  • AGENTS.md

Comment thread AGENTS.md Outdated
- Add persist-credentials: false to checkout (security)
- Resolve refs/heads/main explicitly in github-script (data integrity)
- --bump patch now promotes RC to stable instead of skipping
- Wrap changelog in markdown fence for release.yml compatibility
- Make local-mode idempotent (-B, force-with-lease, update existing PR)
- Reject RC for already-tagged stable versions
- Update PR checklist to reflect auto-tagging

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
.github/workflows/create-release-pr.yml (1)

139-146: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Use a signed commit here
createCommit is called without a signature, so this produces an unsigned commit. If this step must produce a signed commit, pass a valid signature or switch to a signed git commit flow.

🤖 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 @.github/workflows/create-release-pr.yml around lines 139 - 146, Update the
createCommit call in the release workflow to produce a signed commit by
supplying a valid signature, or replace this API-based creation with a signed
git commit flow. Preserve the existing owner, repository, message, tree, and
parent values.
🤖 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 @.github/workflows/tag-release.yml:
- Around line 36-39: Update the “Create and push tag” workflow step to handle an
existing tag idempotently: fetch the tag, verify it resolves to the intended
commit, and exit successfully only when it matches; otherwise fail, while
preserving tag creation and push for missing tags.
- Around line 14-31: The release workflow’s version extraction and tagging must
not trust interpolated PR-title data or arbitrary merged branches. Update the
version step to receive the PR title through an environment variable, then
validate the extracted version and require the merged PR’s head repository to
match the base repository and its head ref to equal release/$VERSION before
creating the tag.

---

Outside diff comments:
In @.github/workflows/create-release-pr.yml:
- Around line 139-146: Update the createCommit call in the release workflow to
produce a signed commit by supplying a valid signature, or replace this
API-based creation with a signed git commit flow. Preserve the existing owner,
repository, message, tree, and parent values.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0236b998-83a2-4fd2-a498-bf895ec96f93

📥 Commits

Reviewing files that changed from the base of the PR and between 8c3576e and 8f08d43.

📒 Files selected for processing (4)
  • .github/workflows/create-release-pr.yml
  • .github/workflows/tag-release.yml
  • AGENTS.md
  • scripts/release.sh
🚧 Files skipped from review as they are similar to previous changes (2)
  • AGENTS.md
  • scripts/release.sh

Comment thread .github/workflows/tag-release.yml
Comment thread .github/workflows/tag-release.yml Outdated
- tag-release: idempotent tag creation (skip if same commit, fail if different)
- tag-release: validate trust boundaries (same repo, release/* branch)
- tag-release: receive PR title via env var, not direct interpolation
- create-release-pr: document API commit security model
@psjostrom
psjostrom force-pushed the ci/release-workflow branch from 8f08d43 to 152a3af Compare July 25, 2026 10:19

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 @.github/workflows/tag-release.yml:
- Around line 70-81: Update the existing-tag lookup in the tag verification
block to request and parse the peeled commit SHA for annotated tags, rather than
comparing the tag-object and peeled output together. Ensure EXISTING_SHA
contains a single commit SHA matching COMMIT_SHA while preserving the existing
skip and mismatch handling.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1ce8e0bd-0b88-44c5-9444-37c3e3ba0b28

📥 Commits

Reviewing files that changed from the base of the PR and between 8f08d43 and 152a3af.

📒 Files selected for processing (2)
  • .github/workflows/create-release-pr.yml
  • .github/workflows/tag-release.yml
🚧 Files skipped from review as they are similar to previous changes (1)
  • .github/workflows/create-release-pr.yml

Comment thread .github/workflows/tag-release.yml Outdated
@psjostrom
psjostrom force-pushed the ci/release-workflow branch from 0672992 to f043e73 Compare July 25, 2026 10:52
psjostrom and others added 2 commits July 25, 2026 15:08
- Remove v prefix from branch name and commit/PR titles in SKILL.md
  and AGENTS.md manual fallback (release/vX.Y.Z → release/X.Y.Z)
- Add scripts/test-release.sh (11 tests for version bumping, RC logic)
- Add docs/internal/release-automation.md (pipeline docs, trust
  boundaries, failure modes)

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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 (1)
.github/workflows/tag-release.yml (1)

62-63: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Pin actions/checkout to a full commit SHA.

@v4 is mutable; a retagged or compromised action would execute with this job’s write token. Pin a verified SHA and update it through dependency automation. GitHub identifies full SHAs as the immutable option for Actions dependencies. (docs.github.com)

🤖 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 @.github/workflows/tag-release.yml around lines 62 - 63, Update the Checkout
step’s actions/checkout reference from the mutable `@v4` tag to a verified full
commit SHA, preserving the existing major-version behavior, and configure it for
dependency automation updates.
🤖 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 `@docs/internal/release-automation.md`:
- Line 49: Update the workflow DAG fenced code block in the release automation
documentation to specify the text language, changing the opening fence to use
text while preserving the diagram contents.

In `@scripts/test-release.sh`:
- Around line 229-230: Update the assertion after the release preparation
command to read and validate the generated CHANGELOG.md content rather than the
generic command output. Assert a known commit subject expected in the written
changelog, while preserving the existing version preparation flow and assertion
context.
- Around line 212-213: Update the “both flags” case in the release test to
invoke the copied release script that exists in the temporary repository, using
the same script path established by the surrounding test setup. Keep the
conflicting --version and --bump arguments and assert the command exits nonzero
so their validation is actually exercised.

---

Nitpick comments:
In @.github/workflows/tag-release.yml:
- Around line 62-63: Update the Checkout step’s actions/checkout reference from
the mutable `@v4` tag to a verified full commit SHA, preserving the existing
major-version behavior, and configure it for dependency automation updates.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4a1b52bc-f8db-494e-b9cd-c4bf7bb7ff30

📥 Commits

Reviewing files that changed from the base of the PR and between 8f08d43 and d6284ea.

📒 Files selected for processing (6)
  • .agents/skills/release/SKILL.md
  • .github/workflows/create-release-pr.yml
  • .github/workflows/tag-release.yml
  • AGENTS.md
  • docs/internal/release-automation.md
  • scripts/test-release.sh
🚧 Files skipped from review as they are similar to previous changes (2)
  • .github/workflows/create-release-pr.yml
  • .agents/skills/release/SKILL.md

Comment thread docs/internal/release-automation.md Outdated
Comment thread scripts/test-release.sh Outdated
Comment thread scripts/test-release.sh Outdated
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