name: Deploy Finance FaaS

on:
  push:
    branches:
      - master
  workflow_dispatch:
    inputs:
      deploy_note:
        description: Optional note for the deployment log
        required: false
        type: string
      deploy_profile:
        description: Deployment profile for this manual run
        required: false
        default: fast_dev
        type: choice
        options:
          - fast_dev
      force_deploy_now:
        description: Bypass the configured SAST deploy window for this run
        required: false
        default: false
        type: boolean

permissions:
  contents: read

concurrency:
  group: deploy-finance-faas-prod
  cancel-in-progress: false

env:
  FINANCE_FAAS_DEPLOY_ROOT: ${{ vars.FINANCE_FAAS_DEPLOY_ROOT }}
  FINANCE_FAAS_RELEASE_STATE_ROOT: ${{ vars.FINANCE_FAAS_RELEASE_STATE_ROOT }}
  FINANCE_FAAS_ENV_FILE: ${{ vars.FINANCE_FAAS_ENV_FILE }}
  FINANCE_FAAS_DEPLOY_WINDOW_TIMEZONE: ${{ vars.FINANCE_FAAS_DEPLOY_WINDOW_TIMEZONE }}
  FINANCE_FAAS_DEPLOY_WINDOW_DAYS: ${{ vars.FINANCE_FAAS_DEPLOY_WINDOW_DAYS }}
  FINANCE_FAAS_DEPLOY_WINDOW_START: ${{ vars.FINANCE_FAAS_DEPLOY_WINDOW_START }}
  FINANCE_FAAS_DEPLOY_WINDOW_END: ${{ vars.FINANCE_FAAS_DEPLOY_WINDOW_END }}
  FINANCE_FAAS_DEPLOY_WINDOW_MAX_WAIT_MINUTES: ${{ vars.FINANCE_FAAS_DEPLOY_WINDOW_MAX_WAIT_MINUTES }}
  FINANCE_FAAS_DEPLOY_WINDOW_POLL_SECONDS: ${{ vars.FINANCE_FAAS_DEPLOY_WINDOW_POLL_SECONDS }}
  FINANCE_FAAS_DRAIN_TIMEOUT_SECONDS: ${{ vars.FINANCE_FAAS_DRAIN_TIMEOUT_SECONDS }}
  FINANCE_FAAS_DRAIN_INTERVAL_SECONDS: ${{ vars.FINANCE_FAAS_DRAIN_INTERVAL_SECONDS }}
  FINANCE_FAAS_MAX_ACTIVE_SESSIONS: ${{ vars.FINANCE_FAAS_MAX_ACTIVE_SESSIONS }}
  FINANCE_FAAS_ACTIVE_SESSION_GRACE_SECONDS: ${{ vars.FINANCE_FAAS_ACTIVE_SESSION_GRACE_SECONDS }}
  FINANCE_FAAS_CLOSE_ACTIVE_SESSIONS: ${{ vars.FINANCE_FAAS_CLOSE_ACTIVE_SESSIONS }}

jobs:
  announce_validating:
    runs-on:
      - self-hosted
      - linux
      - x64
      - finance-faas
    needs:
      - detect_scope
    if: ${{ needs.detect_scope.outputs.deploy_required == 'true' }}
    outputs:
      requested_at: ${{ steps.deployment_metadata.outputs.requested_at }}
    steps:
      - name: Capture deployment start metadata
        id: deployment_metadata
        shell: bash
        run: |
          set -euo pipefail
          echo "requested_at=$(date -u +"%Y-%m-%dT%H:%M:%SZ")" >> "${GITHUB_OUTPUT}"

      - name: Check out repository
        uses: actions/checkout@v6

      - name: Publish predeploy validating state
        continue-on-error: true
        shell: bash
        run: |
          set -euo pipefail
          python3 scripts/publish_deployment_state.py \
            --state validating \
            --requested-at "${{ steps.deployment_metadata.outputs.requested_at }}" \
            --workflow-run-id "${GITHUB_RUN_ID}" \
            --workflow-run-url "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" \
            --status-detail "Checking the next update now." \
            --maintenance-pending false \
            --read-only-allowed true \
            --block-new-logins false \
            --source workflow-validating

  detect_scope:
    runs-on: ubuntu-latest
    outputs:
      deploy_required: ${{ steps.scope.outputs.deploy_required }}
      frontend_changed: ${{ steps.scope.outputs.frontend_changed }}
      changed_files_count: ${{ steps.scope.outputs.changed_files_count }}
      deploy_relevant_files_count: ${{ steps.scope.outputs.deploy_relevant_files_count }}
      frontend_relevant_files_count: ${{ steps.scope.outputs.frontend_relevant_files_count }}
    steps:
      - name: Check out repository
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Detect deployment scope
        id: scope
        shell: bash
        run: |
          set -euo pipefail
          head_sha="${GITHUB_SHA}"
          before_sha="${{ github.event.before || '' }}"
          if [[ "${{ github.event_name }}" == "push" && -n "${before_sha}" && "${before_sha}" != "0000000000000000000000000000000000000000" ]]; then
            base_sha="${before_sha}"
          elif git rev-parse "${head_sha}^" >/dev/null 2>&1; then
            base_sha="$(git rev-parse "${head_sha}^")"
          else
            base_sha="${head_sha}"
          fi

          echo "Comparing ${base_sha}..${head_sha}"
          if [[ "${base_sha}" == "${head_sha}" ]]; then
            printf '' | python3 scripts/deploy_change_scope.py --github-output "${GITHUB_OUTPUT}"
          else
            git diff --name-only "${base_sha}" "${head_sha}" | python3 scripts/deploy_change_scope.py --github-output "${GITHUB_OUTPUT}"
          fi

      - name: Summarize scope
        shell: bash
        run: |
          set -euo pipefail
          echo "- Deploy required: ${{ steps.scope.outputs.deploy_required }}" >> "${GITHUB_STEP_SUMMARY}"
          echo "- Frontend changed: ${{ steps.scope.outputs.frontend_changed }}" >> "${GITHUB_STEP_SUMMARY}"
          echo "- Changed files: ${{ steps.scope.outputs.changed_files_count }}" >> "${GITHUB_STEP_SUMMARY}"
          echo "- Deploy-relevant files: ${{ steps.scope.outputs.deploy_relevant_files_count }}" >> "${GITHUB_STEP_SUMMARY}"
          echo "- Frontend-relevant files: ${{ steps.scope.outputs.frontend_relevant_files_count }}" >> "${GITHUB_STEP_SUMMARY}"

  validate:
    runs-on: ubuntu-latest
    needs:
      - detect_scope
    steps:
      - name: Check out repository
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Set up uv
        uses: astral-sh/setup-uv@v7

      - name: Set up Python 3.13
        uses: actions/setup-python@v6
        with:
          python-version: "3.13"

      - name: Set up Node
        uses: actions/setup-node@v6
        with:
          node-version-file: .nvmrc

      - name: Install root Node tools
        run: npm ci

      - name: Install markdownlint
        run: npm install -g markdownlint-cli@0.47.0

      - name: Expose local Node bins
        shell: bash
        run: |
          set -euo pipefail
          echo "${GITHUB_WORKSPACE}/node_modules/.bin" >> "${GITHUB_PATH}"
          echo "$(npm prefix -g)/bin" >> "${GITHUB_PATH}"

      - name: Install Python lint dependencies
        run: uv sync --group lint --locked

      - name: Lint
        run: uv run python scripts/lint.py

      - name: Focused tests
        run: >
          uv run
          --with pytest==8.3.4
          --with fastapi==0.115.14
          --with uvicorn==0.37.0
          --with pydantic==2.11.7
          --with starlette==0.46.0
          --with httpx==0.28.1
          python -m pytest
          scripts/tests
          services/automation-core/tests
          services/capetown-faas-core/tests
          services/database-abstraction-core/tests
          services/documentation-core/tests
          -q

      - name: Build documentation site
        run: npm run docs:build

      - name: Install portal dependencies
        if: ${{ needs.detect_scope.outputs.frontend_changed == 'true' }}
        run: npm --prefix apps/portal-web install

      - name: Build portal-web
        if: ${{ needs.detect_scope.outputs.frontend_changed == 'true' }}
        run: npm --prefix apps/portal-web run build

      - name: Skip portal-web build
        if: ${{ needs.detect_scope.outputs.frontend_changed != 'true' }}
        run: echo "No frontend-relevant changes detected; skipping portal-web build in validation."

      - name: Package source release
        shell: bash
        run: |
          set -euo pipefail
          git archive --format=tar HEAD | gzip -9 > "${RUNNER_TEMP}/finance-faas-release.tar.gz"

      - name: Upload release archive
        uses: actions/upload-artifact@v7
        with:
          name: finance-faas-release
          path: ${{ runner.temp }}/finance-faas-release.tar.gz
          if-no-files-found: error
          retention-days: 7

  announce_queued:
    runs-on:
      - self-hosted
      - linux
      - x64
      - finance-faas
    needs:
      - announce_validating
      - detect_scope
      - validate
    if: ${{ always() && needs.detect_scope.outputs.deploy_required == 'true' && needs.validate.result == 'success' }}
    steps:
      - name: Check out repository
        uses: actions/checkout@v6

      - name: Publish queued deployment state
        continue-on-error: true
        shell: bash
        run: |
          set -euo pipefail
          python3 scripts/publish_deployment_state.py \
            --state queued \
            --requested-at "${{ needs.announce_validating.outputs.requested_at }}" \
            --workflow-run-id "${GITHUB_RUN_ID}" \
            --workflow-run-url "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" \
            --status-detail "The next update is almost ready." \
            --maintenance-pending false \
            --read-only-allowed true \
            --block-new-logins false \
            --source workflow-queued

  clear_predeploy_state:
    runs-on:
      - self-hosted
      - linux
      - x64
      - finance-faas
    needs:
      - detect_scope
      - announce_validating
      - validate
    if: ${{ always() && needs.detect_scope.outputs.deploy_required == 'true' && needs.validate.result != 'success' }}
    steps:
      - name: Check out repository
        uses: actions/checkout@v6

      - name: Clear predeploy state after validation failure
        continue-on-error: true
        shell: bash
        run: |
          set -euo pipefail
          python3 scripts/publish_deployment_state.py \
            --state normal \
            --workflow-run-id "${GITHUB_RUN_ID}" \
            --workflow-run-url "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" \
            --maintenance-pending false \
            --read-only-allowed true \
            --block-new-logins false \
            --source workflow-validate-cleanup

  deploy:
    runs-on:
      - self-hosted
      - linux
      - x64
      - finance-faas
    needs:
      - announce_validating
      - detect_scope
      - validate
      - announce_queued
    if: ${{ always() && needs.detect_scope.outputs.deploy_required == 'true' && needs.validate.result == 'success' }}
    steps:
      - name: Check out repository
        uses: actions/checkout@v6

      - name: Download release archive
        uses: actions/download-artifact@v8
        with:
          name: finance-faas-release
          path: ${{ runner.temp }}

      - name: Validate deployment configuration
        shell: bash
        run: |
          set -euo pipefail
          echo "FINANCE_FAAS_DEPLOY_ROOT=${FINANCE_FAAS_DEPLOY_ROOT:-/srv/capetownmarket-faas}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_RELEASE_STATE_ROOT=${FINANCE_FAAS_RELEASE_STATE_ROOT:-/var/lib/capetownmarket-faas/deploy-state}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_ENV_FILE=${FINANCE_FAAS_ENV_FILE:-/etc/capetownmarket-faas/capetownmarket-faas.env}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_DEPLOY_WINDOW_TIMEZONE=${FINANCE_FAAS_DEPLOY_WINDOW_TIMEZONE:-Africa/Johannesburg}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_DEPLOY_WINDOW_DAYS=${FINANCE_FAAS_DEPLOY_WINDOW_DAYS:-}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_DEPLOY_WINDOW_START=${FINANCE_FAAS_DEPLOY_WINDOW_START:-}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_DEPLOY_WINDOW_END=${FINANCE_FAAS_DEPLOY_WINDOW_END:-}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_DEPLOY_WINDOW_MAX_WAIT_MINUTES=${FINANCE_FAAS_DEPLOY_WINDOW_MAX_WAIT_MINUTES:-0}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_DEPLOY_WINDOW_POLL_SECONDS=${FINANCE_FAAS_DEPLOY_WINDOW_POLL_SECONDS:-60}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_DRAIN_TIMEOUT_SECONDS=${FINANCE_FAAS_DRAIN_TIMEOUT_SECONDS:-300}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_DRAIN_INTERVAL_SECONDS=${FINANCE_FAAS_DRAIN_INTERVAL_SECONDS:-5}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_MAX_ACTIVE_SESSIONS=${FINANCE_FAAS_MAX_ACTIVE_SESSIONS:-0}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_ACTIVE_SESSION_GRACE_SECONDS=${FINANCE_FAAS_ACTIVE_SESSION_GRACE_SECONDS:-0}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_CLOSE_ACTIVE_SESSIONS=${FINANCE_FAAS_CLOSE_ACTIVE_SESSIONS:-false}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_DEPLOY_EVIDENCE_DIR=${RUNNER_TEMP}/finance-faas-deploy-evidence/${GITHUB_RUN_ID}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_FRONTEND_CHANGED=${{ needs.detect_scope.outputs.frontend_changed }}" >> "${GITHUB_ENV}"

      - name: Resolve deployment profile
        shell: bash
        run: |
          set -euo pipefail
          deploy_profile='fast_dev'
          deploy_window_override='true'

          effective_drain_timeout="${FINANCE_FAAS_DRAIN_TIMEOUT_SECONDS}"
          effective_drain_interval="${FINANCE_FAAS_DRAIN_INTERVAL_SECONDS}"
          effective_max_active_sessions="${FINANCE_FAAS_MAX_ACTIVE_SESSIONS}"
          effective_active_session_grace_seconds="${FINANCE_FAAS_ACTIVE_SESSION_GRACE_SECONDS}"
          effective_close_active_sessions="${FINANCE_FAAS_CLOSE_ACTIVE_SESSIONS}"
          deploy_profile_note='Fast development deploy timings are currently active for every deploy run: deploy-window waiting is bypassed and drain waiting is skipped.'

          if [[ "${deploy_profile}" == "fast_dev" ]]; then
            deploy_window_override='true'
            effective_drain_timeout='0'
            effective_drain_interval='1'
            effective_max_active_sessions='0'
            effective_active_session_grace_seconds='0'
            effective_close_active_sessions='false'
            deploy_profile_note='Fast development deploy profile active: deploy-window waiting is bypassed and drain waiting is skipped.'
          fi

          echo "FINANCE_FAAS_DEPLOY_PROFILE=${deploy_profile}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_DEPLOY_WINDOW_OVERRIDE=${deploy_window_override}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_EFFECTIVE_DRAIN_TIMEOUT_SECONDS=${effective_drain_timeout}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_EFFECTIVE_DRAIN_INTERVAL_SECONDS=${effective_drain_interval}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_EFFECTIVE_MAX_ACTIVE_SESSIONS=${effective_max_active_sessions}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_EFFECTIVE_ACTIVE_SESSION_GRACE_SECONDS=${effective_active_session_grace_seconds}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_EFFECTIVE_CLOSE_ACTIVE_SESSIONS=${effective_close_active_sessions}" >> "${GITHUB_ENV}"
          echo "FINANCE_FAAS_DEPLOY_PROFILE_NOTE=${deploy_profile_note}" >> "${GITHUB_ENV}"
          echo "- Deploy profile: ${deploy_profile}" >> "${GITHUB_STEP_SUMMARY}"
          echo "- Deploy profile note: ${deploy_profile_note}" >> "${GITHUB_STEP_SUMMARY}"

      - name: Prepare checked-in deploy script
        shell: bash
        run: |
          chmod +x scripts/deploy-finance-faas-server.sh
          chmod +x scripts/deploy_notify.py
          chmod +x scripts/release_note_from_git.py
          chmod +x scripts/deploy_window.py

      - name: Wait for allowed deploy window
        shell: bash
        run: |
          set -euo pipefail
          python3 scripts/deploy_window.py \
            --timezone "${FINANCE_FAAS_DEPLOY_WINDOW_TIMEZONE}" \
            --days "${FINANCE_FAAS_DEPLOY_WINDOW_DAYS}" \
            --start "${FINANCE_FAAS_DEPLOY_WINDOW_START}" \
            --end "${FINANCE_FAAS_DEPLOY_WINDOW_END}" \
            --max-wait-minutes "${FINANCE_FAAS_DEPLOY_WINDOW_MAX_WAIT_MINUTES}" \
            --poll-seconds "${FINANCE_FAAS_DEPLOY_WINDOW_POLL_SECONDS}" \
            --override "${FINANCE_FAAS_DEPLOY_WINDOW_OVERRIDE}" \
            --sleep-until-window

      - name: Run local deployment on finance-faas-server
        shell: bash
        run: |
          set -euo pipefail
          deploy_note="${{ github.event.inputs.deploy_note || '' }}"
          script_path="${GITHUB_WORKSPACE}/scripts/deploy-finance-faas-server.sh"
          artifact_path="${RUNNER_TEMP}/finance-faas-release.tar.gz"
          if [[ -z "${deploy_note}" ]]; then
            deploy_note="$(python3 scripts/release_note_from_git.py "${GITHUB_SHA}" | tr '\n' ' ' | sed 's/[[:space:]]\+/ /g' | sed 's/^ //; s/ $//')"
          fi
          if [[ -z "${deploy_note}" ]]; then
            deploy_note="github-${GITHUB_SHA}"
          fi
          deploy_cmd=(
            /bin/bash
            "${script_path}"
            --artifact "${artifact_path}"
            --repo-root "${FINANCE_FAAS_DEPLOY_ROOT}"
            --release-state-root "${FINANCE_FAAS_RELEASE_STATE_ROOT}"
            --evidence-dir "${FINANCE_FAAS_DEPLOY_EVIDENCE_DIR}"
            --env-file "${FINANCE_FAAS_ENV_FILE}"
            --requested-at "${{ needs.announce_validating.outputs.requested_at }}"
            --release-note "${deploy_note}"
            --requested-commit "${GITHUB_SHA}"
            --workflow-run-id "${GITHUB_RUN_ID}"
            --workflow-run-url "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}"
            --drain-timeout "${FINANCE_FAAS_EFFECTIVE_DRAIN_TIMEOUT_SECONDS}"
            --drain-interval "${FINANCE_FAAS_EFFECTIVE_DRAIN_INTERVAL_SECONDS}"
            --max-active-sessions "${FINANCE_FAAS_EFFECTIVE_MAX_ACTIVE_SESSIONS}"
            --active-session-grace-seconds "${FINANCE_FAAS_EFFECTIVE_ACTIVE_SESSION_GRACE_SECONDS}"
            --close-active-sessions "${FINANCE_FAAS_EFFECTIVE_CLOSE_ACTIVE_SESSIONS}"
          )
          if [[ "${FINANCE_FAAS_FRONTEND_CHANGED}" != "true" ]]; then
            deploy_cmd+=(--skip-portal-build)
          fi
          if [[ "$(id -u)" -eq 0 ]]; then
            "${deploy_cmd[@]}"
          else
            sudo -n "${deploy_cmd[@]}"
          fi

      - name: Publish deploy evidence summary
        if: always()
        shell: bash
        run: |
          set -euo pipefail
          summary_file="${FINANCE_FAAS_DEPLOY_EVIDENCE_DIR}/summary.md"
          if [[ -f "${summary_file}" ]]; then
            cat "${summary_file}" >> "${GITHUB_STEP_SUMMARY}"
          else
            echo "No deploy summary generated at ${summary_file}" >> "${GITHUB_STEP_SUMMARY}"
          fi

      - name: Upload deploy evidence
        if: always()
        uses: actions/upload-artifact@v7
        with:
          name: finance-faas-deploy-evidence-${{ github.run_id }}
          path: ${{ runner.temp }}/finance-faas-deploy-evidence/${{ github.run_id }}
          if-no-files-found: warn
          retention-days: 14

      - name: Send deploy failure notification
        if: failure()
        continue-on-error: true
        shell: bash
        env:
          FINANCE_FAAS_NOTIFY_WEBHOOK_URL: ${{ secrets.FINANCE_FAAS_NOTIFY_WEBHOOK_URL }}
          FINANCE_FAAS_NOTIFY_WEBHOOK_BEARER_TOKEN: ${{ secrets.FINANCE_FAAS_NOTIFY_WEBHOOK_BEARER_TOKEN }}
          FINANCE_FAAS_NOTIFY_EMAIL_TO: ${{ vars.FINANCE_FAAS_NOTIFY_EMAIL_TO }}
          FINANCE_FAAS_NOTIFY_EMAIL_FROM: ${{ vars.FINANCE_FAAS_NOTIFY_EMAIL_FROM }}
          FINANCE_FAAS_NOTIFY_SUBJECT_PREFIX: ${{ vars.FINANCE_FAAS_NOTIFY_SUBJECT_PREFIX }}
          FINANCE_FAAS_NOTIFY_SMTP_HOST: ${{ vars.FINANCE_FAAS_NOTIFY_SMTP_HOST }}
          FINANCE_FAAS_NOTIFY_SMTP_PORT: ${{ vars.FINANCE_FAAS_NOTIFY_SMTP_PORT }}
          FINANCE_FAAS_NOTIFY_SMTP_USERNAME: ${{ secrets.FINANCE_FAAS_NOTIFY_SMTP_USERNAME }}
          FINANCE_FAAS_NOTIFY_SMTP_PASSWORD: ${{ secrets.FINANCE_FAAS_NOTIFY_SMTP_PASSWORD }}
          FINANCE_FAAS_NOTIFY_SMTP_STARTTLS: ${{ vars.FINANCE_FAAS_NOTIFY_SMTP_STARTTLS }}
          FINANCE_FAAS_NOTIFY_SMTP_SSL: ${{ vars.FINANCE_FAAS_NOTIFY_SMTP_SSL }}
          FINANCE_FAAS_NOTIFY_TIMEOUT_SECONDS: ${{ vars.FINANCE_FAAS_NOTIFY_TIMEOUT_SECONDS }}
        run: |
          set -euo pipefail
          python3 scripts/deploy_notify.py \
            --environment-name "finance-faas-server" \
            --repository "${{ github.repository }}" \
            --run-id "${{ github.run_id }}" \
            --run-url "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
            --sha "${{ github.sha }}" \
            --artifact-name "finance-faas-deploy-evidence-${GITHUB_RUN_ID}" \
            --summary-file "${FINANCE_FAAS_DEPLOY_EVIDENCE_DIR}/summary.md" \
            --metadata-file "${FINANCE_FAAS_DEPLOY_EVIDENCE_DIR}/metadata.json" \
            --status "failure"

  clear_cancelled_predeploy_state:
    runs-on:
      - self-hosted
      - linux
      - x64
      - finance-faas
    needs:
      - detect_scope
      - announce_validating
      - validate
      - announce_queued
      - deploy
    if: ${{ always() && needs.detect_scope.outputs.deploy_required == 'true' && (needs.announce_validating.result == 'cancelled' || needs.validate.result == 'cancelled' || needs.announce_queued.result == 'cancelled' || needs.deploy.result == 'cancelled') }}
    steps:
      - name: Check out repository
        uses: actions/checkout@v6

      - name: Clear predeploy state after cancellation
        continue-on-error: true
        shell: bash
        run: |
          set -euo pipefail
          python3 scripts/publish_deployment_state.py \
            --state normal \
            --workflow-run-id "${GITHUB_RUN_ID}" \
            --workflow-run-url "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" \
            --maintenance-pending false \
            --read-only-allowed true \
            --block-new-logins false \
            --source workflow-cancelled-cleanup
