diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 5a7f5de..ffba845 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -4,10 +4,17 @@ on: push: pull_request: +# Registry on the local Gitea instance (HTTP — add to Docker insecure-registries if needed) +env: + REGISTRY: 192.168.0.234:8765 + # Deployment directory on the host — compose file lives here so relative + # volume paths (./infra/traefik/...) resolve correctly on the host. + DEPLOY_DIR: /opt/ems + jobs: # ── Test ────────────────────────────────────────────────────────────────── - # Runs on every push and every PR. Must pass before deploy proceeds. + # Runs on every push and every PR. test: runs-on: ubuntu-latest steps: @@ -26,48 +33,74 @@ jobs: - name: Build binary (compile check) run: CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /dev/null . - # ── Deploy ──────────────────────────────────────────────────────────────── - # Runs only on push to main. SSH into the Synology, pull, rebuild, restart. + # ── Build & Push ────────────────────────────────────────────────────────── + # Builds the Docker image and pushes it to the Gitea container registry. + # Runs on house/lutz and main; skipped on other branches and PRs. # - # Required secrets (set in Gitea → Repository → Settings → Secrets): - # DEPLOY_HOST — Synology LAN IP or hostname (e.g. 192.168.0.10) - # DEPLOY_USER — SSH user with docker access (e.g. ems-deploy) - # DEPLOY_KEY — SSH private key (PEM, no passphrase) - # DEPLOY_PATH — Absolute path to this repo on the Synology (e.g. /opt/ems) - # - # One-time setup on Synology: - # 1. Create a dedicated deploy user (or reuse existing) - # 2. Add the deploy public key to ~/.ssh/authorized_keys - # 3. Add the user to the 'docker' group: sudo synogroup --member docker deploy-user - deploy: + # Required secret: + # GITEA_TOKEN — personal access token with write:packages permission + build-push: needs: test runs-on: ubuntu-latest - if: github.ref == 'refs/heads/main' - + if: github.ref == 'refs/heads/house/lutz' || github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v4 - - name: Install SSH key + - name: Log in to Gitea registry run: | - mkdir -p ~/.ssh - echo "${{ secrets.DEPLOY_KEY }}" > ~/.ssh/deploy_key - chmod 600 ~/.ssh/deploy_key - # Suppress host key prompt — runner talks to a known LAN host - echo "Host ${{ secrets.DEPLOY_HOST }}" >> ~/.ssh/config - echo " StrictHostKeyChecking no" >> ~/.ssh/config - echo " IdentityFile ~/.ssh/deploy_key" >> ~/.ssh/config + echo "${{ secrets.GITEA_TOKEN }}" | \ + docker login ${{ env.REGISTRY }} -u ${{ gitea.actor }} --password-stdin - - name: Deploy to Synology + - name: Build and push image run: | - ssh "${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}" \ - "cd ${{ secrets.DEPLOY_PATH }} \ - && git pull --ff-only \ - && docker compose up -d --build \ - && docker image prune -f" + IMAGE=${{ env.REGISTRY }}/${{ gitea.repository_owner }}/ems + docker build \ + -t ${IMAGE}:${{ gitea.sha }} \ + -t ${IMAGE}:latest \ + . + docker push ${IMAGE}:${{ gitea.sha }} + docker push ${IMAGE}:latest + echo "IMAGE=${IMAGE}:${{ gitea.sha }}" >> $GITHUB_ENV + + # ── Deploy ──────────────────────────────────────────────────────────────── + # Syncs compose + infra files to DEPLOY_DIR on the host, then restarts + # only the EMS container. Traefik keeps running untouched. + # + # Uses a docker:cli helper container so that: + # - relative paths in docker-compose.yml resolve from DEPLOY_DIR on the host + # - Docker socket gives access to the host daemon from within the job container + deploy: + needs: build-push + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/house/lutz' || github.ref == 'refs/heads/main' + steps: + - uses: actions/checkout@v4 + + - name: Log in to Gitea registry + run: | + echo "${{ secrets.GITEA_TOKEN }}" | \ + docker login ${{ env.REGISTRY }} -u ${{ gitea.actor }} --password-stdin + + - name: Sync files and restart EMS + run: | + IMAGE=${{ env.REGISTRY }}/${{ gitea.repository_owner }}/ems:${{ gitea.sha }} + + docker run --rm \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v ${{ env.DEPLOY_DIR }}:${{ env.DEPLOY_DIR }} \ + -v "$(pwd)":/src:ro \ + -e EMS_IMAGE=${IMAGE} \ + docker:cli sh -c " + set -e + mkdir -p ${{ env.DEPLOY_DIR }} + cp /src/docker-compose.yml ${{ env.DEPLOY_DIR }}/ + cp -r /src/infra ${{ env.DEPLOY_DIR }}/ + cd ${{ env.DEPLOY_DIR }} + docker compose pull ems + docker compose up -d ems + " - name: Verify health run: | - # Wait for container to come up, then check /health via LAN sleep 10 - ssh "${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}" \ - "wget -qO- http://localhost:9099/health" + wget -qO- http://localhost:9099/health && echo " — OK" diff --git a/docker-compose.yml b/docker-compose.yml index 6572db5..52e2213 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -26,7 +26,12 @@ services: # ── EMS ───────────────────────────────────────────────────────────────────── # Web UI is NOT exposed externally — Traefik proxies to :9099 internally. # Prometheus metrics on :9101 stay LAN-accessible for the existing scrape job. + # + # Image source: + # CI deploy: EMS_IMAGE=192.168.0.234:8765/owner/ems:sha docker compose up -d ems + # Local dev: docker compose up --build ems: + image: ${EMS_IMAGE:-ems:latest} build: . restart: unless-stopped ports: