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
110 changes: 94 additions & 16 deletions .github/workflows/release_alpha.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,97 @@
# Tags and publishes an alpha release when its release PR is merged.
#
# Triggered when a `release/alpha-*` PR (opened by "Prepare Alpha Release") is
# merged into `alpha`. It builds, pushes the `v<version>` tag, and publishes
# @reearth/core to the npm `alpha` dist-tag.
#
# Publishing is secured via npm Trusted Publishing (OIDC): no NPM_TOKEN, no PAT,
# no GitHub App. Auth is a short-lived OIDC handshake and every publish carries
# a provenance attestation (verify with `npm audit signatures`).
#
# Tag + publish are combined into this single job on purpose: a tag pushed by
# GITHUB_TOKEN does not trigger other workflows, so publishing here (rather than
# in a separate `on: push: tags` workflow) is what lets us avoid a privileged
# token entirely.
#
# npm Trusted Publisher (one-time, already configured on npmjs.com):
# @reearth/core -> repo reearth/core, workflow release_alpha.yml, action
# "npm publish". Keep this file named release_alpha.yml so that stays valid.
#
# beta/latest still publish via npm_release.yml + NPM_TOKEN and are unaffected.

name: Release Alpha

on:
push:
branches: alpha
paths-ignore:
- "package.json"
workflow_dispatch:
pull_request:
types: [closed]

permissions:
contents: write # push the version tag
id-token: write # OIDC token for npm Trusted Publishing + provenance

jobs:
release:
permissions:
contents: write
uses: reearth/core/.github/workflows/npm_release.yml@beta
with:
branch: alpha
tag: alpha
version-args: --preid alpha prerelease
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
PAT: ${{ secrets.PAT }}
publish:
name: Tag and publish alpha
runs-on: ubuntu-latest
# Gates the whole job (tag + publish) on a required reviewer approving the
# npm-publish environment, so a merged PR can't auto-publish unreviewed.
environment: npm-publish
# Only for merged release PRs into alpha (not every closed PR).
if: >-
github.event.pull_request.merged == true &&
github.event.pull_request.base.ref == 'alpha' &&
startsWith(github.event.pull_request.head.ref, 'release/alpha-')
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.merge_commit_sha }}
- uses: actions/setup-node@v4
with:
# Trusted Publishing requires Node >=22.14 and npm >=11.5.1. Pin a
# concrete >=22.14 version so the floor can't regress via runner
# installer changes.
node-version: 22.14.0
registry-url: "https://registry.npmjs.org"
- name: Activate npm via corepack
# Node 22 ships npm 10.x; Trusted Publishing needs >=11.5.1. corepack
# fetches a fresh npm binary, avoiding the broken self-upgrade path.
run: |
corepack enable npm
corepack prepare npm@11.5.1 --activate
npm --version
- name: Run install
run: yarn install --frozen-lockfile
- name: Build
run: yarn build
- name: Verify tag matches package.json version
id: version
run: |
VERSION=$(node -p "require('./package.json').version")
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"
echo "Publishing @reearth/core@$VERSION"
- name: Create and push tag
run: |
TAG="${{ steps.version.outputs.tag }}"
HEAD_SHA=$(git rev-parse HEAD)
# Commit the remote tag points to (peel annotated tags via ^{}); empty
# if the tag does not exist remotely.
REMOTE_SHA=$(git ls-remote --tags origin "refs/tags/${TAG}^{}" | awk '{print $1}')
[ -z "$REMOTE_SHA" ] && REMOTE_SHA=$(git ls-remote --tags origin "refs/tags/${TAG}" | awk '{print $1}')
if [ -n "$REMOTE_SHA" ]; then
if [ "$REMOTE_SHA" = "$HEAD_SHA" ]; then
echo "Tag ${TAG} already exists and matches HEAD; skipping tag push."
else
echo "::error::Tag ${TAG} already exists but points to ${REMOTE_SHA}, not the release commit ${HEAD_SHA}. Refusing to publish a mismatched build."
exit 1
fi
else
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git tag -a "${TAG}" -m "${TAG}"
git push origin "${TAG}"
fi
- name: Publish to npm with provenance (OIDC)
# No NPM_TOKEN: auth is the OIDC handshake configured as a Trusted
# Publisher on npmjs.com. --access public because @reearth/core is scoped.
run: npm publish --provenance --access public --tag alpha
63 changes: 63 additions & 0 deletions .github/workflows/release_alpha_prepare.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Prepares an alpha release.
#
# Dispatch this workflow on the `alpha` branch. It bumps the alpha prerelease
# version, commits it to a `release/alpha-<version>` branch, and opens a PR
# into `alpha`. Merging that PR triggers release_alpha.yml, which tags the
# release and publishes to npm (dist-tag `alpha`) via OIDC.
#
# Uses only the built-in GITHUB_TOKEN: no PAT, no GitHub App. The version bump
# never touches the protected `alpha` branch directly; it goes through the PR,
# so no branch-protection bypass is required.

name: Prepare Alpha Release

on:
workflow_dispatch:

permissions:
contents: write # push the release/alpha-* branch
pull-requests: write # open the release PR

jobs:
prepare:
name: Open alpha release PR
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/alpha'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22.14.0
- name: Set up git user
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
- name: Run install
run: yarn install --frozen-lockfile
- name: Bump alpha prerelease version
id: bump
# --no-git-tag-version: we commit the bump onto the release branch
# ourselves; the tag is created later by the publish workflow. This
# still runs the preversion (yarn test run) and version (yarn build)
# npm scripts, so tests and the build gate the bump.
run: |
npm version --preid alpha prerelease --no-git-tag-version
VERSION=$(node -p "require('./package.json').version")
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Create release branch and PR
env:
VERSION: ${{ steps.bump.outputs.version }}
GH_TOKEN: ${{ github.token }}
run: |
BRANCH="release/alpha-${VERSION}"
git checkout -b "$BRANCH"
git add package.json
git commit -m "chore: release ${VERSION}"
git push origin "$BRANCH"
gh pr create \
--base alpha \
--head "$BRANCH" \
--title "chore: release ${VERSION}" \
--body "Prepares alpha release \`${VERSION}\`.

Merging this PR tags \`v${VERSION}\` and publishes \`@reearth/core@${VERSION}\` to the npm \`alpha\` dist-tag via OIDC trusted publishing (with provenance)."
Loading