# Runs only on pushes to main. # Builds the Docker image on the CI runner host (which has Docker socket access), # pushes it to the Forgejo container registry, then SSHes to the app host to restart. # # Runner requirement: act_runner with /var/run/docker.sock mounted (see infra/runner-swarm.yml). # # Required secrets (Forgejo repo → Settings → Secrets): # REGISTRY_USER — your Forgejo username (bvandeusen) # REGISTRY_TOKEN — Forgejo personal access token with write:packages scope # DEPLOY_HOST — IP or hostname of the server running fabledassistant # DEPLOY_USER — SSH user on that server # DEPLOY_SSH_KEY — private SSH key (matching public key must be in authorized_keys on app host) # DEPLOY_PATH — absolute path to the directory with docker-compose.yml on the app host name: Build & Deploy on: push: branches: [main] env: REGISTRY: git.fabledsword.com IMAGE: git.fabledsword.com/bvandeusen/fabledassistant jobs: build: name: Build & push image runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to Forgejo registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ secrets.REGISTRY_USER }} password: ${{ secrets.REGISTRY_TOKEN }} - name: Build and push uses: docker/build-push-action@v6 with: context: . push: true tags: | ${{ env.IMAGE }}:latest ${{ env.IMAGE }}:${{ github.sha }} # Registry-side layer cache lives in the Forgejo container registry. # Unchanged layers (npm install, pip install) are reused across builds, # cutting typical build time from ~4 min to ~45 sec after the first run. cache-from: type=registry,ref=${{ env.IMAGE }}:cache cache-to: type=registry,ref=${{ env.IMAGE }}:cache,mode=max deploy: name: Deploy needs: build runs-on: ubuntu-latest steps: - name: Pull new image and restart app uses: appleboy/ssh-action@v1 with: host: ${{ secrets.DEPLOY_HOST }} username: ${{ secrets.DEPLOY_USER }} key: ${{ secrets.DEPLOY_SSH_KEY }} # Pulls only the app service image, restarts only the app container. # Database and Ollama containers are left untouched (--no-deps). script: | set -e echo "${{ secrets.REGISTRY_TOKEN }}" | \ docker login git.fabledsword.com -u "${{ secrets.REGISTRY_USER }}" --password-stdin cd "${{ secrets.DEPLOY_PATH }}" docker compose pull app docker compose up -d --no-build --no-deps app docker image prune -f