179 lines
6.7 KiB
YAML
179 lines
6.7 KiB
YAML
# =============================================================================
|
||
# Single pipeline – all event types handled via step-level when conditions:
|
||
# pull_request → syntax-check, validate, drift-check
|
||
# push (master) → syntax-check, validate, deploy, update-sync-metric
|
||
# cron → gitops_sync_check (read-only drift check, no deploy)
|
||
#
|
||
# NOTE: Woodpecker does not support multiple YAML documents (---) in one file.
|
||
# All pipelines must live in a single document with step-level filtering.
|
||
# =============================================================================
|
||
when:
|
||
- event: pull_request
|
||
- event: push
|
||
branch: master
|
||
- event: cron
|
||
|
||
steps:
|
||
# ---------------------------------------------------------------------------
|
||
# syntax-check: Lint all playbooks – runs on pull_request and push
|
||
# ---------------------------------------------------------------------------
|
||
syntax-check:
|
||
image: alpine/ansible:latest
|
||
environment:
|
||
ANSIBLE_CONFIG: ansible.cfg
|
||
commands:
|
||
- ansible-playbook -i ansible/inventory/hosts.yml --syntax-check ansible/playbooks/*.yml
|
||
when:
|
||
- event: pull_request
|
||
- event: push
|
||
branch: master
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# validate: Validate server state – runs on pull_request and push
|
||
# ---------------------------------------------------------------------------
|
||
validate:
|
||
image: alpine/ansible:latest
|
||
depends_on: [syntax-check]
|
||
environment:
|
||
ANSIBLE_CONFIG: ansible.cfg
|
||
SSH_PRIVATE_KEY:
|
||
from_secret: SSH_PRIVATE_KEY
|
||
commands:
|
||
- mkdir -p ~/.ssh
|
||
- printf '%s\n' "$${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa
|
||
- chmod 600 ~/.ssh/id_rsa
|
||
- ansible-playbook -i ansible/inventory/hosts.yml ansible/playbooks/validate.yml
|
||
when:
|
||
- event: pull_request
|
||
- event: push
|
||
branch: master
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# drift-check: Compare server config to Git – runs on pull_request only
|
||
# ---------------------------------------------------------------------------
|
||
drift-check:
|
||
image: alpine/ansible:latest
|
||
depends_on: [syntax-check]
|
||
environment:
|
||
ANSIBLE_CONFIG: ansible.cfg
|
||
SSH_PRIVATE_KEY:
|
||
from_secret: SSH_PRIVATE_KEY
|
||
commands:
|
||
- mkdir -p ~/.ssh
|
||
- printf '%s\n' "$${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa
|
||
- chmod 600 ~/.ssh/id_rsa
|
||
- ansible-playbook -i ansible/inventory/hosts.yml ansible/playbooks/drift-check.yml
|
||
when:
|
||
event: pull_request
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# deploy: Apply Git configuration to server – runs on push to master only
|
||
# ---------------------------------------------------------------------------
|
||
deploy:
|
||
image: alpine/ansible:latest
|
||
depends_on: [syntax-check, validate]
|
||
environment:
|
||
ANSIBLE_CONFIG: ansible.cfg
|
||
SSH_PRIVATE_KEY:
|
||
from_secret: SSH_PRIVATE_KEY
|
||
commands:
|
||
- mkdir -p ~/.ssh
|
||
- printf '%s\n' "$${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa
|
||
- chmod 600 ~/.ssh/id_rsa
|
||
- ansible-playbook -i ansible/inventory/hosts.yml ansible/playbooks/apply.yml
|
||
when:
|
||
branch: master
|
||
event: push
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# update-sync-metric: Post-deploy sync check + Prometheus metric push
|
||
# Runs on push to master only, after deploy succeeds.
|
||
# STATUS=1 means SYNCED, STATUS=0 means OUT_OF_SYNC.
|
||
# ---------------------------------------------------------------------------
|
||
update-sync-metric:
|
||
image: alpine/ansible:latest
|
||
depends_on: [deploy]
|
||
environment:
|
||
ANSIBLE_CONFIG: ansible.cfg
|
||
SSH_PRIVATE_KEY:
|
||
from_secret: SSH_PRIVATE_KEY
|
||
PUSHGATEWAY_URL: http://pushgateway.observability-stack.svc.cluster.local:9091
|
||
commands:
|
||
- |
|
||
apk add --no-cache curl > /dev/null 2>&1
|
||
mkdir -p ~/.ssh
|
||
printf '%s\n' "$${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa
|
||
chmod 600 ~/.ssh/id_rsa
|
||
|
||
echo "==> Verifying post-deploy sync status..."
|
||
set +e
|
||
ansible-playbook -i ansible/inventory/hosts.yml ansible/playbooks/drift-check.yml
|
||
DRIFT_RC=$?
|
||
set -e
|
||
|
||
if [ "$DRIFT_RC" -eq 0 ]; then
|
||
STATUS=1
|
||
echo "==> SYNCED (1) – server configuration matches Git"
|
||
else
|
||
STATUS=0
|
||
echo "==> OUT OF SYNC (0) – drift detected after deploy"
|
||
fi
|
||
|
||
printf 'gitops_sync_status{repo="rsyslog",server="rsyslog-lab"} %s\n' "$STATUS" | \
|
||
curl --silent --show-error --fail --data-binary @- \
|
||
"$${PUSHGATEWAY_URL}/metrics/job/gitops_rsyslog/instance/rsyslog-lab"
|
||
|
||
exit $DRIFT_RC
|
||
when:
|
||
branch: master
|
||
event: push
|
||
|
||
# ---------------------------------------------------------------------------
|
||
# gitops_sync_check: ArgoCD-style cron drift check – read-only, no deploy
|
||
# Detects manual changes made directly on the server between pushes.
|
||
# STATUS=1 → SYNCED, STATUS=0 → OUT_OF_SYNC
|
||
# Pipeline marked FAILED when drift found so it is visible in the UI.
|
||
#
|
||
# ─── Woodpecker Cron UI settings ──────────────────────────────────────────
|
||
# Name: gitops_sync_check
|
||
# Branch: master
|
||
# Schedule: */2 * * * *
|
||
# ---------------------------------------------------------------------------
|
||
gitops_sync_check:
|
||
image: alpine/ansible:latest
|
||
environment:
|
||
ANSIBLE_CONFIG: ansible.cfg
|
||
SSH_PRIVATE_KEY:
|
||
from_secret: SSH_PRIVATE_KEY
|
||
PUSHGATEWAY_URL: http://pushgateway.observability-stack.svc.cluster.local:9091
|
||
commands:
|
||
- |
|
||
apk add --no-cache curl > /dev/null 2>&1
|
||
|
||
mkdir -p ~/.ssh
|
||
printf '%s\n' "$${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa
|
||
chmod 600 ~/.ssh/id_rsa
|
||
|
||
echo "==> [cron] Running drift check against remote server..."
|
||
set +e
|
||
ansible-playbook -i ansible/inventory/hosts.yml ansible/playbooks/drift-check.yml
|
||
DRIFT_RC=$?
|
||
set -e
|
||
|
||
if [ "$DRIFT_RC" -eq 0 ]; then
|
||
STATUS=1
|
||
echo "==> STATUS: SYNCED (1) – server configuration matches Git"
|
||
else
|
||
STATUS=0
|
||
echo "==> STATUS: OUT OF SYNC (0) – manual drift detected on server"
|
||
fi
|
||
|
||
echo "==> Pushing metric: gitops_sync_status{repo=\"rsyslog\",server=\"rsyslog-lab\"} $STATUS"
|
||
printf 'gitops_sync_status{repo="rsyslog",server="rsyslog-lab"} %s\n' "$STATUS" | \
|
||
curl --silent --show-error --fail --data-binary @- \
|
||
"$${PUSHGATEWAY_URL}/metrics/job/gitops_rsyslog/instance/rsyslog-lab"
|
||
|
||
exit $DRIFT_RC
|
||
when:
|
||
event: cron
|