This commit is contained in:
dvirlabs 2026-04-19 01:43:49 +03:00
parent 11b6bcc494
commit e2937a8744

View File

@ -1,4 +1,17 @@
# =============================================================================
# Pipeline 1: CI/CD
# Triggered by: pull_request (validate + drift-check)
# push to master (validate + deploy + post-deploy sync metric)
# =============================================================================
when:
- event: pull_request
- event: push
branch: master
steps: steps:
# ---------------------------------------------------------------------------
# syntax-check: Lint all playbooks runs on pull_request and push
# ---------------------------------------------------------------------------
syntax-check: syntax-check:
image: alpine/ansible:latest image: alpine/ansible:latest
environment: environment:
@ -6,6 +19,9 @@ steps:
commands: commands:
- ansible-playbook -i ansible/inventory/hosts.yml --syntax-check ansible/playbooks/*.yml - ansible-playbook -i ansible/inventory/hosts.yml --syntax-check ansible/playbooks/*.yml
# ---------------------------------------------------------------------------
# validate: Validate server state runs on pull_request and push
# ---------------------------------------------------------------------------
validate: validate:
image: alpine/ansible:latest image: alpine/ansible:latest
depends_on: [syntax-check] depends_on: [syntax-check]
@ -19,6 +35,9 @@ steps:
- chmod 600 ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa
- ansible-playbook -i ansible/inventory/hosts.yml ansible/playbooks/validate.yml - ansible-playbook -i ansible/inventory/hosts.yml ansible/playbooks/validate.yml
# ---------------------------------------------------------------------------
# drift-check: Compare server config to Git runs on pull_request only
# ---------------------------------------------------------------------------
drift-check: drift-check:
image: alpine/ansible:latest image: alpine/ansible:latest
depends_on: [syntax-check] depends_on: [syntax-check]
@ -34,6 +53,9 @@ steps:
when: when:
event: pull_request event: pull_request
# ---------------------------------------------------------------------------
# deploy: Apply Git configuration to server runs on push to master only
# ---------------------------------------------------------------------------
deploy: deploy:
image: alpine/ansible:latest image: alpine/ansible:latest
depends_on: [syntax-check, validate] depends_on: [syntax-check, validate]
@ -49,3 +71,119 @@ steps:
when: when:
branch: master branch: master
event: push event: push
# ---------------------------------------------------------------------------
# update-sync-metric: Verify post-deploy sync and report to Prometheus
# Runs drift-check after deploy; pushes gitops_sync_status metric.
# STATUS=1 means SYNCED, STATUS=0 means OUT_OF_SYNC.
# Runs on push to master only, after deploy succeeds.
# ---------------------------------------------------------------------------
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:
from_secret: PUSHGATEWAY_URL
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
---
# =============================================================================
# Pipeline 2: GitOps Sync Check (ArgoCD-style continuous drift detection)
# Triggered by: cron runs every 2 minutes even without a new push
#
# Purpose: Detect manual configuration changes made directly on the server
# (outside Git). If someone edits /etc/rsyslog.conf by hand, the next cron
# run will catch it and mark the system OUT_OF_SYNC in Prometheus.
#
# This pipeline does NOT deploy anything it is a read-only drift check.
#
# ─── Woodpecker Cron Configuration (set in the Woodpecker UI) ───────────────
# Name: gitops-drift-check
# Branch: master
# Schedule: */2 * * * *
# ─────────────────────────────────────────────────────────────────────────────
#
# Required secrets (Woodpecker → Repository Settings → Secrets):
# SSH_PRIVATE_KEY SSH key to reach the managed server
# PUSHGATEWAY_URL Base URL of Prometheus Pushgateway
# e.g. http://pushgateway:9091
# =============================================================================
when:
event: cron
steps:
# ---------------------------------------------------------------------------
# gitops_sync_check: Read-only drift check + Prometheus metric push
# STATUS=1 → SYNCED (server matches Git)
# STATUS=0 → OUT_OF_SYNC (manual drift detected on server)
# Pipeline is marked FAILED when out of sync so it is visible in the UI.
# ---------------------------------------------------------------------------
gitops_sync_check:
image: alpine/ansible:latest
environment:
ANSIBLE_CONFIG: ansible.cfg
SSH_PRIVATE_KEY:
from_secret: SSH_PRIVATE_KEY
PUSHGATEWAY_URL:
from_secret: PUSHGATEWAY_URL
commands:
- |
apk add --no-cache curl > /dev/null 2>&1
# Prepare SSH key for remote server access
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 non-zero when out of sync so Woodpecker marks the pipeline FAILED
exit $DRIFT_RC