mirror of
https://github.com/hanzoai/control.git
synced 2026-09-30 20:56:21 +00:00
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]>
79 lines
3.7 KiB
YAML
79 lines
3.7 KiB
YAML
name: Publish
|
|
|
|
# Publishing is the runner's job, not a laptop's. This file is the ONLY thing
|
|
# here allowed to reach npmjs.
|
|
#
|
|
# No `paths:` filter, deliberately, and the reasoning is hanzoai/ui's, learned
|
|
# there twice: the question is "does npmjs serve something older than this tree?"
|
|
# and the registry comparison below is the only thing that reads the truth. A
|
|
# path gate in front of it guesses from the shape of a diff, and a lockfile-only
|
|
# fix to a failed release then matches no path and cannot re-run the job it
|
|
# repaired. With no gate this is idempotent by construction — it publishes what
|
|
# is ahead of npmjs and nothing when nothing is — which is also what makes the
|
|
# manual dispatch safe.
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
publish:
|
|
runs-on: [linux-amd64]
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 24
|
|
registry-url: https://registry.npmjs.org
|
|
|
|
# There is no build: src/control.js is served to a browser byte-for-byte.
|
|
# A syntax error would reach every embedding site at once and read as a
|
|
# widget that silently never mounts, so this runs before the version is
|
|
# immutable rather than after.
|
|
- run: node --check src/control.js
|
|
|
|
- name: Publish if the tree is ahead of npmjs
|
|
env:
|
|
KMS_CLIENT_ID: ${{ secrets.KMS_CLIENT_ID }}
|
|
KMS_CLIENT_SECRET: ${{ secrets.KMS_CLIENT_SECRET }}
|
|
run: |
|
|
# 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 npm 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; }
|
|
URL="$KMS/v1/kms/secrets/NPM_TOKEN?env=$ENVN"
|
|
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
|
|
|
|
NAME=$(jq -r .name package.json)
|
|
NEW=$(jq -r .version package.json)
|
|
OLD=$(curl -sf "https://registry.npmjs.org/${NAME}" \
|
|
| 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. Asking the registry rather than the previous commit also
|
|
# survives a merge whose first parent already carries the bump.
|
|
NEWEST=$(printf '%s\n%s\n' "$OLD" "$NEW" | sort -V | tail -1)
|
|
if [ "$OLD" = "$NEW" ] || [ "$NEWEST" != "$NEW" ]; then
|
|
echo "npmjs serves $OLD; tree is $NEW — nothing to publish."
|
|
exit 0
|
|
fi
|
|
echo "Publishing $NAME $OLD -> $NEW"
|
|
npm publish --access public
|