# ============================================================================= # Deploy SQLInsight Hub til appserveren ved push til main. # # Kører på den self-hostede appserver-runner (host-mode, docker.sock). # Runner-containeren har ikke INSTALL_DIR mountet, så .env, compose-filen og # 'docker compose up' håndteres via kortlivede helper-containere med # INSTALL_DIR bind-mountet fra værten. # # Alle miljøværdier (også IP'er) kommer fra Forgejo repo-secrets. # # Påkrævede secrets: HOST_BIND HOST_PORT DB_SERVER DB_PORT DB_NAME DB_USER DB_PASSWORD KNOWN_PROXY # Valgfri: TRUSTED_KEY_ID + TRUSTED_KEY (offentlig licensnøgle fra keygen) # ============================================================================= name: deploy hub on: push: branches: [main] paths: - "src/**" - "deploy/hub/**" - "Directory.*.props" - "global.json" - ".forgejo/workflows/deploy-hub.yml" workflow_dispatch: concurrency: group: deploy-sqlinsight-hub cancel-in-progress: false env: INSTALL_DIR: /opt/sqlinsight-hub IMAGE: sqlinsight-hub CONTAINER: sqlinsight-hub jobs: deploy: runs-on: [self-hosted, appserver] timeout-minutes: 30 steps: - name: Checkout uses: actions/checkout@v4 - name: Build image run: | set -e docker build -f deploy/hub/Dockerfile -t "${IMAGE}:latest" -t "${IMAGE}:${{ github.sha }}" . - name: Write .env + docker-compose.yml to INSTALL_DIR env: HOST_BIND: ${{ secrets.HOST_BIND }} HOST_PORT: ${{ secrets.HOST_PORT }} DB_SERVER: ${{ secrets.DB_SERVER }} DB_PORT: ${{ secrets.DB_PORT }} DB_NAME: ${{ secrets.DB_NAME }} DB_USER: ${{ secrets.DB_USER }} DB_PASSWORD: ${{ secrets.DB_PASSWORD }} KNOWN_PROXY: ${{ secrets.KNOWN_PROXY }} TRUSTED_KEY_ID: ${{ secrets.TRUSTED_KEY_ID }} TRUSTED_KEY: ${{ secrets.TRUSTED_KEY }} run: | set -eu required="HOST_BIND HOST_PORT DB_SERVER DB_PORT DB_NAME DB_USER DB_PASSWORD KNOWN_PROXY" missing=0 for v in $required; do if [ -z "$(printenv "$v" || true)" ]; then echo "ERROR: required secret $v is not set in repo settings" missing=1 fi done [ "$missing" -eq 0 ] || exit 1 # Værdier skrives single-quoted, så compose ikke udvider '$' i passwords for v in $required TRUSTED_KEY_ID TRUSTED_KEY; do case "$(printenv "$v" || true)" in *"'"*|*";"*) echo "ERROR: secret $v indeholder ' eller ; – ikke understøttet"; exit 1 ;; esac done tmp="$(mktemp -d)" { printf "HOST_BIND='%s'\n" "$HOST_BIND" printf "HOST_PORT='%s'\n" "$HOST_PORT" printf "ConnectionStrings__Hub='Host=%s;Port=%s;Database=%s;Username=%s;Password=%s;GSS Encryption Mode=Disable'\n" \ "$DB_SERVER" "$DB_PORT" "$DB_NAME" "$DB_USER" "$DB_PASSWORD" printf "SQLInsight__Hub__KnownProxies__0='%s'\n" "$KNOWN_PROXY" if [ -n "${TRUSTED_KEY_ID:-}" ] && [ -n "${TRUSTED_KEY:-}" ]; then printf "SQLInsight__Hub__TrustedKeys__%s='%s'\n" "$TRUSTED_KEY_ID" "$TRUSTED_KEY" else echo "WARNING: TRUSTED_KEY_ID/TRUSTED_KEY ikke sat – hubben kan ikke verificere licenser" >&2 fi } > "$tmp/.env" cp deploy/hub/docker-compose.prod.yml "$tmp/docker-compose.yml" tar -C "$tmp" -cf - .env docker-compose.yml | docker run --rm -i \ -v "${INSTALL_DIR}:/out" alpine:3 \ sh -c 'tar -C /out -xf - && chown root:root /out/.env /out/docker-compose.yml && chmod 600 /out/.env && chmod 644 /out/docker-compose.yml' rm -rf "$tmp" - name: Deploy (compose up) run: | set -eu docker run --rm \ -v /var/run/docker.sock:/var/run/docker.sock \ -v "${INSTALL_DIR}:${INSTALL_DIR}" \ -w "${INSTALL_DIR}" \ docker:cli \ docker compose --project-name sqlinsight-hub up -d --force-recreate --remove-orphans - name: Wait for /health env: HOST_BIND: ${{ secrets.HOST_BIND }} HOST_PORT: ${{ secrets.HOST_PORT }} run: | set -eu # aspnet-imaget har hverken curl eller wget – poll udefra for i in $(seq 1 30); do if docker run --rm alpine:3 wget -qO- -T 3 "http://${HOST_BIND}:${HOST_PORT}/health" 2>/dev/null | grep -q '"ok"'; then echo "${CONTAINER} is healthy" exit 0 fi echo "attempt $i: not ready" sleep 5 done echo "${CONTAINER} did not answer /health within 150s — last 100 log lines:" docker logs --tail 100 "${CONTAINER}" || true exit 1 - name: Prune old images if: always() run: | docker image prune -f || true # Behold latest + de 3 nyeste sha-tags docker images "${IMAGE}" --format '{{.Tag}} {{.CreatedAt}}' \ | grep -v '^latest ' | sort -k2 -r | awk 'NR>3 {print $1}' \ | xargs -r -I{} docker image rm "${IMAGE}:{}" || true