Files
zeekayandHanzo Dev 7465ba939c runs-on names a machine, not a purpose
The purpose-prefixed labels (hanzo-build-*, hanzo-deploy-*, hanzo-docs-build-*)
are retired in favour of the bare <os>-<arch> every runner already advertises.

They were not a capability, only a habit, and the habit cost builds: papers asked
for hanzo-build-linux-amd64, no online runner offered it, and two idle
linux-amd64 runners sat beside the queue while the build simply never ran. The
lux tree lost three days to lux-linux-amd64 the same way.

What a job is FOR is the workflow's name. runs-on is the machine it needs.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-15 11:38:27 -07:00

98 lines
4.2 KiB
YAML

name: Publish
# The one thing here allowed to reach a registry. Publishing follows a push
# to main instead of a GitHub release, so a version bump is the release —
# nothing else has to be remembered or clicked.
#
# No `paths:` filter, deliberately. The question is "does the registry serve
# something older than this tree?", and the comparison below is the only
# thing that reads the truth. A path gate guesses it from the shape of a
# diff, so a lockfile-only fix to a failed release matches no path and
# cannot re-run the job it repaired.
on:
push:
branches: [main]
workflow_dispatch:
# Serialized, newest wins. Two runs in flight both read the registry before
# either writes to it, so both believe the same version is unpublished and
# the slower one ships a stale tree under a number the faster one already
# defined.
concurrency:
group: publish
cancel-in-progress: true
jobs:
publish:
runs-on: [linux-amd64]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
with:
version: 8
run_install: false
- uses: actions/setup-node@v3
with:
node-version: '20.x'
registry-url: 'https://registry.npmjs.org'
cache: 'pnpm'
- run: pnpm install
# build, then test:coverage — the same pair package.json's own
# `preversion` script runs before a version bump — so this is the
# build gate too. It runs before the version becomes immutable rather
# than after: a broken `dist/` published under a real version cannot
# be taken back, only superseded.
- run: pnpm build
- run: pnpm test:coverage
- name: Publish if the tree is ahead of the registry
env:
KMS_CLIENT_ID: ${{ secrets.KMS_CLIENT_ID }}
KMS_CLIENT_SECRET: ${{ secrets.KMS_CLIENT_SECRET }}
run: |
set -euo pipefail
NAME=$(jq -r .name package.json)
NEW=$(jq -r .version package.json)
OLD=$(curl -sf "https://registry.npmjs.org/${NAME/\//%2f}" \
| jq -r '."dist-tags".latest // "0.0.0"' 2>/dev/null || echo "0.0.0")
# FORWARD ONLY. `!=` fires in both directions and a revert would
# walk the registry backwards; only a strictly greater local
# version is a release.
NEWEST=$(printf '%s\n%s\n' "$OLD" "$NEW" | sort -V | tail -1)
if [ "$OLD" = "$NEW" ] || [ "$NEWEST" != "$NEW" ]; then
echo "registry serves $OLD; tree is $NEW — nothing to publish."
exit 0
fi
# Only the KMS machine identity lives as an Actions secret. A registry
# token beside it would be a second home for one thing, and the one
# that rots unwatched — nothing reads it until a release day.
if [ -z "${KMS_CLIENT_ID:-}" ] || [ -z "${KMS_CLIENT_SECRET:-}" ]; then
echo "::error::KMS machine identity absent — cannot pull the publish credential. Seed KMS_CLIENT_ID/KMS_CLIENT_SECRET as Hanzo Git Actions secrets (org or repo scope)." >&2
exit 1
fi
KMS=https://kms.hanzo.ai; ENVN=prod
KT=$(curl -sf "$KMS/v1/kms/auth/login" -H 'Content-Type: application/json' \
-d "{\"clientId\":\"$KMS_CLIENT_ID\",\"clientSecret\":\"$KMS_CLIENT_SECRET\"}" | jq -r .accessToken)
[ -n "$KT" ] && [ "$KT" != null ] || { echo "::error::KMS login failed"; exit 1; }
# The org is the token's owner claim, not a path segment.
URL="$KMS/v1/kms/secrets/NPM_TOKEN?env=$ENVN"
# No -f: a `curl -sf` on a 404 exits 22 and kills the step before any
# message of ours prints, which reads like a broken network.
BODY=$(curl -s -w '\n%{http_code}' "$URL" -H "Authorization: Bearer $KT") || true
CODE=$(printf '%s' "$BODY" | tail -1)
NODE_AUTH_TOKEN=$(printf '%s' "$BODY" | sed '$d' | jq -r '.value // empty' 2>/dev/null || true)
if [ -z "$NODE_AUTH_TOKEN" ]; then
echo "::error::KMS returned HTTP $CODE for $URL with no value — seed NPM_TOKEN there, not as an Actions secret." >&2
exit 1
fi
echo "::add-mask::$NODE_AUTH_TOKEN"
export NODE_AUTH_TOKEN
echo "Publishing $NAME $OLD -> $NEW"
pnpm publish --no-git-checks