name: Deploy on: push: branches: [main] tags: ["v*"] # Required repository secrets: # REGISTRY registry hostname, e.g. registry.librete.ch # REGISTRY_USER robot account # REGISTRY_PASS robot token # DEPLOY_HOST deployment SSH target, e.g. root@librenot.es # DEPLOY_KEY private SSH key (PEM, no passphrase) # DEPLOY_PATH remote directory containing the compose stack # HEALTH_URL public URL to verify post-deploy, e.g. # https://librenot.es/healthz # # Tag pushes deploy the tag (vX.Y.Z); main-branch pushes deploy # the rolling :main image. Set image to immutable tag so rollback # is just `docker compose -f ... up -d` with the previous tag. jobs: build: runs-on: ubuntu-latest timeout-minutes: 15 if: ${{ vars.DEPLOY_ENABLED == 'true' }} steps: - uses: actions/checkout@v4 - uses: docker/setup-buildx-action@v3 - name: Log in to registry uses: docker/login-action@v3 with: registry: ${{ secrets.REGISTRY }} username: ${{ secrets.REGISTRY_USER }} password: ${{ secrets.REGISTRY_PASS }} - name: Compute tags id: tags run: | BASE="${{ secrets.REGISTRY }}/librenotes" if [[ "${GITHUB_REF}" == refs/tags/* ]]; then TAG="${GITHUB_REF##refs/tags/}" echo "tags=${BASE}:${TAG},${BASE}:latest" >> "$GITHUB_OUTPUT" echo "version=${TAG}" >> "$GITHUB_OUTPUT" else echo "tags=${BASE}:main,${BASE}:${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT" echo "version=${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT" fi - uses: docker/build-push-action@v6 with: context: . push: true tags: ${{ steps.tags.outputs.tags }} build-args: | VERSION=${{ steps.tags.outputs.version }} BUILDTIME=${{ github.event.head_commit.timestamp }} deploy: runs-on: ubuntu-latest needs: build timeout-minutes: 10 if: ${{ vars.DEPLOY_ENABLED == 'true' }} steps: - name: Configure SSH run: | mkdir -p ~/.ssh echo "${{ secrets.DEPLOY_KEY }}" > ~/.ssh/id_deploy chmod 600 ~/.ssh/id_deploy ssh-keyscan -H "${{ secrets.DEPLOY_HOST#*@ }}" >> ~/.ssh/known_hosts || true - name: Pull and restart on deploy host env: DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} DEPLOY_PATH: ${{ secrets.DEPLOY_PATH }} run: | ssh -i ~/.ssh/id_deploy "$DEPLOY_HOST" \ "cd $DEPLOY_PATH && \ docker compose -f docker-compose.yml -f docker-compose.prod.yml pull && \ docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --remove-orphans" - name: Verify health env: HEALTH_URL: ${{ secrets.HEALTH_URL }} run: | # Give the new container ~30s to come up, then poll for # a 200 from /healthz. Failure aborts the workflow which # is the alert. for i in $(seq 1 12); do if curl -fsS "$HEALTH_URL" >/dev/null; then echo "deploy verified" exit 0 fi sleep 5 done echo "deploy verification failed" exit 1