Skip to content

Commit b4ab4c3

Browse files
authored
chore: add release PR helper script (#19)
1 parent 3dbe613 commit b4ab4c3

File tree

2 files changed

+99
-4
lines changed

2 files changed

+99
-4
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -177,10 +177,10 @@ A few ground rules:
177177
## Releasing
178178

179179
- Add a changeset for user-facing updates: `pnpm changeset`
180-
- Merge PRs to `main` as usual.
181-
- The `Release` GitHub Action opens/updates a release PR with version bumps + `CHANGELOG.md`.
182-
- Merging that release PR publishes to npm and creates a GitHub release.
183-
- Release notes are auto-generated with pull requests, commit log, contributors, and a compare link.
180+
- Merge feature PRs to `main`.
181+
- Cut a release PR manually: `bash scripts/cut-release-pr.sh`
182+
- Merge the generated `chore: release` PR.
183+
- Run the `Release` workflow manually (`workflow_dispatch`) to publish npm + tag + GitHub release notes.
184184

185185
## Disclaimer
186186

scripts/cut-release-pr.sh

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
usage() {
5+
echo "Usage: scripts/cut-release-pr.sh [--dry-run]" >&2
6+
}
7+
8+
DRY_RUN="false"
9+
if [[ "${1:-}" == "--dry-run" ]]; then
10+
DRY_RUN="true"
11+
shift
12+
fi
13+
14+
if [[ $# -ne 0 ]]; then
15+
usage
16+
exit 1
17+
fi
18+
19+
if ! command -v gh >/dev/null 2>&1; then
20+
echo "GitHub CLI (gh) is required." >&2
21+
exit 1
22+
fi
23+
if ! command -v pnpm >/dev/null 2>&1; then
24+
echo "pnpm is required." >&2
25+
exit 1
26+
fi
27+
28+
ROOT_DIR="$(git rev-parse --show-toplevel)"
29+
cd "$ROOT_DIR"
30+
31+
if ! git diff --quiet || ! git diff --cached --quiet; then
32+
echo "Working tree is not clean. Commit or stash changes first." >&2
33+
exit 1
34+
fi
35+
36+
CURRENT_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
37+
if [[ "$CURRENT_BRANCH" != "main" ]]; then
38+
echo "Switching to main from $CURRENT_BRANCH"
39+
git checkout main
40+
fi
41+
42+
echo "Syncing main..."
43+
git fetch origin --prune
44+
git pull --ff-only origin main
45+
46+
TIMESTAMP="$(date +%Y%m%d-%H%M%S)"
47+
RELEASE_BRANCH="codex/release-${TIMESTAMP}"
48+
echo "Creating release branch: $RELEASE_BRANCH"
49+
git checkout -b "$RELEASE_BRANCH"
50+
51+
OLD_VERSION="$(node -p "require('./package.json').version")"
52+
echo "Running changeset versioning..."
53+
pnpm version-packages
54+
pnpm install --lockfile-only
55+
NEW_VERSION="$(node -p "require('./package.json').version")"
56+
57+
if git diff --quiet; then
58+
echo "No release changes generated (no pending changesets)."
59+
git checkout main
60+
git branch -D "$RELEASE_BRANCH"
61+
exit 0
62+
fi
63+
64+
echo "Version: $OLD_VERSION -> $NEW_VERSION"
65+
git add -A
66+
git commit -m "chore: release"
67+
68+
if [[ "$DRY_RUN" == "true" ]]; then
69+
echo "Dry run complete. Skipping push/PR creation."
70+
echo "Release commit created on $RELEASE_BRANCH."
71+
exit 0
72+
fi
73+
74+
git push -u origin "$RELEASE_BRANCH"
75+
76+
BODY_FILE="$(mktemp)"
77+
cat > "$BODY_FILE" <<EOF2
78+
## Description
79+
Cut release v${NEW_VERSION}.
80+
81+
## Summary
82+
- bump package version to \`${NEW_VERSION}\`
83+
- update \`CHANGELOG.md\`
84+
- consume pending changesets
85+
86+
## Checks
87+
- [x] npm run check
88+
- [x] npm run security
89+
EOF2
90+
91+
PR_URL="$(gh pr create --base main --head "$RELEASE_BRANCH" --title "chore: release" --body-file "$BODY_FILE")"
92+
rm -f "$BODY_FILE"
93+
94+
echo "Release PR created: $PR_URL"
95+
echo "After merge, run the Release workflow manually to publish/tag."

0 commit comments

Comments
 (0)