All checks were successful
Deploy server-up (dev) / deploy (push) Successful in 39s
BIND bleef niet staan. Oorzaak: docker-compose.yml staat in Git, dus rsync zet
dat bestand bij elke deploy terug; een wijziging daarin op de server houdt het
nooit. De juiste plek is .env ernaast, maar dat bestand bevatte na een deploy
alleen een kale SU_TAG-regel en was daarmee niet vindbaar.
- Bestaat er nog geen .env, dan zet de deploy hem op vanuit .env.example, met
alle instellingen erin en uitleg per sleutel. Een bestaande .env blijft
ongemoeid (rsync slaat hem al over sinds 6d5453e).
- De deploy logt nu welke instellingen actief zijn, zodat je in de run-log ziet
wat er staat.
- Waarschuwing in docker-compose.yml zelf dat je BIND daar niet moet aanpassen
maar in .env. Dat bestand wordt toch elke deploy teruggezet, dus de tip staat
er altijd.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C7oLCRYzY5ixJ5Sv8Y8EFb
152 lines
5.6 KiB
YAML
152 lines
5.6 KiB
YAML
name: Deploy server-up (prod)
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
tags: ['v*']
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
group: server-up-deploy-prod
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
deploy:
|
|
runs-on: [self-hosted, prod]
|
|
timeout-minutes: 20
|
|
|
|
env:
|
|
DEPLOY_DIR: /opt/server-up
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 1
|
|
|
|
- name: Bepaal versie
|
|
id: version
|
|
run: |
|
|
set -euo pipefail
|
|
BASE="$(tr -d '[:space:]' < VERSION 2>/dev/null || echo 0.0.0)"
|
|
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
|
|
VERSION="${GITHUB_REF_NAME#v}"
|
|
CHANNEL="release"
|
|
else
|
|
VERSION="${BASE}"
|
|
CHANNEL="main"
|
|
fi
|
|
echo "VERSION=${VERSION}" >> "$GITHUB_ENV"
|
|
echo "CHANNEL=${CHANNEL}" >> "$GITHUB_ENV"
|
|
echo "SU_VERSION=${VERSION}" >> "$GITHUB_ENV"
|
|
echo "Deploying version: ${VERSION} (${CHANNEL})"
|
|
|
|
- name: Tests draaien
|
|
run: |
|
|
set -euo pipefail
|
|
# In een container in plaats van een venv op de runner: die heeft
|
|
# geen python3-venv, en zo draaien de tests bovendien op exact de
|
|
# Python-versie waarop de app in productie draait.
|
|
# PYTHONDONTWRITEBYTECODE + no:cacheprovider voorkomen dat er
|
|
# root-eigen bestanden in de werkmap achterblijven.
|
|
docker run --rm \
|
|
-v "$PWD:/w" -w /w \
|
|
-v su-pip-cache:/root/.cache/pip \
|
|
-e PYTHONDONTWRITEBYTECODE=1 \
|
|
python:3.12-slim \
|
|
sh -c "pip install -q -r server-up/requirements.txt pytest \
|
|
&& python -m pytest tests -q -p no:cacheprovider"
|
|
|
|
- name: Sync code naar deploy-directory
|
|
run: |
|
|
set -euo pipefail
|
|
# .env staat in .gitignore, dus de checkout heeft er geen. Zonder deze
|
|
# uitzondering wist --delete de lokale instellingen van de server
|
|
# (BIND, SU_IMAGE, PORT) bij elke deploy.
|
|
rsync -a --delete \
|
|
--exclude='.git/' \
|
|
--exclude='.forgejo/' \
|
|
--exclude='.env' \
|
|
./ "$DEPLOY_DIR/"
|
|
|
|
- name: Schrijf VERSION-bestand
|
|
working-directory: ${{ env.DEPLOY_DIR }}
|
|
run: echo "${VERSION}" > VERSION
|
|
|
|
- name: Bouwen (en pushen naar de registry)
|
|
working-directory: ${{ env.DEPLOY_DIR }}
|
|
run: |
|
|
set -euo pipefail
|
|
# SU_TAG vastleggen zodat compose en de "Nu bijwerken"-knop in de app
|
|
# naar hetzelfde image wijzen (zie docs/updates.md).
|
|
#
|
|
# Bestaat er nog geen .env, dan zetten we hem op vanuit .env.example,
|
|
# zodat BIND, PORT en SU_IMAGE zichtbaar en instelbaar zijn. Een
|
|
# bestaande .env blijft ongemoeid; rsync slaat hem over.
|
|
if [ ! -f .env ] && [ -f .env.example ]; then
|
|
cp .env.example .env
|
|
echo "Nieuwe .env aangemaakt vanuit .env.example"
|
|
fi
|
|
touch .env
|
|
sed -i '/^SU_TAG=/d' .env
|
|
echo "SU_TAG=${VERSION}" >> .env
|
|
echo "Actieve instellingen:"; grep -vE '^\s*(#|$)' .env | sed 's/^/ /'
|
|
|
|
# Draait deze server vanaf de registry (SU_IMAGE in .env), dan bouwen
|
|
# we hier én pushen we het resultaat, zodat de in-app updateknop het
|
|
# image kan ophalen. Bouwen en pushen zitten bewust in dezelfde job:
|
|
# een aparte build-workflow zou met deze deploy om de runner strijden.
|
|
SU_IMAGE="$(grep -E '^SU_IMAGE=' .env | cut -d= -f2- || true)"
|
|
docker compose build --pull
|
|
|
|
if [ -n "$SU_IMAGE" ]; then
|
|
echo "Registry-modus: ${SU_IMAGE}:${VERSION} pushen"
|
|
echo "${{ secrets.PACKAGE_TOKEN }}" \
|
|
| docker login "${{ vars.REGISTRY }}" -u "${{ vars.OWNER }}" --password-stdin
|
|
docker tag "${SU_IMAGE}:${VERSION}" "${SU_IMAGE}:${CHANNEL}" || true
|
|
docker push "${SU_IMAGE}:${VERSION}"
|
|
# Pre-releases krijgen geen 'latest': dat hoort bij stable.
|
|
case "$VERSION" in
|
|
*-*) docker tag "${SU_IMAGE}:${VERSION}" "${SU_IMAGE}:beta"
|
|
docker push "${SU_IMAGE}:beta" ;;
|
|
*) docker tag "${SU_IMAGE}:${VERSION}" "${SU_IMAGE}:latest"
|
|
docker push "${SU_IMAGE}:latest" ;;
|
|
esac
|
|
docker logout "${{ vars.REGISTRY }}" || true
|
|
else
|
|
echo "Lokale bouwmodus (geen SU_IMAGE ingesteld)"
|
|
docker tag "server-up:${VERSION}" "server-up:${CHANNEL}" || true
|
|
fi
|
|
|
|
- name: Deploy
|
|
working-directory: ${{ env.DEPLOY_DIR }}
|
|
run: |
|
|
set -euo pipefail
|
|
docker compose up -d --remove-orphans
|
|
docker compose ps
|
|
|
|
- name: Wachten op healthcheck
|
|
run: |
|
|
set -euo pipefail
|
|
for i in {1..40}; do
|
|
status=$(docker inspect --format '{{.State.Health.Status}}' server-up 2>/dev/null || echo "starting")
|
|
echo "poll $i: $status"
|
|
if [ "$status" = "healthy" ]; then
|
|
echo "server-up is healthy als versie ${VERSION}"
|
|
exit 0
|
|
fi
|
|
sleep 3
|
|
done
|
|
echo "server-up werd niet healthy in tijd — logs:"
|
|
cd "$DEPLOY_DIR" && docker compose logs --tail=200
|
|
exit 1
|
|
|
|
- name: Oude images opruimen (behoud laatste 5)
|
|
if: success()
|
|
run: |
|
|
docker images server-up --format '{{.Tag}} {{.ID}}' \
|
|
| grep -vE '^(latest|release|main) ' \
|
|
| tail -n +6 \
|
|
| awk '{print $2}' \
|
|
| xargs -r docker rmi -f || true
|
|
docker image prune -f
|