Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions .github/scripts/open-release-pr.mjs
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
#!/usr/bin/env node
// Open a release PR to main and enable auto-merge — without the gh CLI, which is not
// Open a release PR and enable auto-merge — without the gh CLI, which is not
// installed on the self-hosted runner. Uses the REST API to create the PR and the GraphQL
// API to enable auto-merge. Relies only on Node's global fetch (Node >= 22).
//
// The PR targets BASE_BRANCH (default: develop) — the version bump lands on develop
// first and reaches main through the normal develop -> main promotion, never by a
// direct push or PR to main.
//
// Required env: GH_TOKEN, GITHUB_REPOSITORY (owner/repo), VERSION, RELEASE_BRANCH.
// Optional env: BASE_BRANCH (default "develop").

const token = process.env.GH_TOKEN;
const repo = process.env.GITHUB_REPOSITORY;
const version = process.env.VERSION;
const branch = process.env.RELEASE_BRANCH;
const baseBranch = process.env.BASE_BRANCH || 'develop';

for (const [k, v] of Object.entries({ GH_TOKEN: token, GITHUB_REPOSITORY: repo, VERSION: version, RELEASE_BRANCH: branch })) {
if (!v) {
Expand Down Expand Up @@ -45,12 +51,13 @@ async function graphql(query, variables) {

const prBody =
`Automated version bump for v${version}. Tag \`v${version}\` and the npm publish already ` +
`completed; merging this lands the bumped package.json on main.`;
`completed; merging this lands the bumped package.json on \`${baseBranch}\`, from where it ` +
`is promoted to main through the regular ${baseBranch} -> main merge.`;

// Create the PR — or reuse an existing one for this branch (idempotent on re-run).
let { status, body } = await rest(`/repos/${owner}/${name}/pulls`, {
method: 'POST',
body: JSON.stringify({ title: `release: v${version}`, head: branch, base: 'main', body: prBody }),
body: JSON.stringify({ title: `release: v${version}`, head: branch, base: baseBranch, body: prBody }),
});

let pr;
Expand Down
9 changes: 6 additions & 3 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ jobs:
VERSION=$(node -p "require('./package.json').version")
echo "VERSION=${VERSION}" >> "$GITHUB_ENV"
echo "RELEASE_BRANCH=release/v${VERSION}" >> "$GITHUB_ENV"
# main is protected (requires a PR), so commit to a release branch and merge via PR.
# Never touch main directly: commit the bump to a release branch; a PR
# into develop is opened below, and develop is promoted to main manually.
git switch -c "release/v${VERSION}"
git add package.json
git commit -m "release: v${VERSION}"
Expand All @@ -71,13 +72,15 @@ jobs:
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

- name: Push release branch and tag, open auto-merge PR
- name: Push release branch and tag, open auto-merge PR into develop
if: ${{ inputs.dry-run != true }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BASE_BRANCH: develop
run: |
git push origin "${RELEASE_BRANCH}"
git push origin --tags
# gh CLI is not installed on the self-hosted runner — open the PR + enable
# auto-merge via the GitHub API (Node global fetch) instead.
# auto-merge via the GitHub API (Node global fetch) instead. The PR targets
# develop; main only receives the bump via the manual develop -> main merge.
node .github/scripts/open-release-pr.mjs
Loading