Skip to content

chore(release): adopt shared forensic release pipeline - #1514

Merged
chhoumann merged 3 commits into
masterfrom
chore/shared-release-pipeline
Jul 11, 2026
Merged

chore(release): adopt shared forensic release pipeline#1514
chhoumann merged 3 commits into
masterfrom
chore/shared-release-pipeline

Conversation

@chhoumann

@chhoumann chhoumann commented Jul 11, 2026

Copy link
Copy Markdown
Owner

What and why

Migrates QuickAdd onto the shared forensic release pipeline in
chhoumann/obsidian-plugin-workflows
(pinned @v2, workflows-ref: v2). QuickAdd's old release path was a
manually dispatched semantic-release run; this replaces it with the
standing-PR model every plugin now shares: after green CI on master, the
per-repo App bot opens/refreshes one release PR, and merging that PR is the
sole release act
. A fix now lands once in the shared repo and every plugin
picks it up by bumping a pin.

The old release.yml (9 KB of inline logic), the semantic-release config +
dev deps, and version-bump.mjs are replaced by three thin caller stubs
(trigger + uses:); all logic lives in the shared reusables.

Line delta

+162 / -2620 across 8 files. The bulk is pnpm-lock.yaml (-2317, pruning the
semantic-release dependency tree) and the old release.yml internals (-223).
Three stubs total ~130 lines. 277 packages removed from the lockfile.

Parity audit vs the old flow

Every guarantee in the old release.yml was mapped to its new home in the
shared reusables.

Preserved:

Guarantee (old QuickAdd release.yml) New home (shared repo @v2)
Sigstore attestation over main.js / manifest.json / styles.css release.yml attest job (attest-build-provenance), plus post-publish gh attestation verify + per-asset re-hash (stronger than before)
GitHub App bot as release actor (quickadd-release-bot) release-prepare.yml mints the App token and authors the commit + PR as the bot
Least-privilege App token (contents/issues/pull-requests only) scoped per job in the reusables
persist-credentials: false while install/build/test runs preserved in the reusable build job
Build + test before publish (pnpm build, pnpm test) release.yml build job: build-command (pnpm run build) + verify-commands (lint, check, test)
Opt-in Slack + Discord notify (skipped when webhook unset) release.yml notify job, wired via slack-webhook / discord-webhook secrets
Serialized releases (no cancel-in-progress) concurrency on each stub + reusable

Gained (new forensic guarantees the old flow lacked): standing-PR
provenance checks, exact version-file-diff validation, commit-message/parent and
squash-tree binding, prior-tag ancestry + history-unchanged checks, a durable
release-run/<version> recovery branch, and no direct pushes to master
(releases go through a reviewable PR).

Deviations (intended, flagged - not silently dropped)

  1. Release model: manual dispatch -> PR merge. The old flow was triggered by
    hand (workflow_dispatch running semantic-release, which pushed the
    version commit + tag and created the release in one shot). The new flow is
    PR-to-release: the bot opens a standing version-bump PR and merging it is the
    release. No manual dispatch on the happy path (a workflow_dispatch escape
    hatch remains for dry-run/recovery).

  2. App-bot role changes. The App (quickadd-release-bot) previously only
    pushed semantic-release's output; commits were authored by
    semantic-release-bot. It now authors the release commit + PR in prepare,
    so forensic author checks bind to the App identity. This is why it needs a
    new permission (below).

  3. Per-release PR-comment DROPPED. The old flow ran find-pr + a
    github-script step to post a Release has been published: vX comment on the
    triggering PR. The shared pipeline has no equivalent, so this feature is gone.
    Flagging explicitly; if wanted, it would need to be added to the shared repo,
    not here (the stubs carry no logic).

  4. app-id is a repository VARIABLE, not a secret. The reusable
    release-prepare.yml takes app-id as a with: input, and GitHub does not
    allow the secrets context in a reusable-workflow with: block. QuickAdd
    currently stores RELEASE_APP_ID as a secret; a repo variable
    RELEASE_APP_ID must be created (see REQUIRED BEFORE MERGE). RELEASE_APP_PRIVATE_KEY
    stays a secret and carries over unchanged.

Test-file note

tests/release-workflow-hardening.test.ts was deleted. It textually
asserted the inline hardening of the old release.yml (App-token least
privilege, persist-credentials: false). That inline workflow is exactly what
the thin stub removes, so the test's subject no longer exists here; the
hardening is now covered by the shared repo's reusables and their tests.

Dry-run plan evidence

Ran the shared repo's release-plan.mjs against this repo's real git history
(node release-plan.mjs --cwd <quickadd> --package-manager pnpm).

Current master HEAD (405183c) - the post-2.19.0 chore(e2e) commits plan
a patch bump:

{"baseSha":"405183c...","previousVersion":"2.19.0","nextVersion":"2.19.1","releaseType":"patch","release":true,"schemaVersion":1}

Historical base 22e439d (the commit 2.19.0 released from) - reproduces the
real 2.19.0 release exactly:

{"baseSha":"22e439d...","previousVersion":"2.18.1","nextVersion":"2.19.0","releaseType":"minor","release":true,
 "notes":"# 2.19.0 ... ### Features\n* **ai:** provider-scoped model identity (#1499) ...\n* **settings:** craft pass on the choices list (#1500) ..."}

Precondition check (planner baseline)

Aligned - package.json 2.19.0 == latest tag 2.19.0 == latest published
GitHub release 2.19.0. No action needed.

Gates (all green locally)

  • pnpm run test: 3825 passed / 37 skipped (340 files).
  • pnpm run build-with-lint: green (tsc + eslint + esbuild; produces
    main.js + styles.css).
  • Three stubs: valid YAML (PyYAML) and actionlint clean.

REQUIRED BEFORE MERGE

The pipeline fails closed without these. CI (Test, Build + Lint, CodeQL,
etc.) is unaffected meanwhile; only releases are blocked until done.

  1. App slug - confirmed quickadd-release-bot. Verified via the API: the bot
    user quickadd-release-bot[bot] (id 293432345) exists, and the App holds
    always bypass on the master ruleset (Integration id 4046320, likely the
    App id). No action beyond confirming.
  2. Add Pull requests: Read and write to the App. It authors PRs now; today
    it likely only has Contents: write (for the old push). Without this, prepare
    cannot open the release PR.
  3. Create repository VARIABLE RELEASE_APP_ID (Settings -> Secrets and
    variables -> Actions -> Variables) with the App's numeric id. It currently
    exists only as a secret, which cannot be passed to the reusable's app-id
    with: input. The App id is likely 4046320 (the master-ruleset Integration
    bypass actor) - confirm from the App settings. RELEASE_APP_PRIVATE_KEY
    (secret) is unchanged.

Branch-protection bypass is already satisfied (the App is an always bypass
actor on master). After the three items above, smoke-test via Actions ->
Prepare release -> Run workflow with the # dry-run: true line uncommented,
before the first real release.

Do not auto-merge

Christian merges this himself after provisioning the App variable + permission.

Summary by CodeRabbit

  • New Features
    • Added release automation workflows to prepare, validate, and publish releases, including a manual “prepare release” flow with optional target selection.
    • Added an automatic release trigger for merged release PRs and streamlined the main release workflow to delegate execution to the shared release pipeline.
  • Documentation
    • Updated contribution and PR title guidelines to align Conventional Commit/release-pipeline versioning language and expanded accepted commit types to include release.
  • Chores
    • Removed legacy release tooling (helper script, hardening test) and cleaned up semantic-release development dependencies/overrides.

Replace the manual-dispatch semantic-release flow with three thin caller
stubs consuming the shared forensic PR-to-release pipeline in
chhoumann/obsidian-plugin-workflows, pinned at @v2.

- release-prepare.yml / release-trigger.yml / release.yml: caller stubs
  (trigger + uses:), all logic in the shared reusables.
- Remove the semantic-release config block, the semantic-release devDeps
  (@semantic-release/exec, @semantic-release/git, semantic-release), the
  now-dead @semantic-release/github>undici override, and version-bump.mjs.
- Keep buildGitInfo.mjs (build tooling for esbuild dev defines).
- Delete tests/release-workflow-hardening.test.ts: it pinned the inline
  hardening of the old release.yml, which the thin stub removes; those
  guarantees now live in the shared reusables.

The App bot (quickadd-release-bot) now authors the release commit + PR in
prepare instead of pushing semantic-release output. Attestation, the App
identity, and opt-in Slack/Discord notify are preserved; the per-release
PR-comment step is dropped.
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9854d44a-a095-4a20-a0db-46e7e2c58b7e

📥 Commits

Reviewing files that changed from the base of the PR and between 0f10885 and 4285526.

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

📝 Walkthrough

Walkthrough

The release process now uses separate preparation and validation workflows plus a reusable release execution workflow. The previous inline release implementation, semantic-release dependencies, version helper, and related guidance were removed or updated.

Changes

Release pipeline migration

Layer / File(s) Summary
Release preparation workflow
.github/workflows/release-prepare.yml
Adds CI-completion and manual triggers that pass release configuration and a target SHA to a reusable preparation workflow.
Merged release validation
.github/workflows/release-trigger.yml
Validates merged release/* pull requests targeting master and invokes the reusable validation workflow.
Reusable release execution
.github/workflows/release.yml
Replaces the inline release pipeline with a dispatch-only wrapper around the reusable release workflow, including verification, asset, and notification inputs.
Release tooling and guidance cleanup
package.json, AGENTS.md, .github/workflows/pr-title.yml, version-bump.mjs, tests/release-workflow-hardening.test.ts
Removes semantic-release packages, the version-bump helper, and the release hardening test, while updating release-related Conventional Commits guidance and validation.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CI
  participant Prepare
  participant Validate
  participant Release
  participant ReusableWorkflow
  CI->>Prepare: successful CI completion
  Prepare->>ReusableWorkflow: prepare release
  Validate->>ReusableWorkflow: validate merged release PR
  Validate->>Release: trigger release workflow
  Release->>ReusableWorkflow: execute release with metadata and checks
Loading

Possibly related PRs

Suggested labels: released

Poem

A bunny packed releases in a reusable cart,
From CI’s green start to the workflow’s heart.
Old tools hopped out of sight,
While release branches danced bright.
“Ship it!” cried Rabbit with delight.

🚥 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 is concise and accurately captures the main change: migrating to the shared release pipeline.
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 chore/shared-release-pipeline

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 11, 2026

Copy link
Copy Markdown

Deploying quickadd with  Cloudflare Pages  Cloudflare Pages

Latest commit: 4285526
Status: ✅  Deploy successful!
Preview URL: https://44ad1e8a.quickadd.pages.dev
Branch Preview URL: https://chore-shared-release-pipelin.quickadd.pages.dev

View logs

@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

🤖 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 32: The repository guidance references the shared release pipeline, but
the comment in the PR-title workflow still uses stale semantic-release
terminology. Update the relevant comment in the workflow so it consistently
describes releases as being determined by the shared pipeline, or remove the
outdated comment entirely.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a9ee3b5f-de70-48f2-8e86-93f59631ab96

📥 Commits

Reviewing files that changed from the base of the PR and between 405183c and c9243c6.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (7)
  • .github/workflows/release-prepare.yml
  • .github/workflows/release-trigger.yml
  • .github/workflows/release.yml
  • AGENTS.md
  • package.json
  • tests/release-workflow-hardening.test.ts
  • version-bump.mjs
💤 Files with no reviewable changes (3)
  • version-bump.mjs
  • tests/release-workflow-hardening.test.ts
  • package.json

Comment thread AGENTS.md
The shared release pipeline's standing PRs are titled
'release(version): Release <x.y.z>'; without this the pr-title check
red-flags every release PR (same fix as MetaEdit 6cc0763).
@chhoumann
chhoumann merged commit cd0a2d9 into master Jul 11, 2026
11 checks passed
@chhoumann
chhoumann deleted the chore/shared-release-pipeline branch July 11, 2026 12:01
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