name: deploy on: workflow_run: workflows: [ci] branches: [main] types: [completed] workflow_dispatch: inputs: deploy_ref: description: "Commit already checked by successful main CI (main or SHA)" default: main required: true deploy_mode: description: "First deploy requires full; plan changes no production resources" type: choice options: [changed, full, plan] default: changed refresh_images: description: "Explicitly refresh mutable third-party Compose tags" type: boolean default: false permissions: contents: read actions: read concurrency: group: deploy-main cancel-in-progress: false env: DEPLOY_HOST: ${{ vars.DEPLOY_HOST || secrets.DEPLOY_HOST }} DEPLOY_PORT: ${{ vars.DEPLOY_PORT || secrets.DEPLOY_PORT }} DEPLOY_USER: ${{ vars.DEPLOY_USER || secrets.DEPLOY_USER }} DEPLOY_KEY: ${{ secrets.DEPLOY_SSH_KEY }} DEPLOY_KNOWN_HOSTS: ${{ vars.DEPLOY_KNOWN_HOSTS }} DEPLOY_RUN_ID: ${{ github.run_id }}-${{ github.run_attempt || 1 }} DEPLOY_MODE: ${{ inputs.deploy_mode || 'changed' }} REFRESH_IMAGES: ${{ inputs.refresh_images && 'true' || 'false' }} jobs: gate: if: >- github.ref == 'refs/heads/main' && (vars.AUTODEPLOY == 'true' || github.event_name == 'workflow_dispatch') && (github.event_name != 'workflow_run' || (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_branch == 'main')) runs-on: homelab timeout-minutes: 10 outputs: sha: ${{ steps.release.outputs.sha }} steps: - name: Checkout repository uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: fetch-depth: 0 - name: Check successful CI and download the exact commit release id: release env: GITEA_TOKEN: ${{ github.token }} DEPLOY_REF: ${{ inputs.deploy_ref || 'main' }} EVENT_SHA: ${{ github.event.workflow_run.head_sha }} run: python3 .gitea/workflows/release.py gate --ref "$DEPLOY_REF" --event-sha "$EVENT_SHA" - name: Submit durable deploy to workstation run: bash .gitea/workflows/ssh-run.sh start apply: needs: [gate] runs-on: homelab timeout-minutes: 100 steps: - name: Checkout checked commit uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: ref: ${{ needs.gate.outputs.sha }} - name: Follow validation and sequential Kubernetes / Compose apply run: bash .gitea/workflows/ssh-run.sh apply verify: needs: [gate, apply] if: always() && needs.gate.result == 'success' runs-on: homelab timeout-minutes: 130 steps: - name: Checkout checked commit uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: ref: ${{ needs.gate.outputs.sha }} - name: Follow workload verification and recovery run: bash .gitea/workflows/ssh-run.sh verify smoke: needs: [gate, verify] if: always() && needs.gate.result == 'success' runs-on: homelab timeout-minutes: 15 steps: - name: Checkout checked commit uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 with: ref: ${{ needs.gate.outputs.sha }} - name: Follow public route checks run: bash .gitea/workflows/ssh-run.sh smoke