Merge pull request #330 from fiddlerwoaroof/chatgpt/fix-cloud-agent-bootstrap

This commit is contained in:
Ed Langley
2026-09-26 08:45:59 -07:00
committed by GitHub
3 changed files with 162 additions and 27 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
{
"name": "Improvise",
"install": "./scripts/agent-bootstrap.sh",
"install": "nix-daemon >/tmp/nix-daemon.log 2>&1 & ./scripts/agent-bootstrap.sh",
"start": "nix-daemon &"
}
+70
View File
@@ -0,0 +1,70 @@
name: Cloud agent smoke
on:
pull_request:
paths:
- ".claude/**"
- ".cursor/**"
- "scripts/agent-bootstrap.sh"
- "scripts/nix-seed-flake-inputs.sh"
- ".github/workflows/cloud-agent-smoke.yml"
jobs:
claude:
name: Claude entry point + bead
runs-on: [self-hosted, nixos, microvm]
steps:
- uses: actions/checkout@v7
- name: Bootstrap through Claude session-start hook
shell: bash
env:
CLAUDE_CODE_REMOTE: "true"
run: |
if ! ./.claude/hooks/session-start.sh; then
echo "=== /tmp/nix-daemon.log ==="
cat /tmp/nix-daemon.log 2>/dev/null || true
echo "=== /tmp/nix-seed.log ==="
cat /tmp/nix-seed.log 2>/dev/null || true
echo "=== /tmp/bd-install.log ==="
cat /tmp/bd-install.log 2>/dev/null || true
exit 1
fi
- name: Create, read back, and close a smoke-test bead
shell: bash
run: |
set -euo pipefail
out="$(bd create "Cloud agent smoke: Claude entry point" --description="Ephemeral local-only bead used to verify the Claude cloud bootstrap entry point." --type=task --priority=4 --json)"
id="$(printf '%s' "$out" | jq -r '.id // .issue.id // empty')"
test -n "$id"
bd show "$id"
bd close "$id" --reason="Cloud-agent smoke test completed"
bd show "$id" | grep -qi closed
cursor:
name: Cursor install entry point + bead
runs-on: [self-hosted, nixos, microvm]
steps:
- uses: actions/checkout@v7
- name: Bootstrap through Cursor install command
shell: bash
run: |
nix-daemon >/tmp/nix-daemon.log 2>&1 &
if ! ./scripts/agent-bootstrap.sh; then
echo "=== /tmp/nix-daemon.log ==="
cat /tmp/nix-daemon.log 2>/dev/null || true
echo "=== /tmp/nix-seed.log ==="
cat /tmp/nix-seed.log 2>/dev/null || true
echo "=== /tmp/bd-install.log ==="
cat /tmp/bd-install.log 2>/dev/null || true
exit 1
fi
- name: Create, read back, and close a smoke-test bead
shell: bash
run: |
set -euo pipefail
out="$(bd create "Cloud agent smoke: Cursor entry point" --description="Ephemeral local-only bead used to verify the Cursor cloud bootstrap entry point." --type=task --priority=4 --json)"
id="$(printf '%s' "$out" | jq -r '.id // .issue.id // empty')"
test -n "$id"
bd show "$id"
bd close "$id" --reason="Cloud-agent smoke test completed"
bd show "$id" | grep -qi closed
+91 -26
View File
@@ -36,22 +36,74 @@ cd "$ROOT" || exit 0
log() { printf '[agent-bootstrap] %s\n' "$*"; }
nix_status=0
ensure_nix_daemon() {
command -v nix >/dev/null 2>&1 || return 1
# Single-user Nix does not need a daemon; multi-user/cloud installs do.
# If the store already answers, leave the environment alone.
if nix --extra-experimental-features 'nix-command' store ping >/dev/null 2>&1; then
return 0
fi
if ! command -v nix-daemon >/dev/null 2>&1; then
log "ERROR: Nix is installed, but the store is unavailable and nix-daemon is not on PATH"
return 1
fi
log "starting nix-daemon for bootstrap…"
nix-daemon >/tmp/nix-daemon.log 2>&1 &
# The daemon is started asynchronously; wait briefly for its socket before
# invoking the seed/build steps that depend on it.
for _ in {1..50}; do
if nix --extra-experimental-features 'nix-command' store ping --store daemon >/dev/null 2>&1; then
return 0
fi
sleep 0.1
done
log "ERROR: nix-daemon did not become ready; see /tmp/nix-daemon.log"
return 1
}
# Start the daemon during cloud-agent installation, before any required Nix
# operation. This is harmless for single-user Nix because nix-store --ping
# succeeds without starting a daemon.
if [ "$SKIP_NIX_SEED" -eq 0 ] || [ "$SKIP_CARGO_WARM" -eq 0 ]; then
if ! ensure_nix_daemon; then
nix_status=1
fi
fi
# ── 0. Seed nix flake inputs (required for cloud environments) ─────────────
# GitHub tarball endpoints are blocked in cloud containers. This seeds the
# flake inputs over git so `nix develop` can build the dev shell.
if [ "$SKIP_NIX_SEED" -eq 0 ] && command -v nix >/dev/null 2>&1; then
# Set SSL cert for proxy environments
if [ -z "${NIX_SSL_CERT_FILE:-}" ] && [ -r /root/.ccr/ca-bundle.crt ]; then
export NIX_SSL_CERT_FILE=/root/.ccr/ca-bundle.crt
fi
if [ -f "$ROOT/scripts/nix-seed-flake-inputs.sh" ]; then
log "seeding nix flake inputs (GitHub tarballs blocked in cloud)…"
if "$ROOT/scripts/nix-seed-flake-inputs.sh" >/tmp/nix-seed.log 2>&1; then
log "flake inputs seeded"
if [ "$SKIP_NIX_SEED" -eq 0 ]; then
if [ "$nix_status" -ne 0 ]; then
log "ERROR: cannot seed flake inputs because Nix is unavailable"
elif ! command -v nix >/dev/null 2>&1; then
log "ERROR: nix not available; required flake input seeding cannot run"
nix_status=1
else
# Set SSL cert for proxy environments
if [ -z "${NIX_SSL_CERT_FILE:-}" ] && [ -r /root/.ccr/ca-bundle.crt ]; then
export NIX_SSL_CERT_FILE=/root/.ccr/ca-bundle.crt
fi
if [ ! -f "$ROOT/scripts/nix-seed-flake-inputs.sh" ]; then
log "ERROR: required scripts/nix-seed-flake-inputs.sh is missing"
nix_status=1
else
log "WARNING: nix-seed-flake-inputs.sh failed; see /tmp/nix-seed.log"
log " 'nix develop' may fail. Check network/proxy settings."
log "seeding nix flake inputs (GitHub tarballs blocked in cloud)…"
if "$ROOT/scripts/nix-seed-flake-inputs.sh" >/tmp/nix-seed.log 2>&1; then
log "flake inputs seeded"
else
log "ERROR: nix-seed-flake-inputs.sh failed; see /tmp/nix-seed.log"
log " 'nix develop' is not validated for this session."
nix_status=1
fi
fi
fi
fi
@@ -173,14 +225,18 @@ if [ -n "${AGENT_ENV_FILE:-${CLAUDE_ENV_FILE:-}}" ]; then
echo 'export PATH="$PATH:/root/go/bin:$HOME/go/bin"' >> "$env_file"
fi
command -v bd >/dev/null 2>&1 && bd metrics off >/dev/null 2>&1
if [ "$pin_status" -eq 0 ]; then
assert_bd_pin || pin_status=2
fi
# Do not run any tracker/config mutation through a bd binary whose version does
# not match the repository pin.
if [ "$pin_status" -eq 0 ] && command -v bd >/dev/null 2>&1; then
bd metrics off >/dev/null 2>&1 || true
fi
# ── 3. Sync the issue tracker from the Dolt remote ─────────────────────────
if command -v bd >/dev/null 2>&1; then
if [ "$pin_status" -eq 0 ] && command -v bd >/dev/null 2>&1; then
DB_NAME="$(jq -r '.dolt_database // "improvise"' .beads/metadata.json 2>/dev/null || echo improvise)"
ORIGIN="$(git remote get-url origin 2>/dev/null || true)"
case "$ORIGIN" in
@@ -224,18 +280,23 @@ fi
# ── 4. Warm the build inside nix develop (optional) ────────────────────────
# Uses nix develop to ensure the correct toolchain (rust from flake, wasm target, etc.)
if [ "$SKIP_CARGO_WARM" -eq 0 ] && command -v nix >/dev/null 2>&1; then
log "warming cargo build inside nix develop…"
NIX_FLAGS=(--extra-experimental-features 'nix-command flakes')
if nix "${NIX_FLAGS[@]}" develop --command cargo build --workspace --tests >/tmp/cargo-warm.log 2>&1; then
log "workspace built (nix develop toolchain)"
if [ "$SKIP_CARGO_WARM" -eq 0 ]; then
if [ "$nix_status" -ne 0 ]; then
log "ERROR: skipping required cargo warm because Nix bootstrap already failed"
elif ! command -v nix >/dev/null 2>&1; then
log "ERROR: nix not available; required cargo warm cannot run"
nix_status=1
else
log "WARNING: cargo build failed; see /tmp/cargo-warm.log"
log " This may indicate nix-seed failed or flake inputs are missing."
log "warming cargo build inside nix develop…"
NIX_FLAGS=(--extra-experimental-features 'nix-command flakes')
if nix "${NIX_FLAGS[@]}" develop --command cargo build --workspace --tests >/tmp/cargo-warm.log 2>&1; then
log "workspace built (nix develop toolchain)"
else
log "ERROR: cargo build failed; see /tmp/cargo-warm.log"
log " Required nix develop validation failed."
nix_status=1
fi
fi
elif [ "$SKIP_CARGO_WARM" -eq 0 ]; then
log "WARNING: nix not available; skipping cargo warm"
log " Install nix or use a container with nix for this repo."
fi
# ── 5. Environment notes ───────────────────────────────────────────────────
@@ -252,4 +313,8 @@ cat <<'NOTES'
• Run commands inside `nix develop` or prefix with `nix develop --command`.
NOTES
exit "$pin_status"
exit_status="$nix_status"
if [ "$pin_status" -ne 0 ]; then
exit_status="$pin_status"
fi
exit "$exit_status"