name: authentik-ci-main

on:
  push:
    branches:
      - main
      - next
      - version-*
    paths-ignore:
      - website
  pull_request:
    branches:
      - main
      - version-*

env:
  POSTGRES_DB: authentik
  POSTGRES_USER: authentik
  POSTGRES_PASSWORD: "EK-5jnKfjrGRm<77"

jobs:
  lint:
    strategy:
      fail-fast: false
      matrix:
        job:
          - bandit
          - black
          - codespell
          - isort
          - pending-migrations
          - pylint
          - pyright
          - ruff
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup authentik env
        uses: ./.github/actions/setup
      - name: run job
        run: poetry run make ci-${{ matrix.job }}
  test-migrations:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup authentik env
        uses: ./.github/actions/setup
      - name: run migrations
        run: poetry run python -m lifecycle.migrate
  test-migrations-from-stable:
    name: test-migrations-from-stable - PostgreSQL ${{ matrix.psql }}
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        psql:
          - 12-alpine
          - 15-alpine
          - 16-alpine
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - name: checkout stable
        run: |
          # Delete all poetry envs
          rm -rf /home/runner/.cache/pypoetry
          # Copy current, latest config to local
          cp authentik/lib/default.yml local.env.yml
          cp -R .github ..
          cp -R scripts ..
          git checkout version/$(python -c "from authentik import __version__; print(__version__)")
          rm -rf .github/ scripts/
          mv ../.github ../scripts .
      - name: Setup authentik env (stable)
        uses: ./.github/actions/setup
        with:
          postgresql_version: ${{ matrix.psql }}
      - name: run migrations to stable
        run: poetry run python -m lifecycle.migrate
      - name: checkout current code
        run: |
          set -x
          git fetch
          git reset --hard HEAD
          git clean -d -fx .
          git checkout $GITHUB_SHA
          # Delete previous poetry env
          rm -rf /home/runner/.cache/pypoetry/virtualenvs/*
      - name: Setup authentik env (ensure latest deps are installed)
        uses: ./.github/actions/setup
        with:
          postgresql_version: ${{ matrix.psql }}
      - name: migrate to latest
        run: |
          poetry run python -m lifecycle.migrate
      - name: run tests
        env:
          # Test in the main database that we just migrated from the previous stable version
          AUTHENTIK_POSTGRESQL__TEST__NAME: authentik
        run: |
          poetry run make test
  test-unittest:
    name: test-unittest - PostgreSQL ${{ matrix.psql }}
    runs-on: ubuntu-latest
    timeout-minutes: 30
    strategy:
      fail-fast: false
      matrix:
        psql:
          - 12-alpine
          - 15-alpine
          - 16-alpine
    steps:
      - uses: actions/checkout@v4
      - name: Setup authentik env
        uses: ./.github/actions/setup
        with:
          postgresql_version: ${{ matrix.psql }}
      - name: run unittest
        run: |
          poetry run make test
          poetry run coverage xml
      - if: ${{ always() }}
        uses: codecov/codecov-action@v3
        with:
          flags: unit
  test-integration:
    runs-on: ubuntu-latest
    timeout-minutes: 30
    steps:
      - uses: actions/checkout@v4
      - name: Setup authentik env
        uses: ./.github/actions/setup
      - name: Create k8s Kind Cluster
        uses: helm/kind-action@v1.8.0
      - name: run integration
        run: |
          poetry run coverage run manage.py test tests/integration
          poetry run coverage xml
      - if: ${{ always() }}
        uses: codecov/codecov-action@v3
        with:
          flags: integration
  test-e2e:
    name: test-e2e (${{ matrix.job.name }})
    runs-on: ubuntu-latest
    timeout-minutes: 30
    strategy:
      fail-fast: false
      matrix:
        job:
          - name: proxy
            glob: tests/e2e/test_provider_proxy*
          - name: oauth
            glob: tests/e2e/test_provider_oauth2* tests/e2e/test_source_oauth*
          - name: oauth-oidc
            glob: tests/e2e/test_provider_oidc*
          - name: saml
            glob: tests/e2e/test_provider_saml* tests/e2e/test_source_saml*
          - name: ldap
            glob: tests/e2e/test_provider_ldap* tests/e2e/test_source_ldap*
          - name: radius
            glob: tests/e2e/test_provider_radius*
          - name: flows
            glob: tests/e2e/test_flows*
    steps:
      - uses: actions/checkout@v4
      - name: Setup authentik env
        uses: ./.github/actions/setup
      - name: Setup e2e env (chrome, etc)
        run: |
          docker-compose -f tests/e2e/docker-compose.yml up -d
      - id: cache-web
        uses: actions/cache@v3
        with:
          path: web/dist
          key: ${{ runner.os }}-web-${{ hashFiles('web/package-lock.json', 'web/src/**') }}
      - name: prepare web ui
        if: steps.cache-web.outputs.cache-hit != 'true'
        working-directory: web
        run: |
          npm ci
          make -C .. gen-client-ts
          npm run build
      - name: run e2e
        run: |
          poetry run coverage run manage.py test ${{ matrix.job.glob }}
          poetry run coverage xml
      - if: ${{ always() }}
        uses: codecov/codecov-action@v3
        with:
          flags: e2e
  ci-core-mark:
    needs:
      - lint
      - test-migrations
      - test-migrations-from-stable
      - test-unittest
      - test-integration
      - test-e2e
    runs-on: ubuntu-latest
    steps:
      - run: echo mark
  build:
    needs: ci-core-mark
    runs-on: ubuntu-latest
    permissions:
      # Needed to upload contianer images to ghcr.io
      packages: write
    timeout-minutes: 120
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.sha }}
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3.0.0
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: prepare variables
        uses: ./.github/actions/docker-push-variables
        id: ev
        env:
          DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
      - name: Login to Container Registry
        uses: docker/login-action@v3
        if: ${{ steps.ev.outputs.shouldBuild == 'true' }}
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: generate ts client
        run: make gen-client-ts
      - name: Build Docker Image
        uses: docker/build-push-action@v5
        with:
          context: .
          secrets: |
            GEOIPUPDATE_ACCOUNT_ID=${{ secrets.GEOIPUPDATE_ACCOUNT_ID }}
            GEOIPUPDATE_LICENSE_KEY=${{ secrets.GEOIPUPDATE_LICENSE_KEY }}
          push: ${{ steps.ev.outputs.shouldBuild == 'true' }}
          tags: |
            ghcr.io/goauthentik/dev-server:gh-${{ steps.ev.outputs.branchNameContainer }}
            ghcr.io/goauthentik/dev-server:gh-${{ steps.ev.outputs.sha }}
            ghcr.io/goauthentik/dev-server:gh-${{ steps.ev.outputs.branchNameContainer }}-${{ steps.ev.outputs.timestamp }}-${{ steps.ev.outputs.shortHash }}
          build-args: |
            GIT_BUILD_HASH=${{ steps.ev.outputs.sha }}
            VERSION=${{ steps.ev.outputs.version }}
            VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
      - name: Comment on PR
        if: github.event_name == 'pull_request'
        continue-on-error: true
        uses: ./.github/actions/comment-pr-instructions
        with:
          tag: gh-${{ steps.ev.outputs.branchNameContainer }}-${{ steps.ev.outputs.timestamp }}-${{ steps.ev.outputs.shortHash }}
  build-arm64:
    needs: ci-core-mark
    runs-on: ubuntu-latest
    permissions:
      # Needed to upload contianer images to ghcr.io
      packages: write
    timeout-minutes: 120
    steps:
      - uses: actions/checkout@v4
        with:
          ref: ${{ github.event.pull_request.head.sha }}
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3.0.0
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: prepare variables
        uses: ./.github/actions/docker-push-variables
        id: ev
        env:
          DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
      - name: Login to Container Registry
        uses: docker/login-action@v3
        if: ${{ steps.ev.outputs.shouldBuild == 'true' }}
        with:
          registry: ghcr.io
          username: ${{ github.repository_owner }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: generate ts client
        run: make gen-client-ts
      - name: Build Docker Image
        uses: docker/build-push-action@v5
        with:
          context: .
          secrets: |
            GEOIPUPDATE_ACCOUNT_ID=${{ secrets.GEOIPUPDATE_ACCOUNT_ID }}
            GEOIPUPDATE_LICENSE_KEY=${{ secrets.GEOIPUPDATE_LICENSE_KEY }}
          push: ${{ steps.ev.outputs.shouldBuild == 'true' }}
          tags: |
            ghcr.io/goauthentik/dev-server:gh-${{ steps.ev.outputs.branchNameContainer }}-arm64
            ghcr.io/goauthentik/dev-server:gh-${{ steps.ev.outputs.sha }}-arm64
            ghcr.io/goauthentik/dev-server:gh-${{ steps.ev.outputs.branchNameContainer }}-${{ steps.ev.outputs.timestamp }}-${{ steps.ev.outputs.shortHash }}-arm64
          build-args: |
            GIT_BUILD_HASH=${{ steps.ev.outputs.sha }}
            VERSION=${{ steps.ev.outputs.version }}
            VERSION_FAMILY=${{ steps.ev.outputs.versionFamily }}
          platforms: linux/arm64
          cache-from: type=gha
          cache-to: type=gha,mode=max