From 930187e52283d51baeff0a43c22da0b28ec971e3 Mon Sep 17 00:00:00 2001 From: Andrea Bueide Date: Mon, 2 Mar 2026 20:42:32 -0600 Subject: [PATCH 1/2] fix(ci): remove @semantic-release/git to avoid branch protection push Remove the @semantic-release/git plugin which pushes version bump commits and CHANGELOG.md back to the branch. The default github.token cannot push to protected branches, and this avoids the need for a PAT. Version source of truth is git tags + npm registry. Add a sync-versions devbox command to pull latest npm versions into package.json on demand. Update release docs accordingly. Co-Authored-By: Claude Opus 4.6 --- release.config.js | 4 ---- scripts/sync-versions.sh | 43 ++++++++++++++++++++++++++++++++++++++++ shells/devbox-fast.json | 1 + wiki/release.md | 15 ++++++++------ 4 files changed, 53 insertions(+), 10 deletions(-) create mode 100755 scripts/sync-versions.sh diff --git a/release.config.js b/release.config.js index 465bc0e7e..7e618588d 100644 --- a/release.config.js +++ b/release.config.js @@ -1,5 +1,3 @@ -const changelogFile = 'CHANGELOG.md'; - module.exports = { branches: ['master', { name: 'beta', prerelease: true }], tagFormat: '${name}-v${version}', @@ -9,10 +7,8 @@ module.exports = { '@semantic-release/release-notes-generator', { preset: 'conventionalcommits' }, ], - ['@semantic-release/changelog', { changelogFile }], ['@semantic-release/npm', { npmPublish: true, provenance: true }], ['@semantic-release/github', { successComment: false }], - ['@semantic-release/git', { assets: [changelogFile, 'package.json'] }], ], debug: true, }; diff --git a/scripts/sync-versions.sh b/scripts/sync-versions.sh new file mode 100755 index 000000000..51f911283 --- /dev/null +++ b/scripts/sync-versions.sh @@ -0,0 +1,43 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Syncs package.json version fields with the latest published npm versions. +# Run via: devbox run sync-versions + +PROJECT_ROOT="${PROJECT_ROOT:-$(git rev-parse --show-toplevel)}" + +updated=0 +skipped=0 + +for pkg_json in "$PROJECT_ROOT"/packages/*/package.json "$PROJECT_ROOT"/packages/plugins/*/package.json; do + [ -f "$pkg_json" ] || continue + + name=$(jq -r '.name' "$pkg_json") + private=$(jq -r '.private // false' "$pkg_json") + current=$(jq -r '.version' "$pkg_json") + + if [ "$private" = "true" ]; then + echo " skip $name (private)" + skipped=$((skipped + 1)) + continue + fi + + latest=$(npm view "$name" version 2>/dev/null || echo "") + if [ -z "$latest" ]; then + echo " skip $name (not on npm)" + skipped=$((skipped + 1)) + continue + fi + + if [ "$current" = "$latest" ]; then + echo " ok $name@$current" + skipped=$((skipped + 1)) + else + jq --arg v "$latest" '.version = $v' "$pkg_json" > "$pkg_json.tmp" && mv "$pkg_json.tmp" "$pkg_json" + echo " bump $name $current -> $latest" + updated=$((updated + 1)) + fi +done + +echo "" +echo "Done: $updated updated, $skipped unchanged/skipped" diff --git a/shells/devbox-fast.json b/shells/devbox-fast.json index 8fd86fdaf..59aaccc83 100644 --- a/shells/devbox-fast.json +++ b/shells/devbox-fast.json @@ -25,6 +25,7 @@ ], "format": ["treefmt"], "lint": ["treefmt --fail-on-change"], + "sync-versions": ["bash $SCRIPTS_DIR/sync-versions.sh"], "update-apps": [ "yarn install --no-immutable", "yarn e2e install --no-immutable", diff --git a/wiki/release.md b/wiki/release.md index edc5d9f80..cc9012dcb 100644 --- a/wiki/release.md +++ b/wiki/release.md @@ -4,26 +4,28 @@ This repo uses semantic-release with multi-semantic-release to version and publi ### Prerequisites -- Secrets: `GH_TOKEN` (repo `contents` write) and `NPM_TOKEN` (publish). CI also passes `YARN_NPM_AUTH_TOKEN` (same as `NPM_TOKEN`). +- Secrets: npm trusted publishing (OIDC) is configured per-package on npmjs.com. The workflow uses `github.token` for GitHub operations. - Git history: full clone (`fetch-depth: 0`) so semantic-release can find prior tags. - Commit format: conventional commits; commitlint is already configured. ### What runs - Config files: `release.config.js` (single-package defaults) and `multi-release.config.js` (multi-package orchestration, sequential init/prepare, ignore private packages, tag format/branches). -- Plugins: commit analyzer + release notes, changelog (`CHANGELOG.md`), npm publish, GitHub release (no success comment), and git commit of changelog + package.json. +- Plugins: commit analyzer + release notes, npm publish (with provenance), and GitHub release (no success comment). - Script: root `yarn release` runs `multi-semantic-release` with the above config per public package. ### CI/CD path (recommended) 1. Ensure `master`/`beta` are green. Merges must use conventional commits. -2. Trigger `Publish` workflow in Actions. Inputs are tokens only; workflow fetches full history, installs Devbox, then runs `devbox run release`. -3. Outputs: package tags (`${name}-vX.Y.Z`), npm publishes, GitHub releases, and updated changelog commits pushed back via the workflow token. +2. Trigger `Release` workflow in Actions. Choose type: `dry-run`, `beta`, or `production`. +3. Outputs: package tags (`${name}-vX.Y.Z`), npm publishes, and GitHub releases. + +Note: version bumps and changelogs are **not** committed back to the repo. The source of truth for versions is the git tags and npm registry. To sync the repo's `package.json` versions with npm, run `devbox run --config=shells/devbox-fast.json sync-versions` and include the changes in a PR. ### Local dry run -1. `GH_TOKEN= NPM_TOKEN= YARN_NPM_AUTH_TOKEN=` (GH token needs `contents` write; npm token can be automation/classic publish). -2. `devbox run release -- --dry-run` to see what would publish. Omit `--dry-run` to actually publish (only do this if you intend to release from your machine). +1. `GH_TOKEN= devbox run --config=shells/devbox-fast.json release-dry-run` (GH token needs `contents` read). +2. Omit `--dry-run` to actually publish (only do this if you intend to release from your machine; npm auth is handled via OIDC in CI). ### Tips and gotchas @@ -31,3 +33,4 @@ This repo uses semantic-release with multi-semantic-release to version and publi - Tag pattern is important: keep `${name}-v${version}` if you create manual tags for debugging. - If adding a new branch for releases, update both `release.config.js` and `multi-release.config.js`. - Keep yarn.lock in sync before releasing to avoid install differences between CI and local. +- `.npmrc` contains `workspaces-update=false` to prevent `npm version` from failing on Yarn's `workspace:` protocol. From d3a2ac1eea9c79f727c13595f1839cc229df88ac Mon Sep 17 00:00:00 2001 From: Andrea Bueide Date: Mon, 2 Mar 2026 20:59:06 -0600 Subject: [PATCH 2/2] fix(ci): override GITHUB_REF for beta releases semantic-release uses env-ci which reads GITHUB_REF to determine the current branch. Since workflow_dispatch runs from master, GITHUB_REF is refs/heads/master even after git checkout -B beta. This caused beta releases to publish as stable versions instead of prereleases. Override GITHUB_REF=refs/heads/beta in the beta release step so semantic-release correctly detects the beta branch and publishes prerelease versions with the @beta dist-tag. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 930f33808..f18b3033a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -69,6 +69,7 @@ jobs: run: devbox run --config=shells/devbox-fast.json release env: GH_TOKEN: ${{ github.token }} + GITHUB_REF: refs/heads/beta - name: Release (production) if: inputs.type == 'production'