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' 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.