name: CI

on:
  push:
    branches:
      - main
    tags:
      - '*'
  pull_request: ~
  workflow_dispatch: ~

concurrency:
  group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
  cancel-in-progress: true

permissions:
  contents: read
  packages: write

jobs:
  tests:
    name: Tests
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Lint Dockerfile
        uses: hadolint/hadolint-action@v3.1.0
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Build Docker images
        uses: docker/bake-action@v5
        with:
          pull: true
          load: true
          files: |
            compose.yaml
            compose.override.yaml
          set: |
            *.cache-from=type=gha,scope=${{github.ref}}
            *.cache-from=type=gha,scope=refs/heads/main
            *.cache-to=type=gha,scope=${{github.ref}},mode=max
      - name: Start services
        run: docker compose up php database --wait --no-build
      - name: Lint Twig templates
        run: docker compose exec -T php bin/console lint:twig --format=github templates
      - name: Coding Style
        run: docker compose exec -T php vendor/bin/php-cs-fixer check --diff --show-progress=none
      - name: Twig Coding Style
        run: docker compose exec -T php vendor/bin/twig-cs-fixer check
      - name: Check HTTP reachability
        run: curl -v --fail-with-body http://localhost
      - name: Check Mercure reachability
        if: false
        run: curl -vkI --fail-with-body https://localhost/.well-known/mercure?topic=test
      - name: Create test database
        run: docker compose exec -T php bin/console -e test doctrine:database:create
      - name: Run migrations
        run: docker compose exec -T php bin/console -e test doctrine:migrations:migrate --no-interaction
      - name: Load fixtures
        run: docker compose exec -T php bin/console -e test doctrine:fixtures:load --no-interaction --group=test
      - name: Run PHPUnit
        run: docker compose exec -T php vendor/bin/phpunit
      - name: Doctrine Schema Validator
        run: docker compose exec -T php bin/console -e test doctrine:schema:validate
  
  build-deploy:
    name: Build and deploy to ${{ startsWith(github.ref, 'refs/tags/') && 'production' || (github.ref == 'refs/heads/main' && 'acceptance' || '') }}
    environment:
      name: ${{ startsWith(github.ref, 'refs/tags/') && 'production' || (github.ref == 'refs/heads/main' && 'acceptance' || '') }}
      url: ${{ vars.URL }}
    needs: tests
    runs-on: ubuntu-latest
    if: (github.ref == 'refs/heads/main' && false) || startsWith(github.ref, 'refs/tags/')
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata
        id: meta
        run: |
          REPO_LOWER=$(echo "${{ github.repository }}" | tr '[:upper:]' '[:lower:]')
          if [[ "${{ github.ref }}" == refs/tags/* ]]; then
            TAG="${GITHUB_REF#refs/tags/}"
            {
              echo "tag=$TAG"
              echo "full_name=ghcr.io/${REPO_LOWER}:$TAG"
            } >> "$GITHUB_OUTPUT"
          else
            SHORT_SHA=$(git rev-parse --short HEAD)
            {
              echo "tag=$SHORT_SHA"
              echo "full_name=ghcr.io/${REPO_LOWER}:$SHORT_SHA"
            } >> "$GITHUB_OUTPUT"
          fi

      - name: Build and Push Docker images
        uses: docker/bake-action@v5
        with:
          pull: true
          push: true
          files: |
            compose.yaml
            compose.build.yaml
          set: |
            *.cache-from=type=gha,scope=${{github.ref}}
            *.cache-from=type=gha,scope=refs/heads/main
            *.cache-to=type=gha,scope=${{github.ref}},mode=max
            *.tags=${{ steps.meta.outputs.full_name }}

      - name: Trigger Portainer Deployment
        shell: bash
        env:
          PORTAINER_WEBHOOK: ${{secrets.PORTAINER_WEBHOOK}}
        run: |
          curl -v -X POST "$PORTAINER_WEBHOOK"?IMAGE_TAG=${{steps.meta.outputs.tag}} --fail-with-body
