Files
Fourier cbbb11b47f ci(release): add secret pre-flight, npm dry-run, and post-publish verify
- Pre-flight checks HOMEBREW_TAP_TOKEN and NPM_TOKEN are non-empty
  (catches empty-secret mistakes before anything runs)
- npm publish step now runs whoami + publish --dry-run before real publish
  (catches auth failures at the same step, not mid-release)
- Verify step polls npm view to confirm the version landed
  (fail fast if publish silently didn't work)

Prevents the v0.4.0 ghost release where GitHub had the tag but npm didn't.
2026-04-18 14:13:02 +08:00

110 lines
3.3 KiB
YAML

name: Release
on:
push:
tags:
- "v*"
permissions:
contents: write
packages: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Pre-flight — verify required secrets
env:
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
missing=0
check() {
if [ -z "$2" ]; then
echo "::error::Required secret $1 is empty or not set"
missing=1
else
echo "✓ $1 present (${#2} chars)"
fi
}
check HOMEBREW_TAP_TOKEN "$HOMEBREW_TAP_TOKEN"
check NPM_TOKEN "$NPM_TOKEN"
if [ $missing -eq 1 ]; then
echo "::error::Aborting release — fix secrets in repo settings before retrying."
exit 1
fi
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: stable
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
version: "~> v2"
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
registry-url: "https://registry.npmjs.org"
- name: Publish to npm
run: |
VERSION=${GITHUB_REF_NAME#v}
cd npm
# Sync version from git tag
node -e "const p=require('./package.json'); p.version='${VERSION}'; require('fs').writeFileSync('package.json', JSON.stringify(p,null,2)+'\n')"
# Copy LICENSE and README from repo root
cp ../LICENSE . 2>/dev/null || true
cp ../README.md . 2>/dev/null || true
# Pre-flight: verify auth works before publishing
echo "--- npm whoami ---"
npm whoami
echo "--- npm publish --dry-run ---"
npm publish --access public --dry-run
echo "--- npm publish ---"
npm publish --access public
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
- name: Verify npm publish succeeded
run: |
VERSION=${GITHUB_REF_NAME#v}
echo "Waiting for npm registry to propagate..."
for i in 1 2 3 4 5 6; do
sleep 10
published=$(npm view @4ier/notion-cli@${VERSION} version 2>/dev/null || true)
if [ "$published" = "${VERSION}" ]; then
echo "✓ @4ier/notion-cli@${VERSION} is live on npm"
exit 0
fi
echo "attempt $i: not yet visible, retrying..."
done
echo "::error::npm publish appears to have failed — @4ier/notion-cli@${VERSION} not visible after 60s"
exit 1