This commit is contained in:
@@ -0,0 +1,38 @@
|
|||||||
|
name: HAProxy CI/CD
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
paths:
|
||||||
|
- "stacks/haproxy/**"
|
||||||
|
- "scripts/validate-haproxy.sh"
|
||||||
|
- "scripts/deploy-haproxy.sh"
|
||||||
|
- ".gitea/workflows/haproxy.yml"
|
||||||
|
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
haproxy:
|
||||||
|
|
||||||
|
name: Validate and deploy HAProxy
|
||||||
|
|
||||||
|
runs-on: docker-home-01
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v7
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
|
||||||
|
- name: Validate configuration
|
||||||
|
run: |
|
||||||
|
./scripts/validate-haproxy.sh
|
||||||
|
|
||||||
|
- name: Deploy to production
|
||||||
|
if: ${{ gitea.ref == 'refs/heads/main' }}
|
||||||
|
run: |
|
||||||
|
./scripts/deploy-haproxy.sh
|
||||||
Executable
+158
@@ -0,0 +1,158 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
|
||||||
|
SRC="${ROOT}/stacks/haproxy"
|
||||||
|
LIVE="/srv/nfs/infra/haproxy"
|
||||||
|
ENV_FILE="${LIVE}/.env"
|
||||||
|
|
||||||
|
BACKUP_ROOT="/srv/nfs/infra/.deploy-backups/haproxy"
|
||||||
|
STAMP="$(date '+%Y%m%d-%H%M%S')"
|
||||||
|
BACKUP="${BACKUP_ROOT}/${STAMP}"
|
||||||
|
|
||||||
|
echo "=== HAProxy deployment ==="
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# 1. Pre-deployment validation
|
||||||
|
#
|
||||||
|
|
||||||
|
"${ROOT}/scripts/validate-haproxy.sh"
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# 2. Backup current configuration
|
||||||
|
#
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "--- Backup current configuration ---"
|
||||||
|
|
||||||
|
mkdir -p "${BACKUP}/conf"
|
||||||
|
|
||||||
|
cp -a \
|
||||||
|
"${LIVE}/docker-compose.yml" \
|
||||||
|
"${BACKUP}/docker-compose.yml"
|
||||||
|
|
||||||
|
rsync -a \
|
||||||
|
"${LIVE}/conf/" \
|
||||||
|
"${BACKUP}/conf/"
|
||||||
|
|
||||||
|
echo "Backup: ${BACKUP}"
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Rollback function
|
||||||
|
#
|
||||||
|
|
||||||
|
rollback()
|
||||||
|
{
|
||||||
|
rc=$?
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "!!! Deployment failed"
|
||||||
|
echo "!!! Restoring ${BACKUP}"
|
||||||
|
|
||||||
|
cp -a \
|
||||||
|
"${BACKUP}/docker-compose.yml" \
|
||||||
|
"${LIVE}/docker-compose.yml"
|
||||||
|
|
||||||
|
rsync -a --delete \
|
||||||
|
"${BACKUP}/conf/" \
|
||||||
|
"${LIVE}/conf/"
|
||||||
|
|
||||||
|
(
|
||||||
|
cd "${LIVE}"
|
||||||
|
|
||||||
|
docker compose \
|
||||||
|
--env-file "${ENV_FILE}" \
|
||||||
|
up -d --remove-orphans || true
|
||||||
|
|
||||||
|
docker compose \
|
||||||
|
--env-file "${ENV_FILE}" \
|
||||||
|
restart haproxy || true
|
||||||
|
)
|
||||||
|
|
||||||
|
exit "${rc}"
|
||||||
|
}
|
||||||
|
|
||||||
|
trap rollback ERR
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# 3. Deploy files
|
||||||
|
#
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "--- Deploy configuration ---"
|
||||||
|
|
||||||
|
install \
|
||||||
|
-m 0644 \
|
||||||
|
"${SRC}/docker-compose.yml" \
|
||||||
|
"${LIVE}/docker-compose.yml"
|
||||||
|
|
||||||
|
rsync -a --delete \
|
||||||
|
"${SRC}/conf/" \
|
||||||
|
"${LIVE}/conf/"
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# 4. Apply Docker Compose
|
||||||
|
#
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "--- Apply Docker Compose ---"
|
||||||
|
|
||||||
|
cd "${LIVE}"
|
||||||
|
|
||||||
|
docker compose \
|
||||||
|
--env-file "${ENV_FILE}" \
|
||||||
|
up -d --remove-orphans
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# HAProxy config is bind-mounted.
|
||||||
|
# docker compose will not automatically restart HAProxy
|
||||||
|
# just because haproxy.cfg changed.
|
||||||
|
#
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "--- Restart HAProxy ---"
|
||||||
|
|
||||||
|
docker compose \
|
||||||
|
--env-file "${ENV_FILE}" \
|
||||||
|
restart haproxy
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# 5. Post-deployment validation
|
||||||
|
#
|
||||||
|
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
RUNNING="$(
|
||||||
|
docker inspect \
|
||||||
|
-f '{{.State.Running}}' \
|
||||||
|
haproxy
|
||||||
|
)"
|
||||||
|
|
||||||
|
if [[ "${RUNNING}" != "true" ]]; then
|
||||||
|
echo "ERROR: HAProxy container is not running"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
docker exec \
|
||||||
|
haproxy \
|
||||||
|
haproxy \
|
||||||
|
-c \
|
||||||
|
-f /usr/local/etc/haproxy/haproxy.cfg
|
||||||
|
|
||||||
|
|
||||||
|
trap - ERR
|
||||||
|
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Deployment successful ==="
|
||||||
|
echo "Backup: ${BACKUP}"
|
||||||
Executable
+89
@@ -0,0 +1,89 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
|
||||||
|
SRC="${ROOT}/stacks/haproxy"
|
||||||
|
LIVE="/srv/nfs/infra/haproxy"
|
||||||
|
ENV_FILE="${LIVE}/.env"
|
||||||
|
|
||||||
|
echo "=== HAProxy validation ==="
|
||||||
|
|
||||||
|
if [[ ! -f "${ENV_FILE}" ]]; then
|
||||||
|
echo "ERROR: ${ENV_FILE} not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "${SRC}/docker-compose.yml" ]]; then
|
||||||
|
echo "ERROR: docker-compose.yml not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "${SRC}/conf/haproxy.cfg" ]]; then
|
||||||
|
echo "ERROR: haproxy.cfg not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "--- Validate docker-compose.yml ---"
|
||||||
|
|
||||||
|
docker compose \
|
||||||
|
--env-file "${ENV_FILE}" \
|
||||||
|
-f "${SRC}/docker-compose.yml" \
|
||||||
|
config >/dev/null
|
||||||
|
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "--- Detect HAProxy image ---"
|
||||||
|
|
||||||
|
HAPROXY_IMAGE="$(
|
||||||
|
docker compose \
|
||||||
|
--env-file "${ENV_FILE}" \
|
||||||
|
-f "${SRC}/docker-compose.yml" \
|
||||||
|
config --images |
|
||||||
|
grep -m1 -E '(^|/)haproxy:'
|
||||||
|
)"
|
||||||
|
|
||||||
|
if [[ -z "${HAPROXY_IMAGE}" ]]; then
|
||||||
|
echo "ERROR: HAProxy image not found in compose"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "HAProxy image: ${HAPROXY_IMAGE}"
|
||||||
|
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "--- Validate haproxy.cfg ---"
|
||||||
|
|
||||||
|
TMP_DIR="$(mktemp -d)"
|
||||||
|
|
||||||
|
cleanup()
|
||||||
|
{
|
||||||
|
rm -rf "${TMP_DIR}"
|
||||||
|
}
|
||||||
|
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
mkdir -p "${TMP_DIR}/conf"
|
||||||
|
|
||||||
|
rsync -a \
|
||||||
|
"${SRC}/conf/" \
|
||||||
|
"${TMP_DIR}/conf/"
|
||||||
|
|
||||||
|
|
||||||
|
docker run \
|
||||||
|
--rm \
|
||||||
|
-v "${TMP_DIR}/conf:/usr/local/etc/haproxy:ro" \
|
||||||
|
-v "${LIVE}/certs:/etc/haproxy/certs:ro" \
|
||||||
|
-v "${LIVE}/crowdsec/lua:/usr/lib/crowdsec-haproxy-spoa-bouncer/lua:ro" \
|
||||||
|
-v "${LIVE}/crowdsec/templates:/var/lib/crowdsec-haproxy-spoa-bouncer/html:ro" \
|
||||||
|
"${HAPROXY_IMAGE}" \
|
||||||
|
haproxy \
|
||||||
|
-c \
|
||||||
|
-f /usr/local/etc/haproxy/haproxy.cfg
|
||||||
|
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "=== Validation successful ==="
|
||||||
Reference in New Issue
Block a user