mirror of
https://github.com/hanzo-apps/industries.git
synced 2026-10-30 14:47:50 +00:00
hanzo-build-linux-amd64, lux-build-linux-amd64, zoo-build-linux-amd64 and every other org-prefixed spelling all meant the same machine. Which org a job belongs to does not change which host can build it, so the org bought one pool name per org per arch and each could go stale on its own -- the evo host alone answered to fourteen names for one label. One vocabulary now: linux-amd64, linux-arm64, macos-arm64, win-amd64. The generic labels every plain workflow uses (ubuntu-latest, self-hosted) are untouched, so naive CI keeps working. Co-authored-by: Hanzo Dev <[email protected]>
97 lines
4.1 KiB
YAML
97 lines
4.1 KiB
YAML
name: deploy
|
|
|
|
# hanzo.industries is a SITE, not an App: a static export with no compute. It ships on the
|
|
# Sites plane. Not GitHub Pages, not Cloudflare Pages, and not an image — baking
|
|
# files that never execute into a container so a Go binary can serve them means an
|
|
# image, a push, a tag pinned in a CR and running pods, all to hand back bytes.
|
|
#
|
|
# build -> out
|
|
# -> site
|
|
#
|
|
# The publish mechanics are NOT here. They are bin/site in hanzoai/ci, reached
|
|
# through its action, and every static surface in the fleet calls that one
|
|
# script — ensure-project, enqueue, presigned per-file upload, complete. A
|
|
# contract transcribed per repo is a contract that drifts, and this file used to
|
|
# carry its own copy of every call. It also SELF-PROVISIONS: the project is
|
|
# created idempotently before the enqueue, so committing this file is enough to
|
|
# stand the site up.
|
|
#
|
|
# The secrets are the KMS machine identity, and the action reads the deploy key
|
|
# from KMS with them. They are set ON THE FORGE: this file lives under
|
|
# .hanzo/workflows/, which only git.hanzo.ai reads, so GitHub's secret store is
|
|
# not in this path at all.
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
group: deploy-${{ github.ref }}
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
site:
|
|
# NOT ubuntu-latest. This file lives in .hanzo/workflows, which GitHub never
|
|
# reads — git.hanzo.ai is the only thing that can run it, and its fleet
|
|
# advertises linux-amd64. An unmatched label is not an error here,
|
|
# it is silence: the job queues until the 24h timeout and nothing says so.
|
|
runs-on: linux-amd64
|
|
timeout-minutes: 30
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22'
|
|
|
|
- name: build the static export
|
|
env:
|
|
NEXT_TELEMETRY_DISABLED: '1'
|
|
NEXT_PUBLIC_PUBLISHABLE_KEY: ${{ secrets.PUBLISHABLE_KEY }}
|
|
run: |
|
|
set -euo pipefail
|
|
corepack enable && corepack prepare [email protected] --activate
|
|
pnpm install --frozen-lockfile
|
|
pnpm build
|
|
test -s out/index.html || { echo "::error::next build produced no out/index.html"; exit 1; }
|
|
echo "exported $(find out -type f | wc -l) files"
|
|
|
|
# This gate has caught real breakage, so it runs against the SAME out/ that
|
|
# gets synced. No `cp out/index.html out/404.html`: every route here is a
|
|
# real exported file, so clobbering the 404 would make a broken link answer
|
|
# 404 while rendering the front page.
|
|
- name: smoke test the export
|
|
run: |
|
|
set -euo pipefail
|
|
pnpm dlx serve out -l 3333 &
|
|
SERVER_PID=$!
|
|
for i in $(seq 1 30); do
|
|
curl -sf -o /dev/null http://localhost:3333 && { echo "server ready after ${i}s"; break; }
|
|
sleep 1
|
|
done
|
|
BODY=$(curl -s http://localhost:3333)
|
|
kill $SERVER_PID 2>/dev/null || true
|
|
echo "$BODY" | grep -q "Application error" && { echo "::error::homepage renders 'Application error'"; exit 1; }
|
|
FAILED=0
|
|
for page in index about research contact careers news ai-models; do
|
|
[ -f "out/${page}.html" ] || [ -f "out/${page}/index.html" ] || { echo "::error::missing page ${page}"; FAILED=1; }
|
|
done
|
|
[ "$FAILED" = "0" ]
|
|
echo "all smoke tests passed"
|
|
|
|
# ONE credential, and the action reads it from KMS: the machine identity is
|
|
# what travels, and the deploy key is resealed in one place rather than
|
|
# copied into every org's secret store. The 202 carries a prefix-scoped,
|
|
# 30-minute presigned POST grant, so nothing here holds a bucket key. Do NOT
|
|
# add SITES_S3_* — that is the standing shared-bucket credential the grant
|
|
# replaced, and it could overwrite every other org's site.
|
|
- name: Publish to the Sites plane
|
|
uses: https://git.hanzo.ai/hanzoai/ci/.github/actions/site@v1
|
|
with:
|
|
slug: hanzo-industries
|
|
dir: out
|
|
env:
|
|
KMS_CLIENT_ID: ${{ secrets.KMS_CLIENT_ID }}
|
|
KMS_CLIENT_SECRET: ${{ secrets.KMS_CLIENT_SECRET }}
|