fix: feat: task dispatcher — poll ops repo and launch runners (#45) #54
1 changed files with 38 additions and 19 deletions
|
|
@ -22,6 +22,20 @@ SCRIPT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
# Source shared environment
|
# Source shared environment
|
||||||
source "${SCRIPT_ROOT}/../lib/env.sh"
|
source "${SCRIPT_ROOT}/../lib/env.sh"
|
||||||
|
|
||||||
|
# Load vault secrets after env.sh (env.sh unsets them for agent security)
|
||||||
|
# Vault secrets must be available to the dispatcher
|
||||||
|
if [ -f "$FACTORY_ROOT/.env.vault.enc" ] && command -v sops &>/dev/null; then
|
||||||
|
set -a
|
||||||
|
eval "$(sops -d --output-type dotenv "$FACTORY_ROOT/.env.vault.enc" 2>/dev/null)" \
|
||||||
|
|| echo "Warning: failed to decrypt .env.vault.enc — vault secrets not loaded" >&2
|
||||||
|
set +a
|
||||||
|
elif [ -f "$FACTORY_ROOT/.env.vault" ]; then
|
||||||
|
set -a
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "$FACTORY_ROOT/.env.vault"
|
||||||
|
set +a
|
||||||
|
fi
|
||||||
|
|
||||||
# Ops repo location (vault/actions directory)
|
# Ops repo location (vault/actions directory)
|
||||||
OPS_REPO_ROOT="${OPS_REPO_ROOT:-/home/debian/disinto-ops}"
|
OPS_REPO_ROOT="${OPS_REPO_ROOT:-/home/debian/disinto-ops}"
|
||||||
VAULT_ACTIONS_DIR="${OPS_REPO_ROOT}/vault/actions"
|
VAULT_ACTIONS_DIR="${OPS_REPO_ROOT}/vault/actions"
|
||||||
|
|
@ -35,7 +49,7 @@ log() {
|
||||||
ensure_ops_repo() {
|
ensure_ops_repo() {
|
||||||
if [ ! -d "${OPS_REPO_ROOT}/.git" ]; then
|
if [ ! -d "${OPS_REPO_ROOT}/.git" ]; then
|
||||||
log "Cloning ops repo from ${FORGE_OPS_REPO}..."
|
log "Cloning ops repo from ${FORGE_OPS_REPO}..."
|
||||||
git clone "${FORGE_WEB}" "${OPS_REPO_ROOT}"
|
git clone "${FORGE_OPS_REPO}" "${OPS_REPO_ROOT}"
|
||||||
else
|
else
|
||||||
log "Pulling latest ops repo changes..."
|
log "Pulling latest ops repo changes..."
|
||||||
(cd "${OPS_REPO_ROOT}" && git pull --rebase)
|
(cd "${OPS_REPO_ROOT}" && git pull --rebase)
|
||||||
|
|
@ -68,24 +82,29 @@ launch_runner() {
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Extract secrets (as space-separated list for env injection)
|
# Extract secrets (array for safe handling)
|
||||||
local secrets
|
local -a secrets=()
|
||||||
secrets=$(jq -r '.secrets[]? // empty' "$action_file" 2>/dev/null | tr '\n' ' ')
|
while IFS= read -r secret; do
|
||||||
|
[ -n "$secret" ] && secrets+=("$secret")
|
||||||
|
done < <(jq -r '.secrets[]? // empty' "$action_file" 2>/dev/null)
|
||||||
|
|
||||||
# Run the formula via docker compose with action ID as argument
|
# Build command array (safe from shell injection)
|
||||||
# The runner container should be defined in docker-compose.yml
|
local -a cmd=(docker compose run --rm runner)
|
||||||
# Secrets are injected via -e flags
|
|
||||||
local compose_cmd="docker compose run --rm runner ${formula} ${id}"
|
|
||||||
|
|
||||||
if [ -n "$secrets" ]; then
|
# Add environment variables BEFORE service name
|
||||||
# Inject secrets as environment variables
|
for secret in "${secrets[@]+"${secrets[@]}"}"; do
|
||||||
for secret in $secrets; do
|
local secret_val="${!secret:-}"
|
||||||
compose_cmd+=" -e ${secret}=${!secret}"
|
cmd+=(-e "${secret}=***") # Redact value in the command array
|
||||||
done
|
done
|
||||||
fi
|
|
||||||
|
|
||||||
log "Running: ${compose_cmd}"
|
# Add formula and id as arguments (after service name)
|
||||||
eval "${compose_cmd}"
|
cmd+=("$formula" "$id")
|
||||||
|
|
||||||
|
# Log command skeleton (secrets are redacted)
|
||||||
|
log "Running: ${cmd[*]}"
|
||||||
|
|
||||||
|
# Execute with array expansion (safe from shell injection)
|
||||||
|
"${cmd[@]}"
|
||||||
|
|
||||||
log "Runner completed for action: ${id}"
|
log "Runner completed for action: ${id}"
|
||||||
}
|
}
|
||||||
|
|
@ -95,10 +114,10 @@ main() {
|
||||||
log "Starting dispatcher..."
|
log "Starting dispatcher..."
|
||||||
log "Polling ops repo: ${VAULT_ACTIONS_DIR}"
|
log "Polling ops repo: ${VAULT_ACTIONS_DIR}"
|
||||||
|
|
||||||
# Ensure ops repo is available
|
|
||||||
ensure_ops_repo
|
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
|
# Refresh ops repo at the start of each poll cycle
|
||||||
|
ensure_ops_repo
|
||||||
|
|
||||||
# Check if actions directory exists
|
# Check if actions directory exists
|
||||||
if [ ! -d "${VAULT_ACTIONS_DIR}" ]; then
|
if [ ! -d "${VAULT_ACTIONS_DIR}" ]; then
|
||||||
log "Actions directory not found: ${VAULT_ACTIONS_DIR}"
|
log "Actions directory not found: ${VAULT_ACTIONS_DIR}"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue