diff --git a/cloudbuild.yaml b/cloudbuild.yaml index 76f87b02e..2b8d70fba 100644 --- a/cloudbuild.yaml +++ b/cloudbuild.yaml @@ -1,19 +1,22 @@ -# Fast release build of trace-commons-ingest for the pilot host. +# Fast release build of the pilot binaries (trace-commons-ingest AND +# trace-commons-upload-claim-issuer) for the pilot host. # # The pilot host (tc-pilot-host) is Ubuntu 24.04 (glibc 2.39, OpenSSL 3). This -# builds on a matching ubuntu:24.04 image on a high-CPU machine and pushes the +# builds on a matching ubuntu:24.04 image on a high-CPU machine and pushes each # binary to GCS for the host to pull (deploy/pilot-gcp/pull-and-install.sh). # -# The ONNX runtime (ort/fastembed) is statically linked (ort downloads -# libonnxruntime.a at build time), so the only runtime deps are standard -# Ubuntu 24.04 system libs that the host already has. +# BOTH binaries are built because the pilot runs both services and changes can +# land in either: ingest (account API + the migration runner that applies V30+ +# on boot) or the issuer (EdDSA upload claims, device-key registration, the +# per-user `subject` derivation, and the instance-enroll `/v1/enroll` handler). +# ingest builds with the cloud features; the issuer builds without them (it does +# not use GCS/KMS/NEAR-AI), matching the operator runbook. The ONNX runtime +# (ort/fastembed, ingest only) is statically linked. # # Run: # gcloud builds submit --config cloudbuild.yaml \ # --project tracecommons-pilot-2026 \ # --substitutions _TAG=$(git rev-parse --short HEAD) -# -# (a .gcloudignore keeps target/ and .git out of the source upload.) substitutions: _TAG: 'manual' # short SHA or tag; defaults to BUILD_ID below if 'manual' @@ -36,9 +39,13 @@ steps: . "$$HOME/.cargo/env" cargo build --release --bin trace-commons-ingest \ --features gcs-client,gcp-kms,near-ai-scorer + # Reuses the deps compiled above; the issuer takes no features. + cargo build --release --bin trace-commons-upload-claim-issuer mkdir -p /workspace/out - cp target/release/trace-commons-ingest /workspace/out/trace-commons-ingest - ( cd /workspace/out && sha256sum trace-commons-ingest > trace-commons-ingest.sha256 ) + for b in trace-commons-ingest trace-commons-upload-claim-issuer; do + cp "target/release/$$b" "/workspace/out/$$b" + ( cd /workspace/out && sha256sum "$$b" > "$$b.sha256" ) + done - name: 'gcr.io/cloud-builders/gcloud' id: publish @@ -48,15 +55,16 @@ steps: - | set -euxo pipefail TAG="${_TAG}"; [ "$$TAG" = "manual" ] && TAG="${BUILD_ID}" - DEST="gs://${_BUCKET}/binaries/trace-commons-ingest/$$TAG" - gcloud storage cp /workspace/out/trace-commons-ingest "$$DEST/trace-commons-ingest" - gcloud storage cp /workspace/out/trace-commons-ingest.sha256 "$$DEST/trace-commons-ingest.sha256" - # latest pointer the host's pull script reads - printf '%s' "$$DEST/trace-commons-ingest" \ - | gcloud storage cp - "gs://${_BUCKET}/binaries/trace-commons-ingest/latest.txt" - echo "published: $$DEST/trace-commons-ingest" + for b in trace-commons-ingest trace-commons-upload-claim-issuer; do + DEST="gs://${_BUCKET}/binaries/$$b/$$TAG" + gcloud storage cp "/workspace/out/$$b" "$$DEST/$$b" + gcloud storage cp "/workspace/out/$$b.sha256" "$$DEST/$$b.sha256" + # latest pointer the host's pull script reads + printf '%s' "$$DEST/$$b" | gcloud storage cp - "gs://${_BUCKET}/binaries/$$b/latest.txt" + echo "published: $$DEST/$$b" + done options: machineType: 'E2_HIGHCPU_32' diskSizeGb: 120 -timeout: '3000s' +timeout: '3600s' diff --git a/deploy/pilot-gcp/pull-and-install.sh b/deploy/pilot-gcp/pull-and-install.sh index cbc29ad21..bc30695dd 100755 --- a/deploy/pilot-gcp/pull-and-install.sh +++ b/deploy/pilot-gcp/pull-and-install.sh @@ -1,46 +1,65 @@ #!/usr/bin/env bash -# Pull a Cloud Build-produced trace-commons-ingest binary from GCS and install it -# on the pilot host, then restart the service. Pairs with cloudbuild.yaml. +# Pull Cloud Build-produced binaries from GCS and install them on the pilot host, +# restarting the services. Pairs with cloudbuild.yaml. +# +# The pilot runs two services; both can change, so this deploys BOTH by default: +# - trace-commons-upload-claim-issuer (EdDSA claims, device-key registration, +# per-user subject, /v1/enroll; serves the JWKS the ingest verifies at boot) +# - trace-commons-ingest (account API; applies migrations on boot) +# The issuer is installed first so its (possibly rotated) JWKS is up before ingest +# restarts and fetches it. # # Usage (on tc-pilot-host): -# deploy/pilot-gcp/pull-and-install.sh [] -# With no arg it reads the `latest.txt` pointer the build publishes. +# deploy/pilot-gcp/pull-and-install.sh # both binaries (default) +# deploy/pilot-gcp/pull-and-install.sh ingest # just ingest +# deploy/pilot-gcp/pull-and-install.sh issuer # just the issuer # -# Verifies the sha256 sidecar, backs up the running binary, installs, and -# restarts trace-commons-ingest (which auto-applies any pending migrations). +# Each install verifies the sha256 sidecar, backs up the running binary, installs, +# and restarts the service. Reads the per-binary `latest.txt` pointer the build +# publishes. set -euo pipefail BUCKET="${TC_ARTIFACT_BUCKET:-tc-pilot-artifacts-20260518}" -BIN_DEST="/opt/tracecommons/bin/trace-commons-ingest" -LATEST="gs://${BUCKET}/binaries/trace-commons-ingest/latest.txt" - -SRC="${1:-}" -if [ -z "$SRC" ]; then - SRC="$(gcloud storage cat "$LATEST")" -fi -echo "Pulling: $SRC" -TMP="$(mktemp -d)" -trap 'rm -rf "$TMP"' EXIT -gcloud storage cp "$SRC" "$TMP/trace-commons-ingest" -gcloud storage cp "${SRC}.sha256" "$TMP/trace-commons-ingest.sha256" || true +install_one() { + local bin="$1" svc="$2" + local latest="gs://${BUCKET}/binaries/${bin}/latest.txt" + local src + src="$(gcloud storage cat "$latest")" + echo "[$bin] pulling: $src" -if [ -f "$TMP/trace-commons-ingest.sha256" ]; then - ( cd "$TMP" && awk '{print $1" trace-commons-ingest"}' trace-commons-ingest.sha256 | sha256sum -c - ) - echo "sha256 verified" -else - echo "WARNING: no sha256 sidecar found; skipping checksum verification" >&2 -fi + local tmp + tmp="$(mktemp -d)" + gcloud storage cp "$src" "$tmp/$bin" + if gcloud storage cp "${src}.sha256" "$tmp/$bin.sha256" 2>/dev/null; then + ( cd "$tmp" && sha256sum -c "$bin.sha256" ) + echo "[$bin] sha256 verified" + else + echo "[$bin] WARNING: no sha256 sidecar; skipping checksum" >&2 + fi + chmod 0755 "$tmp/$bin" -chmod 0755 "$TMP/trace-commons-ingest" -"$TMP/trace-commons-ingest" --version 2>/dev/null || true + local stamp dest + stamp="$(date -u +%Y%m%dT%H%M%SZ)" + dest="/opt/tracecommons/bin/$bin" + sudo cp -av "$dest" "${dest}.bak-${stamp}" + sudo install -o root -g root -m 0755 "$tmp/$bin" "$dest" + rm -rf "$tmp" + echo "[$bin] installed $dest" -STAMP="$(date -u +%Y%m%dT%H%M%SZ)" -sudo cp -av "$BIN_DEST" "${BIN_DEST}.bak-${STAMP}" -sudo install -o root -g root -m 0755 "$TMP/trace-commons-ingest" "$BIN_DEST" -echo "installed $BIN_DEST" + sudo systemctl restart "$svc" + sleep 8 + echo "[$bin] $(systemctl is-active "$svc")" + echo "[$bin] rollback: sudo install -m0755 ${dest}.bak-${stamp} ${dest} && sudo systemctl restart $svc" +} -sudo systemctl restart trace-commons-ingest -sleep 10 -systemctl is-active trace-commons-ingest -echo "done; rollback with: sudo install -m0755 ${BIN_DEST}.bak-${STAMP} ${BIN_DEST} && sudo systemctl restart trace-commons-ingest" +case "${1:-both}" in + ingest) install_one trace-commons-ingest trace-commons-ingest ;; + issuer) install_one trace-commons-upload-claim-issuer trace-commons-upload-claim-issuer ;; + both) + install_one trace-commons-upload-claim-issuer trace-commons-upload-claim-issuer + install_one trace-commons-ingest trace-commons-ingest + ;; + *) echo "usage: $0 [both|ingest|issuer]" >&2; exit 2 ;; +esac +echo "done."