diff --git a/nomad/AGENTS.md b/nomad/AGENTS.md index 6c052c3..2d936c3 100644 --- a/nomad/AGENTS.md +++ b/nomad/AGENTS.md @@ -16,8 +16,8 @@ see issues #821–#962 for the step breakdown. | `client.hcl` | `/etc/nomad.d/client.hcl` | Docker driver cfg + `host_volume` declarations (S0.2); `allow_privileged = true` for woodpecker-agent Docker-in-Docker (S3-fix-5, #961) | | `vault.hcl` | `/etc/vault.d/vault.hcl` | Vault storage, listener, UI, `disable_mlock` (S0.3) | | `jobs/forgejo.hcl` | submitted via `lib/init/nomad/deploy.sh` | Forgejo job; reads creds from Vault via consul-template stanza (S2.4) | -| `jobs/woodpecker-server.hcl` | submitted via Nomad API | Woodpecker CI server; host networking, Vault KV for `WOODPECKER_AGENT_SECRET` + Forgejo OAuth creds (S3.1) | -| `jobs/woodpecker-agent.hcl` | submitted via Nomad API | Woodpecker CI agent; host networking, `docker.sock` mount, Vault KV for `WOODPECKER_AGENT_SECRET` (S3.2) | +| `jobs/woodpecker-server.hcl` | submitted via `lib/init/nomad/deploy.sh` | Woodpecker CI server; host networking, Vault KV for `WOODPECKER_AGENT_SECRET` + Forgejo OAuth creds (S3.1) | +| `jobs/woodpecker-agent.hcl` | submitted via `lib/init/nomad/deploy.sh` | Woodpecker CI agent; host networking, `docker.sock` mount, Vault KV for `WOODPECKER_AGENT_SECRET` (S3.2) | | `jobs/agents.hcl` | submitted via `lib/init/nomad/deploy.sh` | All 7 agent roles (dev, review, gardener, planner, predictor, supervisor, architect) + llama variant; Vault-templated bot tokens via `service-agents` policy (S4.1, #955) | Nomad auto-merges every `*.hcl` under `-config=/etc/nomad.d/`, so the diff --git a/tools/vault-seed-agents.sh b/tools/vault-seed-agents.sh index 366bfde..fbed325 100755 --- a/tools/vault-seed-agents.sh +++ b/tools/vault-seed-agents.sh @@ -84,6 +84,18 @@ hvault_ensure_kv_v2 "$KV_MOUNT" "${LOG_TAG}" \ # ── Step 2: seed each bot role ─────────────────────────────────────────────── total_generated=0 +# Check if shared forge credentials exist for dev role fallback +shared_forge_exists=0 +shared_forge_raw="$(hvault_get_or_empty "${KV_MOUNT}/data/disinto/shared/forge")" \ + || true +if [ -n "$shared_forge_raw" ]; then + shared_forge_token="$(printf '%s' "$shared_forge_raw" | jq -r '.data.data.token // ""')" + shared_forge_pass="$(printf '%s' "$shared_forge_raw" | jq -r '.data.data.pass // ""')" + if [ -n "$shared_forge_token" ] && [ -n "$shared_forge_pass" ]; then + shared_forge_exists=1 + fi +fi + for role in "${BOT_ROLES[@]}"; do kv_logical="disinto/bots/${role}" kv_api="${KV_MOUNT}/data/${kv_logical}" @@ -103,12 +115,35 @@ for role in "${BOT_ROLES[@]}"; do fi generated=() + desired_token="$existing_token" + desired_pass="$existing_pass" - if [ -z "$existing_token" ]; then - generated+=("token") - fi - if [ -z "$existing_pass" ]; then - generated+=("pass") + # Special case: dev role uses shared forge credentials if available + if [ "$role" = "dev" ] && [ "$shared_forge_exists" -eq 1 ]; then + # Use shared FORGE_TOKEN + FORGE_PASS for dev role + if [ -z "$existing_token" ]; then + desired_token="$shared_forge_token" + generated+=("token") + fi + if [ -z "$existing_pass" ]; then + desired_pass="$shared_forge_pass" + generated+=("pass") + fi + else + # Generate random values for missing keys + if [ -z "$existing_token" ]; then + generated+=("token") + fi + if [ -z "$existing_pass" ]; then + generated+=("pass") + fi + + for key in "${generated[@]}"; do + case "$key" in + token) desired_token="$(openssl rand -hex "$TOKEN_BYTES")" ;; + pass) desired_pass="$(openssl rand -hex "$PASS_BYTES")" ;; + esac + done fi if [ "${#generated[@]}" -eq 0 ]; then @@ -122,16 +157,6 @@ for role in "${BOT_ROLES[@]}"; do continue fi - desired_token="$existing_token" - desired_pass="$existing_pass" - - for key in "${generated[@]}"; do - case "$key" in - token) desired_token="$(openssl rand -hex "$TOKEN_BYTES")" ;; - pass) desired_pass="$(openssl rand -hex "$PASS_BYTES")" ;; - esac - done - # Merge new keys into existing data to preserve any keys we don't own. payload="$(printf '%s' "$existing_data" \ | jq --arg t "$desired_token" --arg p "$desired_pass" \