name: Pipeline

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]
  workflow_dispatch:
    inputs:
      target_host:
        description: Ansible host or alias
        required: false
        default: "jp-xhttp-contabo.svc.plus"
        type: string
      run_apply:
        description: Apply deployment
        required: true
        default: true
        type: boolean
      internal_service_token:
        description: Optional ACP auth token
        required: false
        default: ""
        type: string

permissions:
  contents: read
  packages: write
  id-token: write

concurrency:
  group: pipeline-${{ github.ref }}
  cancel-in-progress: true

defaults:
  run:
    shell: bash

env:
  DEFAULT_TARGET_HOST: jp-xhttp-contabo.svc.plus

jobs:
  prep:
    name: Prep
    runs-on: ubuntu-latest
    outputs:
      target_host: ${{ steps.flags.outputs.target_host }}
      run_apply: ${{ steps.flags.outputs.run_apply }}
      image_tag: ${{ steps.flags.outputs.image_tag }}
      push_image: ${{ steps.flags.outputs.push_image }}
      push_latest: ${{ steps.flags.outputs.push_latest }}
    steps:
      - name: Check Out Repository
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          fetch-depth: 0

      - name: Resolve Pipeline Flags
        id: flags
        env:
          IMAGE_REPO_OWNER: ${{ vars.IMAGE_REPO_OWNER || github.repository_owner }}
          DEFAULT_TARGET_HOST: ${{ env.DEFAULT_TARGET_HOST }}
          INPUT_TARGET_HOST: ${{ inputs.target_host }}
          INPUT_RUN_APPLY: ${{ inputs.run_apply }}
          INPUT_IMAGE_TAG: ${{ inputs.image_tag }}
          INPUT_PUSH_IMAGE: ${{ inputs.push_image }}
          INPUT_PUSH_LATEST: ${{ inputs.push_latest }}
          PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
          PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
          GITHUB_BEFORE: ${{ github.event.before }}
          GITHUB_SHA: ${{ github.sha }}
        run: bash ./scripts/github-actions/resolve-pipeline-flags.sh >> "$GITHUB_OUTPUT"

  build:
    name: Build
    needs: prep
    runs-on: ubuntu-latest
    env:
      SERVICE_REGISTRY: ghcr.io
      SERVICE_IMAGE_REPO_OWNER: ${{ vars.IMAGE_REPO_OWNER || github.repository_owner }}
      SERVICE_IMAGE_NAME: accounts
    outputs:
      service_image_repo: ${{ steps.service_image.outputs.repo }}
      service_preferred_tag: ${{ steps.service_preferred.outputs.tag }}
    steps:
      - name: Check Out Repository
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

      - name: Set Up QEMU
        uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3.6.0

      - name: Set Up Docker Buildx
        uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3.11.1

      - name: Log In To GHCR
        if: needs.prep.outputs.push_image == 'true'
        uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
        with:
          registry: ghcr.io
          username: ${{ vars.GHCR_USERNAME || github.repository_owner }}
          password: ${{ secrets.GHCR_TOKEN || github.token }}

      - name: Resolve Service Image Repository
        id: service_image
        run: echo "repo=${SERVICE_REGISTRY}/${SERVICE_IMAGE_REPO_OWNER}/${SERVICE_IMAGE_NAME}" >> "$GITHUB_OUTPUT"

      - name: Compute Service Image Tags
        id: service_meta
        uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
        with:
          images: ${{ steps.service_image.outputs.repo }}
          tags: |
            type=raw,value=${{ needs.prep.outputs.image_tag }},enable=${{ needs.prep.outputs.image_tag != '' }}
            type=sha,format=short,enable=${{ needs.prep.outputs.image_tag == '' }}
            type=raw,value=latest,enable=${{ needs.prep.outputs.push_latest == 'true' || github.ref == 'refs/heads/main' }}

      - name: Resolve Service Preferred Tag
        id: service_preferred
        run: |
          set -euo pipefail
          tag="$(bash .github/scripts/utils/preferred-tag.sh "${{ steps.service_meta.outputs.tags }}")"
          echo "tag=${tag}" >> "$GITHUB_OUTPUT"

      - name: Build And Push Service Image
        uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0
        with:
          context: .
          file: Dockerfile
          platforms: linux/amd64
          push: ${{ needs.prep.outputs.push_image == 'true' }}
          tags: ${{ steps.service_meta.outputs.tags }}
          labels: ${{ steps.service_meta.outputs.labels }}

  deploy:
    name: Deploy
    needs:
      - prep
      - build
    if: ${{ needs.prep.outputs.push_image == 'true' }}
    runs-on: ubuntu-latest
    outputs:
      image: ${{ needs.build.outputs.service_image_repo }}
      preferred_tag: ${{ needs.build.outputs.service_preferred_tag }}
      run_apply: ${{ needs.prep.outputs.run_apply }}
      pushed: "true"
    steps:
      - name: Check Out Repository
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

      - name: Check Out Playbooks Repository
        # Pull latest playbooks HEAD from the default branch.
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
        with:
          repository: x-evor/playbooks
          token: ${{ secrets.WORKSPACE_REPO_TOKEN || github.token }}
          path: playbooks

      - name: Resolve Deploy Image Tag
        id: deploy_image_tag
        run: |
          set -euo pipefail
          tag="${{ needs.build.outputs.service_preferred_tag }}"
          echo "value=${tag##*:}" >> "$GITHUB_OUTPUT"

      - name: Set Up Python
        uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.0.0
        with:
          python-version: "3.11"

      - name: Install Ansible Runtime
        run: |
          python -m pip install --upgrade pip
          python -m pip install "ansible-core==2.18.3"

      - name: Prepare Runner SSH Access
        env:
          SINGLE_NODE_VPS_SSH_PRIVATE_KEY: ${{ secrets.SINGLE_NODE_VPS_SSH_PRIVATE_KEY }}
          SSH_KNOWN_HOSTS: ${{ secrets.SSH_KNOWN_HOSTS }}
        run: |
          bash ./scripts/github-actions/prepare-ssh.sh \
            "${{ needs.prep.outputs.target_host }}" \
            "${SSH_KNOWN_HOSTS}"

      - name: Run Accounts Deploy Playbook
        working-directory: ${{ github.workspace }}/playbooks
        env:
          ACCOUNTS_IMAGE_REPO: ${{ needs.build.outputs.service_image_repo }}
          ACCOUNTS_IMAGE_TAG: ${{ steps.deploy_image_tag.outputs.value }}
          ACCOUNTS_PULL_IMAGE: "true"
        run: |
          set -euo pipefail

          args=(
            ansible-playbook
            -i inventory.ini
            deploy_accounts_svc_plus.yml
            -l "${{ needs.prep.outputs.target_host }}"
          )

          if [[ "${{ needs.prep.outputs.run_apply }}" != "true" ]]; then
            args+=(-C)
          fi

          ANSIBLE_CONFIG="${PWD}/ansible.cfg" \
          ACCOUNTS_PULL_IMAGE="${ACCOUNTS_PULL_IMAGE:-true}" \
          "${args[@]}"


  validate:
    name: Validate
    needs:
      - deploy
    if: ${{ always() && needs.deploy.result == 'success' && needs.deploy.outputs.pushed == 'true' && needs.deploy.outputs.run_apply == 'true' }}
    runs-on: ubuntu-latest
    steps:
      - name: Check Out Repository
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

      - name: Validate Deployed Accounts Service
        run: bash ./scripts/github-actions/validate-deploy.sh https://accounts.svc.plus
