Repository navigation
Expand file tree
/
Copy pathhanzo.yml
More file actions
92 lines (90 loc) · 5.33 KB
/
Copy pathhanzo.yml
File metadata and controls
92 lines (90 loc) · 5.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# Canonical CI config for hanzoai/cli — read by the hanzoai/ci reusable
# (.github/workflows/cicd.yml) and by platform.hanzo.ai. This repo had neither
# this file nor a Makefile, which is why `genspec` — the one thing that keeps
# the CLI's command surface honest — was reachable only by a maintainer typing
# it. A capture nothing re-asks goes stale silently, and this one did: it was
# 7 operations short and 8 operations wrong against the document cloud had
# already committed.
#
# NO images: the CLI is a binary a person installs, not a container a cluster
# runs. NO binaries: this repo's binaries are the five-target cross-build in
# .hanzo/workflows/release-matrix.yml (cargo-zigbuild + a vendored macOS SDK) —
# that is genuinely per-repo build logic and it is already correct; the generic
# Go-shaped lane here cannot produce it. NO deploy: nothing here rolls out.
#
# That path is `.hanzo/`, not `.github/`: the runners belong to git.hanzo.ai and
# github.com has none, so a pipeline under `.github/` queues forever instead of
# building. Both CI files in this repo live under `.hanzo/workflows/` for that
# one reason.
#
# What CI owns for this repo is the two gates below and the client lane.
client:
# The document, by value at a pinned ref: the lane fetches openapi.yaml at the
# ref .spec-lock names and refuses on a digest mismatch. It does not choose the
# ref and does not write the lock — on a push it is check-only at the locked
# one. What MOVES the pin is the nightly re-pin in .hanzo/workflows/drift.yml,
# which reads hanzo-inc/cloud's main and commits the result once `make verify`
# rules on it. Reading api.hanzo.ai here would name whatever is serving now
# rather than a release.
spec: { repo: hanzo-inc/cloud, path: openapi.yaml }
generate: ./scripts/generate.sh
# PATCH only, derived. The command surface is the document's; this crate only
# restates it, so it never earns a minor or a major.
version: "Cargo.toml:grep -m1 '^version' Cargo.toml | sed -E 's/.*\"(.*)\".*/\\1/'"
# THE CAPTURE GATE is NOT here, and that is the point: hanzoai/ci's `client:` lane
# asks it for all eight client repos in one place, on every push — fetch the
# document .spec-lock names, refuse if the ref moved under it, re-run the
# derivation, refuse any delta, write nothing. `make spec-check` is the same
# question a human asks locally, through the same script.
#
# THE DRIFT GATE is a different question — a capture can equal its inputs exactly
# and still describe a surface production stopped serving, or miss a product
# production started — and it IS here, inside `cargo test`, because it stopped
# needing the network. It rules on `spec/live.json`: the raw answers the live
# server gave to every probe and to a nonsense-sibling CONTROL for each, captured
# by `make live` and committed. So the push gate asks both directions on every
# push, in the one lane, with nothing to fail for a reason that is not drift.
#
# It used to need the wire, and that is what made it fragile: a gate needing the
# network in CI gets switched off, and this one first sat in the list below where
# a failure in the client step or the KMS login meant it was never reached at all.
# It was never asked once that way.
#
# What still needs the wire is the OTHER half — has production moved under the
# committed evidence? — and that has its own job, its own triggers and nothing
# else in it: `.hanzo/workflows/drift.yml`, nightly and on a click, `make
# live-check`. One predicate per place, and neither shares its fate with anything.
#
# `make test`, never a bare `cargo test`: the gates below exec maintainer
# binaries that `cargo test` does not build, and a gate that dies on NotFound
# reads exactly like a gate that passed. One invocation, in the Makefile.
#
# THE LINT GATE HAS TO INSTALL WHAT IT LINTS WITH. `dtolnay/rust-toolchain@stable`
# provisions rustc and cargo and no components, so `cargo clippy` answered
# "'cargo-clippy' is not installed for the toolchain" and every main build went
# red on it — six in a row, while `make test` above passed every one of them. A
# gate that cannot run is worse than no gate whichever way it lands: red, it
# teaches people the build lies; green, it teaches them nothing at all. It asks
# for the component first now, which is idempotent and costs a cached download.
#
# THE SUITE NEVER TOUCHES A HOME, and the gate says so the way hanzoai/gen's
# does: it runs against an empty HOME it cannot write, then against an empty one
# it can, which must still be empty after. A runner can be a person's machine,
# and a test that wrote there once rewrote that person's agent configs. Cargo
# and rustup keep their own homes, named before HOME moves.
test:
- name: cargo-test
run: |
set -euo pipefail
export CARGO_HOME="${CARGO_HOME:-$HOME/.cargo}" RUSTUP_HOME="${RUSTUP_HOME:-$HOME/.rustup}" RUSTC_WRAPPER=
export PATH="$CARGO_HOME/bin:$PATH"
unset XDG_DATA_HOME XDG_CONFIG_HOME XDG_CACHE_HOME XDG_STATE_HOME
ro=$(mktemp -d); tmp=$(mktemp -d)
trap 'chmod u+w "$ro"; rm -rf "$ro" "$tmp"' EXIT
chmod 0555 "$ro"
HOME="$ro" make test
HOME="$tmp" make test
left=$(find "$tmp" -mindepth 1 | head -20)
[ -z "$left" ] || { echo "::error::the test suite wrote into HOME:"; echo "$left"; exit 1; }
- name: clippy
run: rustup component add clippy && cargo clippy --locked --all-targets -- -D warnings