name: CD BRouter # Ported from .github/workflows/cd-brouter.yml for Forgejo Actions. # Differences: no `environment: infra`; the image push logs in to ghcr.io # with DEPLOY_GHCR_TOKEN (decrypted) instead of the GitHub auto token. on: push: branches: [main] paths: - "docker/brouter/**" - "infrastructure/brouter-host/**" workflow_dispatch: {} concurrency: group: deploy-brouter cancel-in-progress: true jobs: build: name: Build & Push BRouter Image runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - name: Decrypt secret + login to GHCR run: | curl -sLO https://github.com/getsops/sops/releases/download/v3.9.4/sops-v3.9.4.linux.amd64 chmod +x sops-v3.9.4.linux.amd64 SOPS_AGE_KEY="${{ secrets.AGE_SECRET_KEY }}" ./sops-v3.9.4.linux.amd64 -d infrastructure/secrets.app.env \ | grep '^DEPLOY_GHCR_TOKEN=' | cut -d= -f2- \ | docker login ghcr.io -u stigi --password-stdin - uses: docker/build-push-action@v7 with: context: docker/brouter push: true tags: | ghcr.io/trails-cool/brouter:latest ghcr.io/trails-cool/brouter:${{ github.sha }} deploy: name: Deploy BRouter to dedicated host needs: [build] runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 - name: Decrypt shared secret id: decrypt run: | curl -sLO https://github.com/getsops/sops/releases/download/v3.9.4/sops-v3.9.4.linux.amd64 chmod +x sops-v3.9.4.linux.amd64 SOPS_AGE_KEY="${{ secrets.AGE_SECRET_KEY }}" ./sops-v3.9.4.linux.amd64 -d infrastructure/secrets.app.env \ | grep '^BROUTER_AUTH_TOKEN=' > infrastructure/brouter-host/.env chmod 0600 infrastructure/brouter-host/.env GHCR_TOKEN=$(SOPS_AGE_KEY="${{ secrets.AGE_SECRET_KEY }}" ./sops-v3.9.4.linux.amd64 -d infrastructure/secrets.app.env \ | grep '^DEPLOY_GHCR_TOKEN=' | cut -d= -f2-) echo "::add-mask::$GHCR_TOKEN" echo "GHCR_TOKEN=$GHCR_TOKEN" >> $GITHUB_ENV - name: Deploy to dedicated host (single SSH connection) env: SSH_KEY: ${{ secrets.BROUTER_DEPLOY_SSH_KEY }} HOST: ${{ secrets.BROUTER_DEPLOY_HOST }} PORT: ${{ secrets.BROUTER_DEPLOY_SSH_PORT }} run: | set -euo pipefail install -m 0600 /dev/null ~/id_deploy printf '%s\n' "$SSH_KEY" > ~/id_deploy TARBALL_B64=$(tar -C infrastructure/brouter-host -czf - \ docker-compose.yml Caddyfile promtail-config.yml \ download-segments.sh .env \ poi-extract \ | base64 -w0) ssh -i ~/id_deploy -p "$PORT" \ -o StrictHostKeyChecking=accept-new \ -o UserKnownHostsFile=/tmp/known_hosts \ -o ConnectTimeout=30 \ trails@"$HOST" \ "TARBALL_B64='$TARBALL_B64' GHCR_TOKEN='$GHCR_TOKEN' bash -s" <<'REMOTE' set -euo pipefail mkdir -p ~/brouter && cd ~/brouter echo "$TARBALL_B64" | base64 -d | tar -xzf - chmod +x download-segments.sh poi-extract/poi-extract.sh poi-extract/to-ndjson.py if [ ! -d segments ] || [ -z "$(ls -A segments 2>/dev/null)" ]; then echo "WARNING: segments/ is empty. BRouter will start but return 404 until segments are seeded." mkdir -p segments fi echo "$GHCR_TOKEN" | docker login ghcr.io -u stigi --password-stdin docker compose pull docker compose up -d --remove-orphans docker compose ps REMOTE - name: Annotate deploy in flagship Grafana uses: appleboy/ssh-action@v1 with: host: ${{ secrets.DEPLOY_HOST }} username: root key: ${{ secrets.DEPLOY_SSH_KEY }} script: | cd /opt/trails-cool GRAFANA_TOKEN=$(grep GRAFANA_SERVICE_TOKEN .env | cut -d= -f2-) if [ -n "$GRAFANA_TOKEN" ]; then docker compose exec -T grafana curl -sf -X POST \ -H "Authorization: Bearer $GRAFANA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"text":"Deploy brouter ${{ github.sha }}","tags":["deploy","brouter"]}' \ http://localhost:3000/api/annotations || true fi