From 893b0eb7bc0f3f1917c66e8c1c1ca2f1302d3f27 Mon Sep 17 00:00:00 2001 From: Theo Gravity Date: Mon, 4 May 2026 02:10:58 -0700 Subject: [PATCH] chore(ci): adopt monorel v1.0.0 and consolidate to one workflow monorel v1.0.0 ships `monorel auto`, a single command that detects whether HEAD is a release-PR merge and dispatches to either the post-merge release pipeline (tag, push, publish) or the pre-merge maintenance pipeline (apply changesets onto a staging branch, force-push, upsert the always-open release PR). The action wrapper no longer takes a `command` input; one workflow with one step does both jobs. Changes: - **Delete `release-pr.yml`.** Its job (upsert the release PR) is now done by `monorel auto` on every non-release push. - **Rewrite `release.yml`** as the single consolidated workflow. Single `monorel` job runs the v1.0.0 action on every push to `main` and lets the action route. The `deploy-docs` job (called via `workflow_call` from `docs.yml`) gates on `chore(release):` so docs deploy only on the release-PR merge, not on every feature merge. - **Bump action pin** from `v0.14.0` to `v1.0.0`. - **Update AGENTS.md** to describe the new single-workflow model in the CI / Release Workflows section. Kept: - `actions/setup-go@v5` with `go-version: '1.25'` and `cache: true`. monorel still runs offline tidy with `GOTOOLCHAIN=local`, so the runner's Go must satisfy every sub-module's `go` directive. - The `if: ... !startsWith(..., 'chore(release):')` skip filter on `ci.yml` jobs (PR #80). The race the filter prevents (CI tidy vs release tag-push) still applies under the consolidated workflow. - `workflow_dispatch` as a manual escape hatch. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/release-pr.yml | 48 ------------------------- .github/workflows/release.yml | 61 ++++++++++++++++---------------- AGENTS.md | 25 ++++++------- 3 files changed, 44 insertions(+), 90 deletions(-) delete mode 100644 .github/workflows/release-pr.yml diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml deleted file mode 100644 index e73a702..0000000 --- a/.github/workflows/release-pr.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: release-pr - -# Maintains the always-open release PR. Fires on every push to main -# except the chore(release): merge commit (which is the merge of the -# release PR itself; reprocessing it would churn the just-merged PR). -# -# The PR aggregates pending .changeset/*.md files into a rendered plan -# and updates / opens / closes itself based on whether any changesets -# remain after each push. -# -# Drives every release end-to-end together with release.yml. - -on: - push: - branches: [main] - -permissions: - contents: write - pull-requests: write - -jobs: - release-pr: - # Skip on the release PR's own merge commit. Heuristic: subject - # begins with "chore(release):" by monorel-bot convention. If a - # human ever authors a hand-titled "chore(release):" commit, the - # workflow will skip there too — switch to filtering by - # github.event.head_commit.author.username == 'monorel-bot[automation]' - # if that becomes a problem. - if: ${{ !startsWith(github.event.head_commit.message, 'chore(release):') }} - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - # monorel runs `go mod tidy` with GOTOOLCHAIN=local during release, - # so Go must already be installed at a version satisfying every - # released sub-module's `go` directive (every sub-module here is - # `go 1.25.0`). - - uses: actions/setup-go@v5 - with: - go-version: '1.25' - cache: true - cache-dependency-path: '**/go.sum' - - - uses: disaresta-org/monorel/ci/github@v0.14.0 - with: - command: pr diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 43a6682..233703b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,29 +1,29 @@ name: release -# Cuts the release after the always-open release PR is merged. -# Triggers: -# push (main, "chore(release):") — the standard path; the merge -# commit of the release PR carries that subject by monorel -# convention. -# workflow_dispatch — manual escape hatch. +# Single-step release pipeline using monorel v1's `monorel auto`. +# Fires on every push to main. The action's `monorel auto` step +# detects whether HEAD is a release-PR merge: # -# Pipeline (inside disaresta-org/monorel/ci/github with command:release): -# 1. monorel tag — read HEAD's monorel-Release: trailers -# (written upstream by `monorel apply` on -# the staging branch — see release-pr.yml) -# and create per-package tags locally. -# The merge already brought the file -# changes (CHANGELOGs + changeset deletions) -# onto main from the release PR. -# 2. git push --follow-tags — push the new tags to the remote so -# the provider can validate them. -# 3. monorel publish — create one GitHub Release per tag, body -# sourced from each tag's CHANGELOG entry. +# - On a regular feature merge: applies pending `.changeset/*.md` +# files onto a staging branch, force-pushes, and upserts the +# always-open release PR. The PR's body shows the rendered +# plan; its diff IS the file changes the next release will +# produce. +# - On the merge of that release PR (subject `chore(release): ...`): +# creates per-package tags from HEAD's `monorel-Release:` +# trailers, pushes them with `--follow-tags`, and creates one +# GitHub Release per tag with the body sourced from each tag's +# CHANGELOG entry. # -# Then deploy-docs runs as a workflow_call. Releases created via +# `deploy-docs` runs as a workflow_call after the action completes, +# but only on the `chore(release):` commit so we don't redeploy the +# docs site on every feature merge. Releases created via # secrets.GITHUB_TOKEN do not propagate `release: published` events # (GitHub anti-recursion), so docs.yml's release trigger never fires # from a monorel-driven release; we call docs.yml directly here. +# +# Replaces the v0.x split of release-pr.yml + release.yml. Single +# workflow, single step, no `command` input. on: push: @@ -32,33 +32,34 @@ on: permissions: contents: write + pull-requests: write jobs: - release: - if: github.event_name == 'workflow_dispatch' || startsWith(github.event.head_commit.message, 'chore(release):') + monorel: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - # monorel runs `go mod tidy` with GOTOOLCHAIN=local during release, - # so Go must already be installed at a version satisfying every - # released sub-module's `go` directive (every sub-module here is - # `go 1.25.0`). + # monorel runs `go mod tidy` with GOTOOLCHAIN=local during the + # release path, so Go must already be installed at a version + # satisfying every released sub-module's `go` directive (every + # sub-module here is `go 1.25.0`). - uses: actions/setup-go@v5 with: go-version: '1.25' cache: true cache-dependency-path: '**/go.sum' - - uses: disaresta-org/monorel/ci/github@v0.14.0 - with: - command: release + - uses: disaresta-org/monorel/ci/github@v1.0.0 deploy-docs: - needs: release - if: ${{ needs.release.result == 'success' }} + # Only deploy docs on the release-PR merge commit, not on every + # feature merge. `monorel auto` does PR-upsert work on those + # pushes; nothing in the docs site changes from upserting a PR. + if: ${{ github.event_name == 'workflow_dispatch' || startsWith(github.event.head_commit.message, 'chore(release):') }} + needs: monorel uses: ./.github/workflows/docs.yml permissions: contents: read diff --git a/AGENTS.md b/AGENTS.md index da20212..501da0a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -234,12 +234,13 @@ The release-please-era gotchas (`release-as` initial-version dance, squash-merge GitHub Pages on main push, also called by `release.yml` after a monorel-driven release (workflow_call sidesteps GitHub's anti-recursion for `GITHUB_TOKEN`-created releases). -- **release-pr.yml**: triggered on push to `main`. Runs `monorel preview --upsert` - to maintain the always-open release PR. -- **release.yml**: triggered on push to `main` for the `chore(release):` - merge commit (or via `workflow_dispatch`). Runs the release pipeline: - `monorel release` → `git push --follow-tags` → `monorel publish`. - Then calls `docs.yml` via `workflow_call`. +- **release.yml**: triggered on every push to `main` (or via `workflow_dispatch`). + Runs `monorel auto` via the `disaresta-org/monorel/ci/github@v1` action, + which detects whether HEAD is a release-PR merge: on a regular feature + merge it upserts the always-open release PR; on the `chore(release):` + merge it tags, pushes, and publishes per-package GitHub Releases. After + the action completes on a `chore(release):` push, `deploy-docs` runs + via `workflow_call`. - **pr-title.yml**: validates that PR titles follow Conventional Commits for git-history hygiene. Allowed types match the scoped-commit convention above. @@ -249,14 +250,14 @@ To cut a release: 1. Land changes on `main` via PRs that include a `.changeset/.md` file when a release is desired. Use `monorel add --package ":"` to author one, or hand-roll the file. -2. The release-pr workflow updates the always-open release PR after each - push to `main`. The PR body shows the rendered plan (per-package - `from`/`to` versions plus the changelog body for each). +2. The release workflow's `monorel auto` step updates the always-open + release PR after each push to `main`. The PR body shows the rendered + plan (per-package `from`/`to` versions plus the changelog body for each). 3. Edit `docs/src/whats-new.md` to add the user-facing summary if relevant — monorel doesn't touch this file. -4. Merge the release PR. The release.yml workflow runs the pipeline: - writes per-package CHANGELOG entries, deletes the consumed - `.changeset/*.md` files, creates per-package tags, pushes, and +4. Merge the release PR. The release workflow's `monorel auto` step + detects the `chore(release):` merge, creates per-package tags from + the merge commit's `monorel-Release:` trailers, pushes them, and creates one GitHub Release per tag. ## Vulnerability scanning (advisory, not gating)