From 9a9c740b9a4c704d0c29ea330a207906475bbaa8 Mon Sep 17 00:00:00 2001 From: Sirius Devops Date: Fri, 28 Aug 2026 03:55:00 +0000 Subject: [PATCH] ci: publish all OSINT images to Forgejo registry Push api/pg/news-scraper/news-summarizer to forgejo.siriusdevops.com/sirius/* on every master build, then deploy on the Pi runner. No GHCR. Helper script retags pulls to localhost/* for compose. --- .env.example | 10 +++ .forgejo/workflows/build.yml | 142 ++++++++++++++++++++++++++++++--- scripts/pull-forgejo-images.sh | 10 +++ 3 files changed, 150 insertions(+), 12 deletions(-) create mode 100755 scripts/pull-forgejo-images.sh diff --git a/.env.example b/.env.example index d7a4f36..7bf60b3 100644 --- a/.env.example +++ b/.env.example @@ -91,3 +91,13 @@ NEWS_LOG_LEVEL=INFO # Reserved for the (out-of-scope) Telegram delivery bot. TELEGRAM_TOKEN= TELEGRAM_CHAT_ID= + +# ============================================================================= +# Forgejo container registry (CI publishes here; NOT ghcr.io) +# ============================================================================= +# forgejo.siriusdevops.com/sirius/osint-dashboard[:tag] +# forgejo.siriusdevops.com/sirius/osint-dashboard-pg[:tag] +# forgejo.siriusdevops.com/sirius/osint-news-scraper[:tag] +# forgejo.siriusdevops.com/sirius/osint-news-summarizer[:tag] +FORGEJO_REGISTRY=forgejo.siriusdevops.com +FORGEJO_OWNER=sirius diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml index d5a61e2..d9bf492 100644 --- a/.forgejo/workflows/build.yml +++ b/.forgejo/workflows/build.yml @@ -1,27 +1,145 @@ +# Build all OSINT images, publish to the Forgejo container registry, then +# redeploy on the Pi runner (docker.sock mounted). +# +# Registry: forgejo.siriusdevops.com (NOT ghcr.io) +# Images: +# forgejo.siriusdevops.com/sirius/osint-dashboard +# forgejo.siriusdevops.com/sirius/osint-dashboard-pg +# forgejo.siriusdevops.com/sirius/osint-news-scraper +# forgejo.siriusdevops.com/sirius/osint-news-summarizer +# +# Optional repo variable FORGEJO_REGISTRY overrides the host (default below). +# Deploy still uses the local docker socket on the runner host (rpi). + name: build-and-deploy + on: push: branches: [main, master] + workflow_dispatch: + +env: + # Hostname only — Forgejo packages registry + REGISTRY: ${{ vars.FORGEJO_REGISTRY || 'forgejo.siriusdevops.com' }} + OWNER: sirius + # Keep compose project/volumes stable on the Pi + COMPOSE_PROJECT_NAME: osint-dashboard + jobs: - build: + build-push-deploy: runs-on: docker + permissions: + contents: read + packages: write steps: - name: Checkout uses: https://code.forgejo.org/actions/checkout@v4 - - name: Build and deploy on the Pi (local docker) + + - name: Image refs + id: img + run: | + set -euo pipefail + REG="${REGISTRY}" + OWN="${OWNER}" + SHA="${GITHUB_SHA::12}" + { + echo "reg=$REG" + echo "sha=$SHA" + echo "app=$REG/$OWN/osint-dashboard" + echo "pg=$REG/$OWN/osint-dashboard-pg" + echo "scraper=$REG/$OWN/osint-news-scraper" + echo "summarizer=$REG/$OWN/osint-news-summarizer" + } >> "$GITHUB_OUTPUT" + echo "Registry: $REG" + echo "SHA tag: $SHA" + + - name: Login to Forgejo registry + run: | + set -euo pipefail + # Forgejo Actions token can push packages when packages:write is granted + echo "${{ secrets.GITHUB_TOKEN }}" | docker login "${{ steps.img.outputs.reg }}" \ + -u "${{ github.actor }}" --password-stdin + + - name: Build application image (api / ingester / cameras) + run: | + set -ex + APP="${{ steps.img.outputs.app }}" + SHA="${{ steps.img.outputs.sha }}" + docker build -f Dockerfile -t "${APP}:latest" -t "${APP}:${SHA}" \ + -t "localhost/osint-dashboard:latest" . + docker push "${APP}:latest" + docker push "${APP}:${SHA}" + + - name: Build news-scraper image + run: | + set -ex + IMG="${{ steps.img.outputs.scraper }}" + SHA="${{ steps.img.outputs.sha }}" + docker build -f news/scraper/Dockerfile -t "${IMG}:latest" -t "${IMG}:${SHA}" \ + -t "localhost/osint-news-scraper:latest" news/scraper + docker push "${IMG}:latest" + docker push "${IMG}:${SHA}" + + - name: Build news-summarizer image + run: | + set -ex + IMG="${{ steps.img.outputs.summarizer }}" + SHA="${{ steps.img.outputs.sha }}" + docker build -f news/summerizer/Dockerfile -t "${IMG}:latest" -t "${IMG}:${SHA}" \ + -t "localhost/osint-news-summarizer:latest" news/summerizer + docker push "${IMG}:latest" + docker push "${IMG}:${SHA}" + + - name: Build / refresh Timescale+PostGIS image + run: | + set -ex + PG="${{ steps.img.outputs.pg }}" + SHA="${{ steps.img.outputs.sha }}" + # Prefer rebuild so registry always has a current pg image. If packagecloud + # is unreachable, fall back to whatever local image already exists. + if docker build -f Dockerfile.pg -t "${PG}:latest" -t "${PG}:${SHA}" \ + -t "localhost/osint-dashboard-pg:latest" .; then + docker push "${PG}:latest" + docker push "${PG}:${SHA}" + elif docker image inspect "localhost/osint-dashboard-pg:latest" >/dev/null 2>&1; then + echo "WARN: Dockerfile.pg build failed; retagging existing local pg image into registry" + docker tag "localhost/osint-dashboard-pg:latest" "${PG}:latest" + docker tag "localhost/osint-dashboard-pg:latest" "${PG}:${SHA}" + docker push "${PG}:latest" + docker push "${PG}:${SHA}" + else + echo "ERROR: cannot build or find osint-dashboard-pg image" + exit 1 + fi + + - name: Deploy on runner host (compose) run: | set -ex - # The forgejo-runner runs on the Pi with /var/run/docker.sock and - # /opt/siriusdevops mounted, so we build + deploy LOCALLY — no SSH/scp. - # Deploy straight from the checked-out workspace. cd "${GITHUB_WORKSPACE}" - # Project name is pinned by `name:` in docker-compose.yml - # (osint-dashboard), matching the live volume - # osint-dashboard_osint-pgdata. Do NOT override COMPOSE_PROJECT_NAME - # here — a different name would create a fresh empty pgdata volume. - docker compose build --no-cache + # Pull from Forgejo registry into local tags compose expects, then up. + # Compose file still uses localhost/* for stable local names; we mirror + # registry tags so a cold host can recover via docker pull. + REG="${{ steps.img.outputs.reg }}" + OWN="${{ env.OWNER }}" + for name in osint-dashboard osint-dashboard-pg osint-news-scraper osint-news-summarizer; do + docker pull "${REG}/${OWN}/${name}:latest" || true + docker tag "${REG}/${OWN}/${name}:latest" "localhost/${name}:latest" || true + done + # Do NOT set COMPOSE_PROJECT_NAME differently — volumes must stay + # osint-dashboard_osint-pgdata (pinned by `name:` in compose). + docker compose build --no-cache app ingester camera-service news-scraper news-summarizer || \ + docker compose build app ingester camera-service news-scraper news-summarizer docker compose up -d --force-recreate docker image prune -f - echo 'osint-dashboard deployed (local)' + echo "osint-dashboard deployed; images also on ${REG}/${OWN}/" -# deployed locally on the Pi via runner (docker socket + cli-plugins mounted) + - name: Summary + if: always() + run: | + { + echo "## Forgejo registry images" + echo "- \`${{ steps.img.outputs.app }}:latest\`" + echo "- \`${{ steps.img.outputs.pg }}:latest\`" + echo "- \`${{ steps.img.outputs.scraper }}:latest\`" + echo "- \`${{ steps.img.outputs.summarizer }}:latest\`" + } >> "$GITHUB_STEP_SUMMARY" diff --git a/scripts/pull-forgejo-images.sh b/scripts/pull-forgejo-images.sh new file mode 100755 index 0000000..6f8c1be --- /dev/null +++ b/scripts/pull-forgejo-images.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +# Pull OSINT images from Forgejo registry and retag for docker-compose (localhost/*). +set -euo pipefail +REG="${FORGEJO_REGISTRY:-forgejo.siriusdevops.com}" +OWN="${FORGEJO_OWNER:-sirius}" +for name in osint-dashboard osint-dashboard-pg osint-news-scraper osint-news-summarizer; do + docker pull "${REG}/${OWN}/${name}:latest" + docker tag "${REG}/${OWN}/${name}:latest" "localhost/${name}:latest" + echo "ok ${name}" +done