sqlinsight-pro/.forgejo/workflows/deploy-community.yml
Claude 69fa641f26
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
deploy hub / deploy (push) Successful in 24s
CI / Build og unit tests (push) Successful in 56s
deploy community / deploy (push) Successful in 1s
CI / MSI-installer (push) Successful in 33s
Websted og forum bag SEOSofts reverse proxy på appserveren
- deploy-community.yml: bygger og starter webstedet ved push (som hubben),
  bundet til DMZ-adressen. Springes over, indtil COMMUNITY_PORT er sat.
  Feedet læses skrivebeskyttet fra hubbens feed-mappe; download-links går
  til hub.sqlinsight.seosoft.dk/updates/ (ny indstilling DownloadUrl).
- deploy-forum.yml (manuel): kører discourse_docker-launcheren i en
  helper-container med /var/discourse og docker.sock fra værten.
  app.yml er en skabelon, som render.py udfylder fra secrets.
- Discourse uden egen TLS: lytter på DMZ-adressen, tvinger https-links og
  tager klient-IP fra X-Forwarded-For fra proxyen (ellers rammer rate
  limiting alle brugere samlet).
- Caddy-opsætningen er fjernet; docs/community.md beskriver secrets og
  proxy-opsætning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
2026-09-29 13:59:53 +00:00

141 lines
5.3 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 Pro-webstedet (sqlinsight.seosoft.dk) til appserveren ved push til main.
#
# Samme mønster som deploy-hub.yml: runneren er host-mode, så .env og compose-filen skrives til INSTALL_DIR
# via en kortlivet helper-container, og 'docker compose up' køres i docker:cli.
#
# Påkrævede secrets: HOST_BIND COMMUNITY_PORT COMMUNITY_CONTACT
# Valgfri: TRUSTED_KEY_ID + TRUSTED_KEY (offentlig nøgle, som feedet er signeret med, hvis den ikke er indbygget)
# =============================================================================
name: deploy community
on:
push:
branches: [main]
paths:
- "src/**"
- "docs/**"
- "rules/**"
- "deploy/community/**"
- "Directory.*.props"
- "global.json"
- ".forgejo/workflows/deploy-community.yml"
workflow_dispatch:
concurrency:
group: deploy-sqlinsight-community
cancel-in-progress: false
env:
INSTALL_DIR: /opt/sqlinsight-community
IMAGE: sqlinsight-community
CONTAINER: sqlinsight-community
jobs:
deploy:
runs-on: [self-hosted, appserver]
timeout-minutes: 30
steps:
- name: Configured?
id: check
env:
COMMUNITY_PORT: ${{ secrets.COMMUNITY_PORT }}
run: |
# Indtil secrets er sat, springes deploy over i stedet for at fejle hvert push.
if [ -n "${COMMUNITY_PORT:-}" ]; then
echo "configured=true" >> "$GITHUB_OUTPUT"
else
echo "::warning::COMMUNITY_PORT er ikke sat; webstedet deployes ikke (se docs/community.md)"
echo "configured=false" >> "$GITHUB_OUTPUT"
fi
- name: Checkout
if: steps.check.outputs.configured == 'true'
uses: actions/checkout@v4
- name: Build image
if: steps.check.outputs.configured == 'true'
run: |
set -e
docker build -f deploy/community/Dockerfile -t "${IMAGE}:latest" -t "${IMAGE}:${{ github.sha }}" .
- name: Write .env + docker-compose.yml to INSTALL_DIR
if: steps.check.outputs.configured == 'true'
env:
HOST_BIND: ${{ secrets.HOST_BIND }}
COMMUNITY_PORT: ${{ secrets.COMMUNITY_PORT }}
COMMUNITY_CONTACT: ${{ secrets.COMMUNITY_CONTACT }}
TRUSTED_KEY_ID: ${{ secrets.TRUSTED_KEY_ID }}
TRUSTED_KEY: ${{ secrets.TRUSTED_KEY }}
run: |
set -eu
required="HOST_BIND COMMUNITY_PORT COMMUNITY_CONTACT"
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
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 "COMMUNITY_PORT='%s'\n" "$COMMUNITY_PORT"
printf "SQLInsight__Community__ContactEmail='%s'\n" "$COMMUNITY_CONTACT"
if [ -n "${TRUSTED_KEY_ID:-}" ] && [ -n "${TRUSTED_KEY:-}" ]; then
printf "SQLInsight__Community__TrustedKeys__%s='%s'\n" "$TRUSTED_KEY_ID" "$TRUSTED_KEY"
fi
} > "$tmp/.env"
cp deploy/community/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)
if: steps.check.outputs.configured == 'true'
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-community up -d --force-recreate --remove-orphans
- name: Wait for /health
if: steps.check.outputs.configured == 'true'
env:
HOST_BIND: ${{ secrets.HOST_BIND }}
COMMUNITY_PORT: ${{ secrets.COMMUNITY_PORT }}
run: |
set -eu
for i in $(seq 1 30); do
if docker run --rm alpine:3 wget -qO- -T 3 "http://${HOST_BIND}:${COMMUNITY_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() && steps.check.outputs.configured == 'true'
run: |
docker image prune -f || true
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