feat(ansible): Canonical IaC playbook for fleet management
Some checks failed
PR Checklist / pr-checklist (pull_request) Failing after 1m27s
Some checks failed
PR Checklist / pr-checklist (pull_request) Failing after 1m27s
Implements the Ansible Infrastructure as Code story from KT 2026-04-08. One canonical Ansible playbook defines: - Deadman switch (snapshot good config on health, rollback+restart on death) - Golden state config deployment (Anthropic BANNED, Kimi→Gemini→Ollama) - Cron schedule (source-controlled, no manual crontab edits) - Agent startup sequence (pull→validate→start→verify) - request_log telemetry table (every inference call logged) - Thin config pattern (immutable local pointer to upstream) - Gitea webhook handler (deploy on merge) - Config validator (rejects banned providers) Fleet inventory: Timmy (Mac), Allegro (VPS), Bezalel (VPS), Ezra (VPS) Roles: wizard_base, golden_state, deadman_switch, request_log, cron_manager Addresses: timmy-config #442, #443, #444, #445, #446 References: KT Final 2026-04-08 P2, KT Bezalel 2026-04-08 #1-#5
This commit is contained in:
75
ansible/scripts/deploy_on_webhook.sh
Normal file
75
ansible/scripts/deploy_on_webhook.sh
Normal file
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# Gitea Webhook Handler — Trigger Ansible Deploy on Merge
|
||||
# =============================================================================
|
||||
# This script is called by the Gitea webhook when a PR is merged
|
||||
# to the main branch of timmy-config.
|
||||
#
|
||||
# Setup:
|
||||
# 1. Add webhook in Gitea: Settings → Webhooks → Add Webhook
|
||||
# 2. URL: http://localhost:9000/hooks/deploy-timmy-config
|
||||
# 3. Events: Pull Request (merged only)
|
||||
# 4. Secret: <configured in Gitea>
|
||||
#
|
||||
# This script runs ansible-pull to update the local machine.
|
||||
# For fleet-wide deploys, each machine runs ansible-pull independently.
|
||||
# =============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
REPO="https://forge.alexanderwhitestone.com/Timmy_Foundation/timmy-config.git"
|
||||
BRANCH="main"
|
||||
ANSIBLE_DIR="ansible"
|
||||
LOG_FILE="/var/log/ansible/webhook-deploy.log"
|
||||
LOCK_FILE="/tmp/ansible-deploy.lock"
|
||||
|
||||
log() {
|
||||
echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] [webhook] $*" | tee -a "${LOG_FILE}"
|
||||
}
|
||||
|
||||
# Prevent concurrent deploys
|
||||
if [ -f "${LOCK_FILE}" ]; then
|
||||
LOCK_AGE=$(( $(date +%s) - $(stat -c %Y "${LOCK_FILE}" 2>/dev/null || echo 0) ))
|
||||
if [ "${LOCK_AGE}" -lt 300 ]; then
|
||||
log "Deploy already in progress (lock age: ${LOCK_AGE}s). Skipping."
|
||||
exit 0
|
||||
else
|
||||
log "Stale lock file (${LOCK_AGE}s old). Removing."
|
||||
rm -f "${LOCK_FILE}"
|
||||
fi
|
||||
fi
|
||||
|
||||
trap 'rm -f "${LOCK_FILE}"' EXIT
|
||||
touch "${LOCK_FILE}"
|
||||
|
||||
log "Webhook triggered. Starting ansible-pull..."
|
||||
|
||||
# Pull latest config
|
||||
cd /tmp
|
||||
rm -rf timmy-config-deploy
|
||||
git clone --depth 1 --branch "${BRANCH}" "${REPO}" timmy-config-deploy 2>&1 | tee -a "${LOG_FILE}"
|
||||
|
||||
cd timmy-config-deploy/${ANSIBLE_DIR}
|
||||
|
||||
# Run Ansible against localhost
|
||||
log "Running Ansible playbook..."
|
||||
ansible-playbook \
|
||||
-i inventory/hosts.yml \
|
||||
playbooks/site.yml \
|
||||
--limit "$(hostname)" \
|
||||
--diff \
|
||||
2>&1 | tee -a "${LOG_FILE}"
|
||||
|
||||
RESULT=$?
|
||||
|
||||
if [ ${RESULT} -eq 0 ]; then
|
||||
log "Deploy successful."
|
||||
else
|
||||
log "ERROR: Deploy failed with exit code ${RESULT}."
|
||||
fi
|
||||
|
||||
# Cleanup
|
||||
rm -rf /tmp/timmy-config-deploy
|
||||
|
||||
log "Webhook handler complete."
|
||||
exit ${RESULT}
|
||||
Reference in New Issue
Block a user