fix: [nomad-step-3] S3.4 — wire --with woodpecker + deploy ordering + OAuth seed (#937)
Some checks failed
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/nomad-validate Pipeline failed
ci/woodpecker/pr/ci Pipeline was successful
ci/woodpecker/pr/nomad-validate Pipeline failed
ci/woodpecker/pr/smoke-init Pipeline failed

This commit is contained in:
Agent 2026-04-17 06:37:04 +00:00
parent 3409c1b43c
commit d3c9457b7e
2 changed files with 147 additions and 16 deletions

View file

@ -82,7 +82,7 @@ Init options:
--ci-id <n> Woodpecker CI repo ID (default: 0 = no CI)
--forge-url <url> Forge base URL (default: http://localhost:3000)
--backend <value> Orchestration backend: docker (default) | nomad
--with <services> (nomad) Deploy services: forgejo[,...] (S1.3)
--with <services> (nomad) Deploy services: forgejo,woodpecker-server,woodpecker-agent[,...] (S1.3, S3.4)
--empty (nomad) Bring up cluster only, no jobs (S0.4)
--bare Skip compose generation (bare-metal setup)
--build Use local docker build instead of registry images (dev mode)
@ -783,6 +783,38 @@ _disinto_init_nomad() {
fi
if [ -n "$with_services" ]; then
# Normalize services: auto-include forgejo when woodpecker is requested
# (woodpecker without forgejo is nonsensical)
# Also expand 'woodpecker' to 'woodpecker-server,woodpecker-agent'
local normalized_services="$with_services"
local needs_log_note=false
# First, expand 'woodpecker' to 'woodpecker-server,woodpecker-agent'
if echo "$normalized_services" | grep -q "woodpecker"; then
# Replace woodpecker with woodpecker-server,woodpecker-agent
normalized_services=$(echo "$normalized_services" | sed 's/woodpecker/woodpecker-server,woodpecker-agent/g')
fi
# Then, auto-include forgejo if woodpecker was requested but forgejo is not present
if echo "$normalized_services" | grep -q "woodpecker" && ! echo "$normalized_services" | grep -q "forgejo"; then
echo "Note: --with woodpecker implies --with forgejo (OAuth dependency)"
normalized_services="forgejo,${normalized_services}"
needs_log_note=true
fi
# Define deployment order: forgejo -> woodpecker-server -> woodpecker-agent
# Only include services that are requested (after normalization)
local DEPLOY_ORDER=""
for ordered_svc in forgejo woodpecker-server woodpecker-agent; do
if echo ",$normalized_services," | grep -q ",$ordered_svc,"; then
if [ -z "$DEPLOY_ORDER" ]; then
DEPLOY_ORDER="$ordered_svc"
else
DEPLOY_ORDER="$DEPLOY_ORDER $ordered_svc"
fi
fi
done
# Vault seed plan (S2.6, #928): one line per service whose
# tools/vault-seed-<svc>.sh ships. Services without a seeder are
# silently skipped — the real-run loop below mirrors this,
@ -791,7 +823,7 @@ _disinto_init_nomad() {
# any further change to bin/disinto.
local seed_hdr_printed=false
local IFS=','
for svc in $with_services; do
for svc in $normalized_services; do
svc=$(echo "$svc" | xargs) # trim whitespace
local seed_script="${FACTORY_ROOT}/tools/vault-seed-${svc}.sh"
if [ -x "$seed_script" ]; then
@ -805,17 +837,24 @@ _disinto_init_nomad() {
[ "$seed_hdr_printed" = true ] && echo ""
echo "── Deploy services dry-run ────────────────────────────"
echo "[deploy] services to deploy: ${with_services}"
for svc in $with_services; do
echo "[deploy] services to deploy: ${normalized_services}"
echo "[deploy] deployment order: ${DEPLOY_ORDER}"
# Validate all requested services are known (before DEPLOY_ORDER loop)
local IFS=','
for svc in $normalized_services; do
svc=$(echo "$svc" | xargs) # trim whitespace
# Validate known services first
case "$svc" in
forgejo) ;;
forgejo|woodpecker-server|woodpecker-agent) ;;
*)
echo "Error: unknown service '${svc}' — known: forgejo" >&2
echo "Error: unknown service '${svc}' — known: forgejo, woodpecker-server, woodpecker-agent" >&2
exit 1
;;
esac
done
# Reset IFS for DEPLOY_ORDER loop
IFS=' '
for svc in $DEPLOY_ORDER; do
svc=$(echo "$svc" | xargs) # trim whitespace
local jobspec_path="${FACTORY_ROOT}/nomad/jobs/${svc}.hcl"
if [ ! -f "$jobspec_path" ]; then
echo "Error: jobspec not found: ${jobspec_path}" >&2
@ -936,9 +975,24 @@ _disinto_init_nomad() {
# `env_keep` (VAULT_ADDR is not). Using `env` as the actual command
# sets VAULT_ADDR in the child process regardless of sudoers policy.
if [ -n "$with_services" ]; then
# Normalize services: auto-include forgejo when woodpecker is requested
# (woodpecker without forgejo is nonsensical)
# Also expand 'woodpecker' to 'woodpecker-server,woodpecker-agent'
local normalized_services="$with_services"
# First, expand 'woodpecker' to 'woodpecker-server,woodpecker-agent'
if echo "$normalized_services" | grep -q "woodpecker"; then
normalized_services=$(echo "$normalized_services" | sed 's/woodpecker/woodpecker-server,woodpecker-agent/g')
fi
# Then, auto-include forgejo if woodpecker was requested but forgejo is not present
if echo "$normalized_services" | grep -q "woodpecker" && ! echo "$normalized_services" | grep -q "forgejo"; then
normalized_services="forgejo,${normalized_services}"
fi
local vault_addr="${VAULT_ADDR:-http://127.0.0.1:8200}"
local IFS=','
for svc in $with_services; do
for svc in $normalized_services; do
svc=$(echo "$svc" | xargs) # trim whitespace
local seed_script="${FACTORY_ROOT}/tools/vault-seed-${svc}.sh"
if [ -x "$seed_script" ]; then
@ -959,25 +1013,60 @@ _disinto_init_nomad() {
# Deploy services if requested
if [ -n "$with_services" ]; then
# Normalize services: auto-include forgejo when woodpecker is requested
# (woodpecker without forgejo is nonsensical)
# Also expand 'woodpecker' to 'woodpecker-server,woodpecker-agent'
local normalized_services="$with_services"
local needs_log_note=false
# First, expand 'woodpecker' to 'woodpecker-server,woodpecker-agent'
if echo "$normalized_services" | grep -q "woodpecker"; then
normalized_services=$(echo "$normalized_services" | sed 's/woodpecker/woodpecker-server,woodpecker-agent/g')
fi
# Then, auto-include forgejo if woodpecker was requested but forgejo is not present
if echo "$normalized_services" | grep -q "woodpecker" && ! echo "$normalized_services" | grep -q "forgejo"; then
echo "Note: --with woodpecker implies --with forgejo (OAuth dependency)"
normalized_services="forgejo,${normalized_services}"
needs_log_note=true
fi
# Define deployment order: forgejo -> woodpecker-server -> woodpecker-agent
# Only include services that are requested (after normalization)
local DEPLOY_ORDER=""
for ordered_svc in forgejo woodpecker-server woodpecker-agent; do
if echo ",$normalized_services," | grep -q ",$ordered_svc,"; then
if [ -z "$DEPLOY_ORDER" ]; then
DEPLOY_ORDER="$ordered_svc"
else
DEPLOY_ORDER="$DEPLOY_ORDER $ordered_svc"
fi
fi
done
echo ""
echo "── Deploying services ─────────────────────────────────"
local -a deploy_cmd=("$deploy_sh")
# Split comma-separated service list into positional args
# Validate all requested services are known (before DEPLOY_ORDER loop)
local IFS=','
for svc in $with_services; do
for svc in $normalized_services; do
svc=$(echo "$svc" | xargs) # trim whitespace
if ! echo "$svc" | grep -qE '^[a-zA-Z0-9_-]+$'; then
echo "Error: invalid service name '${svc}' — must match ^[a-zA-Z0-9_-]+$" >&2
exit 1
fi
# Validate known services FIRST (before jobspec check)
case "$svc" in
forgejo) ;;
forgejo|woodpecker-server|woodpecker-agent) ;;
*)
echo "Error: unknown service '${svc}' — known: forgejo" >&2
echo "Error: unknown service '${svc}' — known: forgejo, woodpecker-server, woodpecker-agent" >&2
exit 1
;;
esac
done
# Reset IFS for DEPLOY_ORDER loop
IFS=' '
for svc in $DEPLOY_ORDER; do
svc=$(echo "$svc" | xargs) # trim whitespace
# Check jobspec exists
local jobspec_path="${FACTORY_ROOT}/nomad/jobs/${svc}.hcl"
if [ ! -f "$jobspec_path" ]; then
@ -1011,10 +1100,16 @@ _disinto_init_nomad() {
else
echo "Imported: (none — seed kv/disinto/* manually before deploying secret-dependent services)"
fi
echo "Deployed: ${with_services}"
if echo "$with_services" | grep -q "forgejo"; then
echo "Deployed: ${normalized_services}"
if echo "$normalized_services" | grep -q "forgejo"; then
echo "Ports: forgejo: 3000"
fi
if echo "$normalized_services" | grep -q "woodpecker-server"; then
echo " woodpecker-server: 8000"
fi
if echo "$normalized_services" | grep -q "woodpecker-agent"; then
echo " woodpecker-agent: (agent connected)"
fi
echo "────────────────────────────────────────────────────────"
fi

View file

@ -215,7 +215,7 @@ setup_file() {
run "$DISINTO_BIN" init placeholder/repo --backend=nomad --with unknown-service --dry-run
[ "$status" -ne 0 ]
[[ "$output" == *"unknown service"* ]]
[[ "$output" == *"known: forgejo"* ]]
[[ "$output" == *"known: forgejo, woodpecker-server, woodpecker-agent"* ]]
}
@test "disinto init --backend=nomad --with forgejo (flag=value syntax) works" {
@ -224,6 +224,42 @@ setup_file() {
[[ "$output" == *"services to deploy: forgejo"* ]]
}
# S3.4: woodpecker auto-expansion and forgejo auto-inclusion
@test "disinto init --backend=nomad --with woodpecker auto-expands to server+agent" {
run "$DISINTO_BIN" init placeholder/repo --backend=nomad --with woodpecker --dry-run
[ "$status" -eq 0 ]
[[ "$output" == *"services to deploy: forgejo,woodpecker-server,woodpecker-agent"* ]]
[[ "$output" == *"deployment order: forgejo woodpecker-server woodpecker-agent"* ]]
}
@test "disinto init --backend=nomad --with woodpecker auto-includes forgejo with note" {
run "$DISINTO_BIN" init placeholder/repo --backend=nomad --with woodpecker --dry-run
[ "$status" -eq 0 ]
[[ "$output" == *"Note: --with woodpecker implies --with forgejo"* ]]
}
@test "disinto init --backend=nomad --with woodpecker,forgejo does not duplicate forgejo" {
run "$DISINTO_BIN" init placeholder/repo --backend=nomad --with woodpecker,forgejo --dry-run
[ "$status" -eq 0 ]
# Should still expand woodpecker and have forgejo once
[[ "$output" == *"services to deploy: forgejo,woodpecker-server,woodpecker-agent"* ]]
}
@test "disinto init --backend=nomad --with woodpecker seeds both forgejo and woodpecker" {
run "$DISINTO_BIN" init placeholder/repo --backend=nomad --with woodpecker --dry-run
[ "$status" -eq 0 ]
[[ "$output" == *"tools/vault-seed-forgejo.sh --dry-run"* ]]
[[ "$output" == *"tools/vault-seed-woodpecker.sh --dry-run"* ]]
}
@test "disinto init --backend=nomad --with forgejo,woodpecker deploys all three services" {
run "$DISINTO_BIN" init placeholder/repo --backend=nomad --with forgejo,woodpecker --dry-run
[ "$status" -eq 0 ]
[[ "$output" == *"[deploy] [dry-run] nomad job validate"*"forgejo.hcl"* ]]
[[ "$output" == *"[deploy] [dry-run] nomad job validate"*"woodpecker-server.hcl"* ]]
[[ "$output" == *"[deploy] [dry-run] nomad job validate"*"woodpecker-agent.hcl"* ]]
}
@test "disinto init --backend=nomad --with forgejo --empty --dry-run rejects in any order" {
run "$DISINTO_BIN" init placeholder/repo --with forgejo --backend=nomad --empty --dry-run
[ "$status" -ne 0 ]