Files
hyperframes/.github/workflows/publish.yml
JamesandClaude Opus 4.6 bce1a11e71 chore(ci): simplify release process to a single workflow
The 3-workflow chain (release.yml → release-tag.yml → publish.yml) was
broken by design: tags created by GITHUB_TOKEN don't trigger other
workflows, so merging a release PR never actually published.

Consolidate into a single publish.yml that triggers on both tag push
and release PR merge. Delete the redundant prepare-release and
tag-release workflows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 07:32:38 +00:00

126 lines
4.3 KiB
YAML

name: Publish to npm
on:
push:
tags:
- "v*"
pull_request:
types: [closed]
branches: [main]
jobs:
publish:
name: Publish
runs-on: ubuntu-latest
timeout-minutes: 10
environment: npm-publish
permissions:
contents: write
id-token: write
# Run on tag push OR when a release/* PR is merged
if: >-
github.event_name == 'push' ||
(github.event.pull_request.merged == true &&
startsWith(github.event.pull_request.head.ref, 'release/v'))
steps:
- uses: actions/checkout@v4
- name: Resolve version
id: version
run: |
if [ "${{ github.event_name }}" = "push" ]; then
echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
else
BRANCH="${{ github.event.pull_request.head.ref }}"
echo "version=${BRANCH#release/v}" >> "$GITHUB_OUTPUT"
fi
- name: Create release tag
if: github.event_name == 'pull_request'
run: |
git tag "v${{ steps.version.outputs.version }}"
git push origin "v${{ steps.version.outputs.version }}"
- uses: oven-sh/setup-bun@v2
- uses: actions/setup-node@v4
with:
node-version: 24
registry-url: "https://registry.npmjs.org"
- run: corepack enable
- run: corepack prepare pnpm@10.17.1 --activate
- run: bun install --frozen-lockfile
- run: bun run build
- run: bun run verify:packed-manifests
- name: Publish packages
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
VERSION="${{ steps.version.outputs.version }}"
FAILED=0
publish_pkg() {
local filter="$1"
local name="$2"
# Check if this version is already published
if npm view "${name}@${VERSION}" version >/dev/null 2>&1; then
echo "⏭️ ${name}@${VERSION} already published — skipping"
return 0
fi
echo "📦 Publishing ${name}@${VERSION}..."
if pnpm --filter "$filter" publish --access public --no-git-checks; then
echo "✅ ${name}@${VERSION} published"
else
echo "❌ ${name}@${VERSION} failed to publish"
FAILED=1
fi
}
publish_pkg "@hyperframes/core" "@hyperframes/core"
publish_pkg "@hyperframes/engine" "@hyperframes/engine"
publish_pkg "@hyperframes/producer" "@hyperframes/producer"
publish_pkg "@hyperframes/studio" "@hyperframes/studio"
# CLI is @hyperframes/cli in the monorepo but published as unscoped "hyperframes" on npm.
# Rewrite the name in package.json before publishing, then use npm publish directly
# since pnpm --filter won't match the rewritten name.
if npm view "hyperframes@${VERSION}" version >/dev/null 2>&1; then
echo "⏭️ hyperframes@${VERSION} already published — skipping"
else
node -e "
const fs = require('fs');
const p = 'packages/cli/package.json';
const pkg = JSON.parse(fs.readFileSync(p, 'utf8'));
pkg.name = 'hyperframes';
fs.writeFileSync(p, JSON.stringify(pkg, null, 2) + '\n');
"
echo "📦 Publishing hyperframes@${VERSION}..."
if (cd packages/cli && npm publish --access public); then
echo "✅ hyperframes@${VERSION} published"
else
echo "❌ hyperframes@${VERSION} failed to publish"
FAILED=1
fi
fi
if [ "$FAILED" -ne 0 ]; then
echo "::error::One or more packages failed to publish"
exit 1
fi
- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION="${{ steps.version.outputs.version }}"
# Skip if release already exists (idempotent re-runs)
if gh release view "v${VERSION}" --repo "${{ github.repository }}" >/dev/null 2>&1; then
echo "Release v${VERSION} already exists — skipping"
else
gh release create "v${VERSION}" \
--repo "${{ github.repository }}" \
--title "v${VERSION}" \
--generate-notes
fi