Compare commits
17
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
401e415c01 | ||
|
|
5106bdeada | ||
|
|
0339fc7dee | ||
|
|
0542e97a06 | ||
|
|
265f807635 | ||
|
|
c06948b467 | ||
|
|
2ef5d47f94 | ||
|
|
3a9e055c45 | ||
|
|
8ae1c46625 | ||
|
|
9d18d4a6ba | ||
|
|
ecc3da75f0 | ||
|
|
d425a88e9a | ||
|
|
fb096091b3 | ||
|
|
aadb7a04c0 | ||
|
|
599667e100 | ||
|
|
2bc3b2e1a9 | ||
|
|
572c712140 |
@@ -85,7 +85,7 @@ jobs:
|
||||
# One enqueue per (image, platform), mirroring the buildx tag shape the
|
||||
# deploy path expects (`sha-<short>-<arch>[-<suffix>]`). Default arch is
|
||||
# amd64 (single-arch), so an existing repo's tag shape is unchanged.
|
||||
python3 -c "import yaml,json;print(json.dumps(yaml.safe_load(open('hanzo.yml'))['images']))" | jq -c '.[]' | while read -r img; do
|
||||
python3 -c "import yaml,json;print(json.dumps(yaml.safe_load(open('hanzo.yml')).get('images') or []))" | jq -c '.[]' | while read -r img; do
|
||||
name=$(echo "$img"|jq -r .name); repo=$(echo "$img"|jq -r .repo)
|
||||
ctx=$(echo "$img"|jq -r .context); df=$(echo "$img"|jq -r '.dockerfile // (.context+"/Dockerfile")')
|
||||
sfx=$(echo "$img"|jq -r '."tag-suffix" // ""')
|
||||
@@ -184,6 +184,22 @@ jobs:
|
||||
# KUBECONFIG — cluster access for the deploy step.
|
||||
ORG="$(python3 -c "import yaml;print((yaml.safe_load(open('hanzo.yml')).get('kms') or {}).get('org','') )" 2>/dev/null || true)"
|
||||
: "${ORG:=${KMS_ORG:-}}"
|
||||
# Systemic default: when neither hanzo.yml `kms.org` nor the KMS_ORG var
|
||||
# is set, derive the KMS org from the GitHub owner. The org → KMS-org
|
||||
# relation is a small, stable first-party fact; keeping it here (ONE
|
||||
# place) is why every repo gets the canonical KMS deploy-cred path with
|
||||
# zero per-repo config — before this, ORG was always empty and this whole
|
||||
# step short-circuited, so no build ever fetched its private-dep git
|
||||
# credential from KMS (it silently fell back to GH_PAT and failed on
|
||||
# private hanzoai/cloud). hanzo.yml `kms.org` and KMS_ORG still override.
|
||||
if [ -z "$ORG" ]; then
|
||||
case "${{ github.repository_owner }}" in
|
||||
hanzoai) ORG=hanzo ;;
|
||||
luxfi) ORG=lux ;;
|
||||
zooai) ORG=zoo ;;
|
||||
*) ORG="${{ github.repository_owner }}" ;;
|
||||
esac
|
||||
fi
|
||||
ENV="$(python3 -c "import yaml;print((yaml.safe_load(open('hanzo.yml')).get('kms') or {}).get('environment','prod'))" 2>/dev/null || echo prod)"
|
||||
PATHQ="$(python3 -c "import yaml;print((yaml.safe_load(open('hanzo.yml')).get('kms') or {}).get('path','/deploy').strip('/'))" 2>/dev/null || echo deploy)"
|
||||
if [ -z "${KMS_CLIENT_ID:-}" ] || [ -z "$ORG" ]; then
|
||||
@@ -207,6 +223,12 @@ jobs:
|
||||
GH_PAT: ${{ secrets.GH_PAT }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# `images:` is OPTIONAL. A repo that ships no container image — e.g. a
|
||||
# static site deployed via Cloudflare Pages (its own deploy.yml), which
|
||||
# imports this reusable purely for the `test:` lint gate — omits the key
|
||||
# entirely. `.get('images') or []` yields an empty list, the loop below
|
||||
# runs zero times, and no cross-org GHCR push is attempted (so a repo in
|
||||
# a different GitHub org never hits `denied: permission_denied`).
|
||||
# Build-time private cross-org Go module read (the buildx `gh_token`
|
||||
# secret): prefer the KMS-fetched GIT_TOKEN, else fall back to the org
|
||||
# GH_PAT — the SAME BuildKit gh_token cloud's release.yml uses (proven
|
||||
@@ -219,7 +241,7 @@ jobs:
|
||||
SHORT=$(echo "${{ github.sha }}" | cut -c1-7)
|
||||
IS_TAG=$([ "${{ github.ref_type }}" = "tag" ] && echo 1 || echo 0)
|
||||
VER="${{ github.ref_name }}"; VER="${VER#v}"
|
||||
python3 -c "import yaml,json;print(json.dumps(yaml.safe_load(open('hanzo.yml'))['images']))" | jq -c '.[]' | while read -r img; do
|
||||
python3 -c "import yaml,json;print(json.dumps(yaml.safe_load(open('hanzo.yml')).get('images') or []))" | jq -c '.[]' | while read -r img; do
|
||||
name=$(echo "$img"|jq -r .name); ctx=$(echo "$img"|jq -r .context)
|
||||
df=$(echo "$img"|jq -r '.dockerfile // (.context+"/Dockerfile")'); repo=$(echo "$img"|jq -r .repo)
|
||||
# tag-suffix is OPTIONAL (most repos ship a single variant). When set
|
||||
@@ -254,6 +276,50 @@ jobs:
|
||||
echo "::endgroup::"
|
||||
done
|
||||
|
||||
- name: Provision Go toolchain (go test gates on bare runners)
|
||||
# hanzo.yml `test:` gates (e.g. `go vet ./...`, `go test ...`) run
|
||||
# DIRECTLY on the runner, NOT inside a build container — but the stock
|
||||
# arc runner image (ghcr.io/actions/actions-runner) ships no Go, so a Go
|
||||
# gate dies with `go: command not found` (exit 127). Provision the repo's
|
||||
# OWN Go version from go.mod so the toolchain matches the module exactly.
|
||||
# Guarded to Go repos (go.mod present) so pure-JS/TS callers are
|
||||
# unaffected; harmless if a future runner image bakes Go in.
|
||||
if: inputs.mode != 'delegate' && hashFiles('go.mod') != ''
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
cache: false
|
||||
|
||||
- name: Provision C toolchain (cgo test gates)
|
||||
# CGO_ENABLED=1 gates (e.g. go-sqlite3, which bundles the sqlite
|
||||
# amalgamation) need a C compiler; the minimal arc runner ships none
|
||||
# (`cgo: gcc not found`). Same guarded provision the parse-toolchain step
|
||||
# above uses — a no-op when gcc is already present.
|
||||
if: inputs.mode != 'delegate' && hashFiles('go.mod') != ''
|
||||
run: command -v gcc >/dev/null 2>&1 || { sudo apt-get update -qq && sudo apt-get install -y -qq gcc; }
|
||||
|
||||
- name: Authenticate runner git for private Go modules (test gates)
|
||||
# The Test step runs `go vet`/`go test` ON the runner (not in buildx), so
|
||||
# `go` fetches private hanzoai/* modules (GOPRIVATE → direct) through the
|
||||
# runner's git, which needs a credential. The IMAGE build authenticates
|
||||
# via the KMS `gh_token` inside buildx (GIT_TOKEN); the earlier GH_PAT
|
||||
# git-auth step is a no-op for repos that rely on that KMS token (GH_PAT
|
||||
# unset) — so `go vet` dies with `could not read Username for github.com`.
|
||||
# Reuse the SAME token here for the runner's git (GIT_TOKEN, set by the
|
||||
# KMS step above; GH_PAT fallback). No-op when neither is present.
|
||||
if: inputs.mode != 'delegate' && hashFiles('go.mod') != ''
|
||||
env:
|
||||
GH_PAT: ${{ secrets.GH_PAT }}
|
||||
run: |
|
||||
set -uo pipefail
|
||||
TOKEN="${GIT_TOKEN:-${GH_PAT:-}}"
|
||||
if [ -z "$TOKEN" ]; then echo "no git token — public modules only"; exit 0; fi
|
||||
CFG="$RUNNER_TEMP/gitconfig-go-test"; : > "$CFG"
|
||||
GIT_CONFIG_GLOBAL="$CFG" git config --global \
|
||||
url."https://x-access-token:${TOKEN}@github.com/".insteadOf "https://github.com/"
|
||||
{ echo "GIT_CONFIG_GLOBAL=$CFG"; echo "GIT_CONFIG_NOSYSTEM=1"; } >> "$GITHUB_ENV"
|
||||
echo "runner git authenticated for private Go modules"
|
||||
|
||||
- name: Test (per hanzo.yml)
|
||||
if: inputs.mode != 'delegate'
|
||||
run: |
|
||||
@@ -277,7 +343,7 @@ jobs:
|
||||
fi
|
||||
SHORT=$(echo "${{ github.sha }}" | cut -c1-7)
|
||||
NS=$(python3 -c "import yaml;print(yaml.safe_load(open('hanzo.yml'))['deploy']['namespace'])")
|
||||
python3 -c "import yaml,json;print(json.dumps(yaml.safe_load(open('hanzo.yml'))['images']))" > /tmp/imgs.json
|
||||
python3 -c "import yaml,json;print(json.dumps(yaml.safe_load(open('hanzo.yml')).get('images') or []))" > /tmp/imgs.json
|
||||
python3 -c "import yaml,json;print(json.dumps(yaml.safe_load(open('hanzo.yml'))['deploy']['services']))" | jq -c '.[]' | while read -r s; do
|
||||
svc=$(echo "$s"|jq -r .name); imgname=$(echo "$s"|jq -r .image)
|
||||
repo=$(jq -r --arg n "$imgname" '.[]|select(.name==$n)|.repo' /tmp/imgs.json)
|
||||
|
||||
Reference in New Issue
Block a user