diff --git a/ops/ax/smoke-task.yaml b/ops/ax/smoke-task.yaml.tmpl similarity index 51% rename from ops/ax/smoke-task.yaml rename to ops/ax/smoke-task.yaml.tmpl index ec248a4..32d86c2 100644 --- a/ops/ax/smoke-task.yaml +++ b/ops/ax/smoke-task.yaml.tmpl @@ -1,12 +1,15 @@ -# Minimal Task for the bring-up smoke test: default runner image, a files-only workspace, no MCP or skills. +# Bring-up smoke test: our runner image runs the model-free repo-facts task over a files-only workspace. apiVersion: ax.io/v1alpha1 kind: Task metadata: name: ousast-smoke atespace: default spec: - image: "gcr.io/ax-substrate/ate-images/ax-task-runner@sha256:3a0dea6ad8b55278685db58aca6e37dc4ba04056831d45bef3aaeafdca43cac6" - command: ["sh", "-c", "cat /workspace/hello.txt && echo smoke-ok"] + image: "${RUNNER_IMAGE}" # digest-pinned (Substrate rejects tags); rendered by up.sh + command: ["repo-facts"] + env: + - name: OUSAST_OUTPUT_DIR + value: "/workspace/.ousast-out/smoke" resources: requests: cpu: "100m" @@ -25,5 +28,5 @@ metadata: atespace: default spec: files: - - path: "hello.txt" - content: "hello from openultrasast\n" + - path: "hello.py" + content: "def hello():\n return greet()\n" diff --git a/ops/ax/up.sh b/ops/ax/up.sh index be7a3a7..29fda05 100755 --- a/ops/ax/up.sh +++ b/ops/ax/up.sh @@ -20,20 +20,53 @@ clone ax https://github.com/google/ax.git step() { printf '\n== %s (%s)\n' "$1" "$(date +%H:%M:%S)"; } step "kind cluster '$KIND_CLUSTER_NAME' + registry $KO_DOCKER_REPO" -(cd "$SRC/substrate" && hack/create-kind-cluster.sh) # its helpers resolve paths from the git toplevel +# Each step is skipped when already done: the substrate helper DELETES an existing cluster before creating one. +CTX="kind-$KIND_CLUSTER_NAME" +ready() { kubectl --context "$CTX" -n "$1" get pods --no-headers 2>/dev/null | awk '$2 ~ /^[0-9]+\/[0-9]+$/ {n++; split($2,a,"/"); if (a[1]!=a[2] && $3!="Completed") bad++} END {exit !(n>0 && bad==0)}'; } +if kind get clusters 2>/dev/null | grep -qx "$KIND_CLUSTER_NAME"; then + echo "cluster exists; kept" +else + (cd "$SRC/substrate" && hack/create-kind-cluster.sh) # its helpers resolve paths from the git toplevel +fi step "agent substrate (ate-system)" -(cd "$SRC/substrate" && hack/install-ate-kind.sh --deploy-ate-system) -kubectl -n ate-system wait --for=condition=Ready pod --all --timeout=900s || true -kubectl -n ate-system get pods +if ready ate-system; then echo "substrate ready; kept"; else + (cd "$SRC/substrate" && hack/install-ate-kind.sh --deploy-ate-system) +fi +kubectl --context "$CTX" -n ate-system get pods step "ax control plane (ax-system)" -(cd "$SRC/ax" && make deploy AX_IMAGE_REPO="$KO_DOCKER_REPO") -kubectl -n ax-system wait --for=condition=Ready pod --all --timeout=600s || true -kubectl -n ax-system get pods +if ready ax-system; then echo "ax ready; kept"; else + (cd "$SRC/ax" && make deploy AX_IMAGE_REPO="$KO_DOCKER_REPO") + kubectl --context "$CTX" -n ax-system wait --for=condition=Ready pod --all --timeout=600s +fi +kubectl --context "$CTX" -n ax-system get pods + +step "worker pool (gVisor)" +SUBSTRATE_VERSION="$(kubectl --context "$CTX" get nodes -o jsonpath='{.items[0].metadata.labels.ate\.dev/substrate-version}')" +export SUBSTRATE_VERSION +envsubst < "$(dirname "$0")/workerpool.yaml.tmpl" > "$SRC/workerpool.yaml" +(cd "$SRC/substrate" && KO_DOCKER_REPO="$KO_DOCKER_REPO" ko apply -f "$SRC/workerpool.yaml") +kubectl --context "$CTX" -n ax-system wait --for=condition=Ready pod -l ate.dev/worker-pool=ousast-pool --timeout=600s \ + || kubectl --context "$CTX" -n ax-system get pods + +step "runner image $KO_DOCKER_REPO/ousast-runner" +REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)" +docker build -q -f "$REPO_ROOT/plane/Dockerfile.runner" -t "$KO_DOCKER_REPO/ousast-runner:dev" "$REPO_ROOT" +docker push -q "$KO_DOCKER_REPO/ousast-runner:dev" +RUNNER_IMAGE="$(docker inspect --format '{{range .RepoDigests}}{{println .}}{{end}}' "$KO_DOCKER_REPO/ousast-runner:dev" | grep "^$KO_DOCKER_REPO/ousast-runner@" | head -1)" +[ -n "$RUNNER_IMAGE" ] || { echo "no digest for the runner image" >&2; exit 2; } +export RUNNER_IMAGE; echo "$RUNNER_IMAGE" > "$SRC/runner-image" # the reconciler reads this pin +echo "runner image $RUNNER_IMAGE" + +step "ax CLI from the deployed checkout (a release CLI skews from the server)" +(cd "$SRC/ax" && go install ./cmd/ax) step "smoke task" -ax apply -f "$(dirname "$0")/smoke-task.yaml" +ax delete task ousast-smoke >/dev/null 2>&1 || true +envsubst < "$(dirname "$0")/smoke-task.yaml.tmpl" > "$SRC/smoke-task.yaml" +ax apply -f "$SRC/smoke-task.yaml" +ax resume task ousast-smoke || true ax get tasks step "footprint" diff --git a/ops/ax/workerpool.yaml.tmpl b/ops/ax/workerpool.yaml.tmpl new file mode 100644 index 0000000..f71cdcf --- /dev/null +++ b/ops/ax/workerpool.yaml.tmpl @@ -0,0 +1,23 @@ +# Warm gVisor workers for ax tasks on this host (Agent Substrate WorkerPool). ax's per-task ActorTemplates +# set no workerSelector, so every pool of the matching sandbox class is eligible. Two workers of 1 CPU / +# 1.5 GiB fit the 7 GB host beside the control planes; an actor occupies a whole worker. +apiVersion: ate.dev/v1alpha1 +kind: WorkerPool +metadata: + name: ousast-pool + namespace: ax-system + labels: + workload: ousast +spec: + replicas: 2 + workerImage: ko://github.com/agent-substrate/substrate/cmd/ateom-gvisor + template: + nodeSelector: + ate.dev/substrate-version: "${SUBSTRATE_VERSION}" + resources: + limits: + cpu: "1" + memory: 1536Mi + requests: + cpu: 250m + memory: 1536Mi