|
| 1 | +## Why |
| 2 | +Today’s process requires maintainers to merge the Changesets PR, cut a tag, and draft the GitHub release by hand. npm publish then runs from our existing workflow after the GitHub release is published. The human-in-the-loop steps (versioning, tagging, release notes) slow us down and risk drift between npm, tags, and changelog. |
| 3 | + |
| 4 | +## What Changes |
| 5 | +- Use the single `changesets/action` on pushes to `main` to either open/update the version PR or, when the release PR is merged, run our publish command automatically using repository secrets. |
| 6 | +- Add a `release` script that builds and runs `changeset publish` so the action handles version bumps, changelog commits, npm publish, and GitHub releases end-to-end. |
| 7 | +- Enable `createGithubReleases: true` so GitHub releases are created from the changeset data right after publishing. |
| 8 | +- Document the automated flow, required secrets, guardrails, and recovery steps (rollback, hotfixes). |
| 9 | + |
| 10 | +## Two-Phase Rollout (Two PRs) |
| 11 | +1) Phase 1 — Dry run (no publish) |
| 12 | + - Update the existing `release-prepare.yml` to wire up `changesets/action` with `createGithubReleases: true` and a no-op `publish` command (e.g., `echo 'dry run'`). |
| 13 | + - Keep `.github/workflows/release-publish.yml` intact. This avoids any publish path changes while we verify that the version PR behavior and permissions are correct. |
| 14 | + - Add a repository guard (`if: github.repository == 'Fission-AI/OpenSpec'`) and a concurrency group for safety. |
| 15 | + |
| 16 | +2) Phase 2 — Enable publish and consolidate |
| 17 | + - Add `"release": "pnpm run build && pnpm exec changeset publish"` to `package.json`. |
| 18 | + - Change `release-prepare.yml` to use `with: publish: pnpm run release` and `env: NPM_TOKEN: \\${{ secrets.NPM_TOKEN }}` plus the default `GITHUB_TOKEN`. |
| 19 | + - Remove `.github/workflows/release-publish.yml` to avoid double-publish. Publishing now happens when the version PR is merged. |
| 20 | + |
| 21 | +## Guardrails |
| 22 | +- Concurrency: `concurrency: { group: release-\\${{ github.ref }}, cancel-in-progress: false }` on the workflow to serialize releases. |
| 23 | +- Repository/branch guard: run publish logic only on upstream `main` (`if: github.repository == 'Fission-AI/OpenSpec' && github.ref == 'refs/heads/main'`). |
| 24 | +- Permissions: ensure `contents: write` and `pull-requests: write` for opening/updating the version PR; `packages: read` optional. |
| 25 | + |
| 26 | +## Rollback and Hotfixes |
| 27 | +- Rollback: revert the release PR merge (which reverts version bumps/changelog); if a tag or GitHub release was created, delete the tag and release; deprecate the npm version if necessary (`npm deprecate @fission-ai/openspec@x.y.z 'reason'`). |
| 28 | +- Hotfix (urgent, no pending changesets): create a changeset for the fix and merge the release PR; in emergencies, run a manual bump/publish but reconcile with Changesets by adding a follow-up changeset to align versions. |
| 29 | + |
| 30 | +## Required Secrets |
| 31 | +- `NPM_TOKEN` with publish rights for the `@fission-ai` scope. |
| 32 | +- Default `GITHUB_TOKEN` (provided by GitHub) for opening/updating the version PR and creating GitHub releases. |
| 33 | + |
| 34 | +## How the Maintainer Flow Changes |
| 35 | +| Step | Current process | Future process | |
| 36 | +| --- | --- | --- | |
| 37 | +| Prepare release | Merge changeset PR, then manually draft release notes and tags | Merge release PR; action updates versions and handles changelog automatically | |
| 38 | +| Publish npm package | Happens automatically after GitHub release | Happens automatically via `changeset publish` invoked by the action | |
| 39 | +| GitHub release | Draft manually and sync with changelog | Action creates GitHub releases from changeset data | |
| 40 | +| Docs/process | Follow manual tagging/release steps | Docs describe automated flow + recovery and hotfix paths | |
| 41 | + |
| 42 | +## Impact |
| 43 | +- Automation: reuse `.github/workflows/release-prepare.yml` (phase 1: dry-run, phase 2: publish) and remove `.github/workflows/release-publish.yml` in phase 2. |
| 44 | +- Package metadata: add `release` script to `package.json`. |
| 45 | +- Docs: update README or `/docs` to show the automated flow, secrets, guardrails, and recovery steps. |
| 46 | + |
| 47 | +## Acceptance Criteria |
| 48 | +- Phase 1: merges to `main` open/update a version PR; on merge, the action’s `publish` step is a no-op; no npm publish occurs; logs confirm intended behavior; GitHub releases creation is wired but inert due to no publish. |
| 49 | +- Phase 2: merges to `main` run `pnpm run release` from the action; npm package publishes successfully; GitHub release is created automatically; `.github/workflows/release-publish.yml` is removed; no duplicate publishes occur. |
0 commit comments