sqlinsight-pro/.forgejo/workflows/deploy-hub.yml
Søren Eggert Lundsteen Olsen 4fdeff87fa
Some checks are pending
CI / Integration (mcr.microsoft.com/mssql/server:2017-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2019-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2022-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2025-latest) (push) Blocked by required conditions
CI / Build og unit tests (push) Successful in 1m10s
deploy hub / deploy (push) Successful in 19s
CI / MSI-installer (push) Successful in 50s
Deploy hub to SEOSoft appserver; run CI on the self-hosted runner
deploy-hub.yml builds deploy/hub/Dockerfile on the appserver runner, writes
.env from repo secrets and starts docker-compose.prod.yml (external
PostgreSQL, /data bind-mounted), then polls /health.

ci.yml used runs-on: docker, which no runner has, so jobs never started.
Build/tests and the MSI now run inside the SDK image via deploy/ci/Dockerfile,
because the host-mode runner ignores container: and has no apt-get.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 15:37:56 +02:00

137 lines
5.2 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# =============================================================================
# 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