name: Test

on:
  workflow_call:

jobs:
  mage:
    runs-on: ubuntu-latest
    name: prepare-mage
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
      - name: Set up Go
        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
        with:
          go-version: stable
      - name: Cache Mage
        id: cache-mage
        uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5
        with:
          key: ${{ runner.os }}-build-mage-${{ hashFiles('magefile.go') }}
          path: |
            ./mage-static
      - name: Compile Mage
        if: ${{ steps.cache-mage.outputs.cache-hit != 'true' }}
        uses: magefile/mage-action@6f50bbb8ea47d56e62dee92392788acbc8192d0b # v3
        with:
          version: latest
          args: -compile ./mage-static
      - name: Store Mage Binary
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
        with:
          name: mage_bin
          path: ./mage-static

  api-build:
    runs-on: ubuntu-latest
    needs: mage
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
      - name: Download Mage Binary
        uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
        with:
          name: mage_bin
      - name: Git describe
        id: ghd
        uses: proudust/gh-describe@v2
      - name: Set up Go
        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
        with:
          go-version: stable
      - name: Build
        env:
          RELEASE_VERSION: ${{ steps.ghd.outputs.describe }}
        run: |
          mkdir -p frontend/dist
          touch frontend/dist/index.html
          chmod +x ./mage-static
          ./mage-static build
      - name: Store Vikunja Binary
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
        with:
          name: vikunja_bin
          path: ./vikunja

  api-lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
      - uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
        with:
          go-version: stable
      - name: prepare frontend files
        run: |
          mkdir -p frontend/dist
          touch frontend/dist/index.html
      - name: golangci-lint
        uses: golangci/golangci-lint-action@1e7e51e771db61008b38414a730f564565cf7c20 # v9
        with:
          version: v2.9.0

  api-check-translations:
    runs-on: ubuntu-latest
    needs: mage
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
      - name: Download Mage Binary
        uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
        with:
          name: mage_bin
      - name: Check
        run: |
          chmod +x ./mage-static
          ./mage-static check:translations

  test-migration-smoke:
    runs-on: ubuntu-latest
    needs:
      - api-build
    strategy:
      matrix:
        db:
          - sqlite
          - postgres
          - mysql
    services:
      migration-smoke-db-mysql:
        image: mariadb:12@sha256:f54db0cb3ccfe9431aba6d08c65a1763c499789b116b4cb651dd7fcf325965b3
        env:
          MYSQL_ROOT_PASSWORD: vikunjatest
          MYSQL_DATABASE: vikunjatest
        ports:
          - 3306:3306
      migration-smoke-db-postgres:
        image: postgres:18@sha256:5773fe724c49c42a7a9ca70202e11e1dff21fb7235b335a73f39297d200b73a2
        env:
          POSTGRES_PASSWORD: vikunjatest
          POSTGRES_DB: vikunjatest
        ports:
          - 5432:5432
    steps:
      - name: Download Unstable
        run: |
          wget https://dl.vikunja.io/vikunja/unstable/vikunja-unstable-linux-amd64-full.zip -q -O vikunja-latest.zip
          unzip vikunja-latest.zip vikunja-unstable-linux-amd64
      - name: Download Vikunja Binary
        uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
        with:
          name: vikunja_bin
      - name: run migration
        env:
          VIKUNJA_DATABASE_TYPE: ${{ matrix.db }}
          VIKUNJA_DATABASE_PATH: ./vikunja-migration-test.db
          VIKUNJA_DATABASE_USER: ${{ matrix.db == 'postgres' && 'postgres' || 'root' }}
          VIKUNJA_DATABASE_PASSWORD: vikunjatest
          VIKUNJA_DATABASE_DATABASE: vikunjatest
          VIKUNJA_DATABASE_SSLMODE: disable
          VIKUNJA_LOG_DATABASE: stdout
          VIKUNJA_LOG_DATABASELEVEL: debug
          VIKUNJA_SERVICE_PUBLICURL: http://127.0.0.1:3456
        run: |
          # Wait for MySQL to be ready if using MySQL
          if [ "$VIKUNJA_DATABASE_TYPE" = "mysql" ]; then
            echo "Waiting for MySQL to be ready..."
            until mysql -h 127.0.0.1 -u root -pvikunjatest -e "SELECT 1" &> /dev/null; do
              echo "MySQL not ready yet, waiting 2 seconds..."
              sleep 2
            done
            echo "MySQL is ready!"
          fi

          # Wait for PostgreSQL to be ready if using PostgreSQL
          if [ "$VIKUNJA_DATABASE_TYPE" = "postgres" ]; then
            echo "Waiting for PostgreSQL to be ready..."
            until PGPASSWORD=vikunjatest psql -h 127.0.0.1 -U postgres -d vikunjatest -c "SELECT 1" &> /dev/null; do
              echo "PostgreSQL not ready yet, waiting 2 seconds..."
              sleep 2
            done
            echo "PostgreSQL is ready!"
          fi

          ./vikunja-unstable-linux-amd64 migrate
          # Run the migrations from the binary built in the step before
          chmod +x vikunja
          ./vikunja migrate

  test-api:
    runs-on: ubuntu-latest
    needs:
      - mage
    strategy:
      matrix:
        db:
          - sqlite-in-memory
          - sqlite
          - postgres
          - mysql
          - paradedb
        test:
          - feature
          - web
    services:
      db-mysql:
        image: ${{ matrix.db == 'mysql' && 'mariadb:12@sha256:5b6a1eac15b85b981a61afb89aea2a22bf76b5f58809d05f0bcc13ab6ec44cb8' || '' }}
        env:
          MYSQL_ROOT_PASSWORD: vikunjatest
          MYSQL_DATABASE: vikunjatest
        ports:
          - 3306:3306
      db-postgres:
        image: ${{ matrix.db == 'postgres' && 'postgres:18@sha256:073e7c8b84e2197f94c8083634640ab37105effe1bc853ca4d5fbece3219b0e8' || '' }}
        env:
          POSTGRES_PASSWORD: vikunjatest
          POSTGRES_DB: vikunjatest
        ports:
          - 5432:5432
      db-paradedb:
        image: ${{ matrix.db == 'paradedb' && 'paradedb/paradedb:latest-pg17@sha256:741010eaa8894d292203d9407d46fc95ee4d0cd587915513bf92e6bd70cbd65e' || '' }}
        env:
          POSTGRES_PASSWORD: vikunjatest
          POSTGRES_DB: vikunjatest
        ports:
          - 5433:5432
      test-ldap:
        image: gitea/test-openldap@sha256:b66527e298d6062d5289dc411d1b8da1c593f8140a3d1f863e8d9d021234122f
        ports:
          - 389:389
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
      - name: Download Mage Binary
        uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
        with:
          name: mage_bin
      - name: Set up Go
        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
        with:
          go-version: stable
      - name: Configure Postgres for faster tests
        if: matrix.db == 'postgres' || matrix.db == 'paradedb'
        run: |
          # Connect to Postgres and disable fsync, full_page_writes, and synchronous_commit for faster tests
          PGPASSWORD=vikunjatest psql -h localhost ${{ matrix.db == 'paradedb' && ' -p 5433' || '' }} -U postgres -d vikunjatest -c "ALTER SYSTEM SET fsync = off;"
          PGPASSWORD=vikunjatest psql -h localhost ${{ matrix.db == 'paradedb' && ' -p 5433' || '' }} -U postgres -d vikunjatest -c "ALTER SYSTEM SET full_page_writes = off;"
          PGPASSWORD=vikunjatest psql -h localhost ${{ matrix.db == 'paradedb' && ' -p 5433' || '' }} -U postgres -d vikunjatest -c "ALTER SYSTEM SET synchronous_commit = off;"
          # Reload the configuration
          PGPASSWORD=vikunjatest psql -h localhost ${{ matrix.db == 'paradedb' && ' -p 5433' || '' }} -U postgres -d vikunjatest -c "SELECT pg_reload_conf();"
      - name: test
        env:
          VIKUNJA_TESTS_USE_CONFIG: ${{ matrix.db != 'sqlite-in-memory' && 1 || 0 }}
          VIKUNJA_DATABASE_TYPE: ${{ matrix.db == 'paradedb' && 'postgres' || matrix.db }}
          VIKUNJA_DATABASE_USER: ${{ matrix.db == 'mysql' && 'root' || 'postgres' }}
          VIKUNJA_DATABASE_PASSWORD: vikunjatest
          VIKUNJA_DATABASE_DATABASE: vikunjatest
          VIKUNJA_DATABASE_SSLMODE: disable
          VIKUNJA_DATABASE_HOST: localhost${{ matrix.db == 'paradedb' && ':5433' || '' }}
          VIKUNJA_AUTH_LDAP_ENABLED: 1
          VIKUNJA_AUTH_LDAP_HOST: localhost
          VIKUNJA_AUTH_LDAP_USETLS: 0
          VIKUNJA_AUTH_LDAP_BASEDN: dc=planetexpress,dc=com
          VIKUNJA_AUTH_LDAP_BINDDN: uid=gitea,ou=service,dc=planetexpress,dc=com
          VIKUNJA_AUTH_LDAP_BINDPASSWORD: password
          VIKUNJA_AUTH_LDAP_USERFILTER: "(&(objectclass=inetorgperson)(uid=%s))"
          VIKUNJA_SERVICE_PUBLICURL: http://127.0.0.1:3456
        run: |
          mkdir -p frontend/dist
          touch frontend/dist/index.html
          chmod +x mage-static
          ./mage-static test:${{ matrix.test }}

  test-s3-integration:
    runs-on: ubuntu-latest
    needs:
      - mage
    services:
      test-minio:
        image: bitnamilegacy/minio:latest@sha256:451fe6858cb770cc9d0e77ba811ce287420f781c7c1b806a386f6896471a349c
        env:
          MINIO_ROOT_USER: vikunja
          MINIO_ROOT_PASSWORD: vikunjatest
          MINIO_DEFAULT_BUCKETS: vikunja-test
        ports:
          - 9000:9000
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
      - name: Download Mage Binary
        uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
        with:
          name: mage_bin
      - name: Set up Go
        uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
        with:
          go-version: stable
      - name: test S3 file storage integration
        env:
          VIKUNJA_TESTS_USE_CONFIG: 1
          VIKUNJA_DATABASE_TYPE: sqlite
          VIKUNJA_FILES_TYPE: s3
          VIKUNJA_FILES_S3_ENDPOINT: http://localhost:9000
          VIKUNJA_FILES_S3_BUCKET: vikunja-test
          VIKUNJA_FILES_S3_REGION: us-east-1
          VIKUNJA_FILES_S3_ACCESSKEY: vikunja
          VIKUNJA_FILES_S3_SECRETKEY: vikunjatest
          VIKUNJA_FILES_S3_USEPATHSTYLE: true
          VIKUNJA_SERVICE_PUBLICURL: http://127.0.0.1:3456
        run: |
          mkdir -p frontend/dist
          touch frontend/dist/index.html
          chmod +x mage-static
          # Run only the S3 file storage integration tests
          ./mage-static test:filter "TestFileStorageIntegration"

  frontend-lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
      - uses: ./.github/actions/setup-frontend
      - name: Lint
        working-directory: frontend
        run: pnpm lint

  frontend-stylelint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
      - uses: ./.github/actions/setup-frontend
      - name: Lint styles
        working-directory: frontend
        run: pnpm lint:styles

  frontend-typecheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
      - uses: ./.github/actions/setup-frontend
      - name: Typecheck
        continue-on-error: true
        working-directory: frontend
        run: pnpm typecheck

  test-frontend-unit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
      - uses: ./.github/actions/setup-frontend
      - name: Run unit tests
        working-directory: frontend
        run: pnpm test:unit

  frontend-build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
      - uses: ./.github/actions/setup-frontend
      - name: Git describe
        id: ghd
        uses: proudust/gh-describe@v2
      - name: Inject frontend version
        working-directory: frontend
        run: |
          echo "{\"VERSION\": \"${{ steps.ghd.outputs.describe }}\"}" > src/version.json
      - name: Build frontend
        working-directory: frontend
        run: pnpm build
      - name: Store Frontend
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
        with:
          name: frontend_dist
          path: ./frontend/dist

  test-frontend-e2e-playwright:
    runs-on: ubuntu-latest
    needs:
      - api-build
      - frontend-build
    strategy:
      fail-fast: false
      matrix:
        shard: [1, 2, 3, 4, 5, 6]
        total-shards: [6]
    services:
      dex:
        image: ghcr.io/go-vikunja/dex-testing:main@sha256:d401c06a9f8fd36ece446a07499b827232af7f21eb36872a76c9eac4d0c77bab
        ports:
          - 5556:5556
    container:
      image: mcr.microsoft.com/playwright:v1.58.2-jammy@sha256:4698a73749c5848d3f5fcd42a2174d172fcad2b2283e087843b115424303a565
      options: --user 1001
    steps:
      - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
      - name: Download Vikunja Binary
        uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
        with:
          name: vikunja_bin
      - uses: ./.github/actions/setup-frontend
        with:
          install-e2e-binaries: false # Playwright browsers already in container
      - name: Download Frontend
        uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7
        with:
          name: frontend_dist
          path: ./frontend/dist
      - name: Inject testing flag into index.html
        run: |
          sed -i 's/<head>/<head><script>window.TESTING=true;<\/script>/' ./frontend/dist/index.html
      - run: chmod +x ./vikunja
      - name: Run Playwright tests
        timeout-minutes: 20
        working-directory: frontend
        run: |
          pnpm run preview:vikunja &
          pnpm run preview &

          # Wait for services to be ready (using GET method)
          pnpx wait-on http-get://127.0.0.1:4173 http-get://127.0.0.1:3456/api/v1/info --timeout 60000

          pnpm run test:e2e --shard=${{ matrix.shard }}/${{ matrix.total-shards }}
        env:
          PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS: 1
          TEST_SECRET: averyLongSecretToSe33dtheDB
          VIKUNJA_SERVICE_TESTINGTOKEN: averyLongSecretToSe33dtheDB
          VIKUNJA_LOG_LEVEL: DEBUG
          VIKUNJA_CORS_ENABLE: 1
          VIKUNJA_SERVICE_PUBLICURL: http://127.0.0.1:3456
          VIKUNJA_DATABASE_PATH: memory
          VIKUNJA_DATABASE_TYPE: sqlite
          VIKUNJA_RATELIMIT_NOAUTHLIMIT: 1000
          VIKUNJA_AUTH_OPENID_ENABLED: 1
          VIKUNJA_AUTH_OPENID_PROVIDERS_DEX_NAME: Dex
          VIKUNJA_AUTH_OPENID_PROVIDERS_DEX_AUTHURL: http://dex:5556
          VIKUNJA_AUTH_OPENID_PROVIDERS_DEX_CLIENTID: vikunja
          VIKUNJA_AUTH_OPENID_PROVIDERS_DEX_CLIENTSECRET: secret
      - name: Upload Playwright Report
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
        if: always()
        with:
          name: playwright-report-${{ matrix.shard }}
          path: frontend/playwright-report/
          retention-days: 30
      - name: Upload Test Results
        uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
        if: always()
        with:
          name: playwright-test-results-${{ matrix.shard }}
          path: frontend/test-results/
          retention-days: 30
