diff --git a/scripts/sunbeam.py b/scripts/sunbeam.py index 584f6c4..7bcabbe 100755 --- a/scripts/sunbeam.py +++ b/scripts/sunbeam.py @@ -13,6 +13,7 @@ Usage: ./scripts/sunbeam.py --restart # restart services only ./scripts/sunbeam.py --status # show pod health across all namespaces ./scripts/sunbeam.py --verify # E2E test VSO → OpenBao integration + ./scripts/sunbeam.py --build # Build + push sunbeam-proxy to Gitea; redeploy Requires: limactl mkcert kubectl kustomize linkerd jq yq """ @@ -32,6 +33,7 @@ from pathlib import Path SCRIPT_DIR = Path(__file__).parent.resolve() REPO_ROOT = SCRIPT_DIR.parent SECRETS_DIR = REPO_ROOT / "secrets" / "local" +PROXY_DIR = REPO_ROOT.parent / "proxy" # ── Config ──────────────────────────────────────────────────────────────────── LIMA_VM = "sunbeam" @@ -1460,6 +1462,56 @@ spec: ok("VSO E2E verification passed.") +# ── 18. Build + push sunbeam-proxy ─────────────────────────────────────────── +def build_proxy(domain, admin_pass): + """Build sunbeam-proxy for linux/arm64 and push to our Gitea registry. + + Requires Docker (buildx) on the host. The mkcert CA must already be trusted + by Docker (docker-desktop uses the macOS Keychain, so `mkcert -install` is + sufficient). After pushing, applies manifests so the Deployment picks up + the updated image reference, then rolls the pingora pod to trigger a pull. + """ + if not shutil.which("docker"): + die("docker not found — install Docker Desktop to use --build.") + + if not PROXY_DIR.is_dir(): + die(f"Proxy source not found at {PROXY_DIR}") + + registry = f"src.{domain}" + image = f"{registry}/studio/sunbeam-proxy:latest" + + step(f"Building sunbeam-proxy → {image} ...") + + # Authenticate Docker with Gitea before the build so --push succeeds. + ok("Logging in to Gitea registry...") + r = subprocess.run( + ["docker", "login", registry, + "--username", GITEA_ADMIN_USER, "--password-stdin"], + input=admin_pass, text=True, capture_output=True, + ) + if r.returncode != 0: + die(f"docker login failed:\n{r.stderr.strip()}") + + ok(f"Building image (linux/arm64, push)...") + run(["docker", "buildx", "build", + "--platform", "linux/arm64", + "--push", + "-t", image, + str(PROXY_DIR)]) + + ok(f"Pushed {image}") + + # Apply manifests so the Deployment spec reflects the Gitea image ref. + apply_manifests(domain) + + # Roll the pingora pod — imagePullPolicy: Always ensures it pulls fresh. + ok("Rolling pingora deployment...") + kube("rollout", "restart", "deployment/pingora", "-n", "ingress") + kube("rollout", "status", "deployment/pingora", "-n", "ingress", + "--timeout=120s") + ok("Pingora redeployed.") + + # ── Main ────────────────────────────────────────────────────────────────────── def main(): parser = argparse.ArgumentParser(description="Sunbeam local dev stack manager") @@ -1469,6 +1521,7 @@ def main(): parser.add_argument("--restart", action="store_true", help="Restart services only") parser.add_argument("--status", action="store_true", help="Show pod health across all namespaces") parser.add_argument("--verify", action="store_true", help="E2E test VSO → OpenBao integration") + parser.add_argument("--build", action="store_true", help="Build + push sunbeam-proxy to Gitea; redeploy") args = parser.parse_args() check_prerequisites() @@ -1482,6 +1535,19 @@ def main(): verify_vso() return + if args.build: + ip = get_lima_ip() + domain = f"{ip}.sslip.io" + admin_pass_b64 = kube_out( + "-n", "devtools", "get", "secret", "gitea-admin-credentials", + "-o=jsonpath={.data.password}", + ) + if not admin_pass_b64: + die("gitea-admin-credentials secret not found — run --seed first.") + admin_pass = base64.b64decode(admin_pass_b64).decode() + build_proxy(domain, admin_pass) + return + if args.apply or args.gitea or args.seed or args.restart: ip = get_lima_ip() domain = f"{ip}.sslip.io"