name: Scheduled

on:
  schedule:
    - cron: '0 0 * * *'  # every day at midnight
  workflow_dispatch:

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

jobs:
  check_date: # https://stackoverflow.com/questions/63014786/how-to-schedule-a-github-actions-nightly-build-but-run-it-only-when-there-where
    runs-on: ubuntu-latest
    name: Check latest commit
    outputs:
      should_run: ${{ steps.should_run.outputs.should_run }}
    steps:
      - uses: actions/checkout@v4
      - name: print latest_commit
        run: echo ${{ github.sha }}

      - id: should_run
        continue-on-error: true
        name: check latest commit is less than a day
        if: ${{ github.event_name == 'schedule' }}
        run: test -z $(git rev-list  --after="24 hours"  ${{ github.sha }}) && echo "::set-output name=should_run::false"

  # run Sytest in different variations
  sytest:
    needs: check_date
    if: ${{ needs.check_date.outputs.should_run != 'false' }}
    timeout-minutes: 60
    name: "Sytest (${{ matrix.label }})"
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        include:
          - label: SQLite native

          - label: SQLite Cgo
            cgo: 1

          - label: PostgreSQL
            postgres: postgres
    container:
      image: matrixdotorg/sytest-dendrite:latest
      volumes:
        - ${{ github.workspace }}:/src
        - /root/.cache/go-build:/github/home/.cache/go-build
        - /root/.cache/go-mod:/gopath/pkg/mod
      env:
        POSTGRES: ${{ matrix.postgres && 1}}
        SYTEST_BRANCH: ${{ github.head_ref }}
        RACE_DETECTION: 1
        COVER: 1
    steps:
      - uses: actions/checkout@v4
      - uses: actions/cache@v4
        with:
          path: |
            ~/.cache/go-build
            /gopath/pkg/mod
          key: ${{ runner.os }}-go-sytest-${{ hashFiles('**/go.sum') }}
          restore-keys: |
            ${{ runner.os }}-go-sytest-
      - name: Run Sytest
        run: /bootstrap.sh dendrite
        working-directory: /src
      - name: Summarise results.tap
        if: ${{ always() }}
        run: /sytest/scripts/tap_to_gha.pl /logs/results.tap
      - name: Sytest List Maintenance
        if: ${{ always() }}
        run: /src/show-expected-fail-tests.sh /logs/results.tap /src/sytest-whitelist /src/sytest-blacklist
        continue-on-error: true # not fatal
      - name: Are We Synapse Yet?
        if: ${{ always() }}
        run: /src/are-we-synapse-yet.py /logs/results.tap -v
        continue-on-error: true # not fatal
      - name: Upload Sytest logs
        uses: actions/upload-artifact@v4
        if: ${{ always() }}
        with:
          name: Sytest Logs - ${{ job.status }} - (Dendrite ${{ join(matrix.*, ' ') }})
          path: |
            /logs/results.tap
            /logs/**/*.log*
            /logs/**/covdatafiles/**

  sytest-coverage:
    timeout-minutes: 5
    name: "Sytest Coverage"
    runs-on: ubuntu-latest
    needs: [ sytest, check_date ] # only run once Sytest is done and there was a commit
    if: ${{ always() && needs.check_date.outputs.should_run != 'false' }}
    steps:
      - uses: actions/checkout@v4
      - name: Install Go
        uses: actions/setup-go@v4
        with:
          go-version: 'stable'
          cache: true
      - name: Download all artifacts
        uses: actions/download-artifact@v4
      - name: Collect coverage
        run: |
          go tool covdata textfmt -i="$(find Sytest* -name 'covmeta*' -type f -exec dirname {} \; | uniq | paste -s -d ',' -)" -o sytest.cov
          grep -Ev 'relayapi|setup/mscs|api_trace' sytest.cov > final.cov
          go tool covdata func -i="$(find Sytest* -name 'covmeta*' -type f -exec dirname {} \; | uniq | paste -s -d ',' -)"
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v4
        with:
          files: ./final.cov
          flags: sytest
          fail_ci_if_error: true
          token: ${{ secrets.CODECOV_TOKEN }}

  # run Complement
  complement:
    needs: check_date
    if: ${{ needs.check_date.outputs.should_run != 'false' }}
    name: "Complement (${{ matrix.label }})"
    timeout-minutes: 60
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        include:
          - label: SQLite native
            cgo: 0

          - label: SQLite Cgo
            cgo: 1

          - label: PostgreSQL
            postgres: Postgres
            cgo: 0
    steps:
      # Env vars are set file a file given by $GITHUB_PATH. We need both Go 1.17 and GOPATH on env to run Complement.
      # See https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-system-path
      - name: "Set Go Version"
        run: |
          echo "$GOROOT_1_17_X64/bin" >> $GITHUB_PATH
          echo "~/go/bin" >> $GITHUB_PATH
      - name: "Install Complement Dependencies"
        # We don't need to install Go because it is included on the Ubuntu 20.04 image:
        # See https://github.com/actions/virtual-environments/blob/main/images/linux/Ubuntu2004-Readme.md specifically GOROOT_1_17_X64
        run: |
          sudo apt-get update && sudo apt-get install -y libolm3 libolm-dev
          go install github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@latest
      - name: Run actions/checkout@v4 for dendrite
        uses: actions/checkout@v4
        with:
          path: dendrite

      # Attempt to check out the same branch of Complement as the PR. If it
      # doesn't exist, fallback to main.
      - name: Checkout complement
        shell: bash
        run: |
          mkdir -p complement
          # Attempt to use the version of complement which best matches the current
          # build. Depending on whether this is a PR or release, etc. we need to
          # use different fallbacks.
          #
          # 1. First check if there's a similarly named branch (GITHUB_HEAD_REF
          #    for pull requests, otherwise GITHUB_REF).
          # 2. Attempt to use the base branch, e.g. when merging into release-vX.Y
          #    (GITHUB_BASE_REF for pull requests).
          # 3. Use the default complement branch ("master").
          for BRANCH_NAME in "$GITHUB_HEAD_REF" "$GITHUB_BASE_REF" "${GITHUB_REF#refs/heads/}" "master"; do
            # Skip empty branch names and merge commits.
            if [[ -z "$BRANCH_NAME" || $BRANCH_NAME =~ ^refs/pull/.* ]]; then
              continue
            fi
            (wget -O - "https://github.com/matrix-org/complement/archive/$BRANCH_NAME.tar.gz" | tar -xz --strip-components=1 -C complement) && break
          done
      # Build initial Dendrite image
      - run: docker build --build-arg=CGO=${{ matrix.cgo }} -t complement-dendrite:${{ matrix.postgres }}${{ matrix.cgo }} -f build/scripts/Complement${{ matrix.postgres }}.Dockerfile .
        working-directory: dendrite
        env:
          DOCKER_BUILDKIT: 1

      - name: Create post test script
        run: |
          cat <<EOF > /tmp/posttest.sh
          #!/bin/bash
          mkdir -p /tmp/Complement/logs/\$2/\$1/
          docker cp \$1:/tmp/covdatafiles/. /tmp/Complement/logs/\$2/\$1/
          EOF
          
          chmod +x /tmp/posttest.sh
      # Run Complement
      - run: |
          set -o pipefail &&
          go test -v -json -tags dendrite_blacklist ./tests ./tests/csapi 2>&1 | gotestfmt -hide all
        shell: bash
        name: Run Complement Tests
        env:
          COMPLEMENT_BASE_IMAGE: complement-dendrite:${{ matrix.postgres }}${{ matrix.cgo }}
          COMPLEMENT_SHARE_ENV_PREFIX: COMPLEMENT_DENDRITE_
          COMPLEMENT_DENDRITE_COVER: 1
          COMPLEMENT_POST_TEST_SCRIPT: /tmp/posttest.sh
        working-directory: complement

      - name: Upload Complement logs
        uses: actions/upload-artifact@v4
        if: ${{ always() }}
        with:
          name: Complement Logs - (Dendrite ${{ join(matrix.*, ' ') }})
          path: |
            /tmp/Complement/logs/**

  complement-coverage:
    timeout-minutes: 5
    name: "Complement Coverage"
    runs-on: ubuntu-latest
    needs: [ complement, check_date ] # only run once Complements is done and there was a commit
    if: ${{ always() && needs.check_date.outputs.should_run != 'false' }}
    steps:
      - uses: actions/checkout@v4
      - name: Install Go
        uses: actions/setup-go@v4
        with:
          go-version: 'stable'
          cache: true
      - name: Download all artifacts
        uses: actions/download-artifact@v4
      - name: Collect coverage
        run: |
          go tool covdata textfmt -i="$(find Complement* -name 'covmeta*' -type f -exec dirname {} \; | uniq | paste -s -d ',' -)" -o complement.cov
          grep -Ev 'relayapi|setup/mscs|api_trace' complement.cov > final.cov
          go tool covdata func -i="$(find Complement* -name 'covmeta*' -type f -exec dirname {} \; | uniq | paste -s -d ',' -)"
      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v4
        with:
          files: ./final.cov
          flags: complement
          fail_ci_if_error: true
          token: ${{ secrets.CODECOV_TOKEN }} # required

  element-web:
    if: ${{ false }} # disable for now, as Cypress has been replaced by Playwright
    timeout-minutes: 120
    runs-on: ubuntu-latest
    steps:
      - uses: tecolicom/actions-use-apt-tools@v1
        with:
          # Our test suite includes some screenshot tests with unusual diacritics, which are
          # supposed to be covered by STIXGeneral.
          tools: fonts-stix
      - uses: actions/checkout@v4
        with:
          repository: matrix-org/matrix-react-sdk
      - uses: actions/setup-node@v3
        with:
          cache: 'yarn'
      - name: Fetch layered build
        run: scripts/ci/layered.sh
      - name: Copy config
        run: cp element.io/develop/config.json config.json
        working-directory: ./element-web
      - name: Build
        env:
          CI_PACKAGE: true
          NODE_OPTIONS: "--openssl-legacy-provider"
        run: yarn build
        working-directory: ./element-web
      - name: Edit Test Config
        run: |
          sed -i '/HOMESERVER/c\        HOMESERVER: "dendrite",' cypress.config.ts
      - name: "Run cypress tests"
        uses: cypress-io/github-action@v4.1.1
        with:
          browser: chrome
          start: npx serve -p 8080 ./element-web/webapp
          wait-on: 'http://localhost:8080'
        env:
          PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: true
          TMPDIR: ${{ runner.temp }}

  element-web-pinecone:
    if: ${{ false }} # disable for now, as Cypress has been replaced by Playwright
    timeout-minutes: 120
    runs-on: ubuntu-latest
    steps:
      - uses: tecolicom/actions-use-apt-tools@v1
        with:
          # Our test suite includes some screenshot tests with unusual diacritics, which are
          # supposed to be covered by STIXGeneral.
          tools: fonts-stix
      - uses: actions/checkout@v4
        with:
          repository: matrix-org/matrix-react-sdk
      - uses: actions/setup-node@v3
        with:
          cache: 'yarn'
      - name: Fetch layered build
        run: scripts/ci/layered.sh
      - name: Copy config
        run: cp element.io/develop/config.json config.json
        working-directory: ./element-web
      - name: Build
        env:
          CI_PACKAGE: true
          NODE_OPTIONS: "--openssl-legacy-provider"
        run: yarn build
        working-directory: ./element-web
      - name: Edit Test Config
        run: |
          sed -i '/HOMESERVER/c\        HOMESERVER: "dendritePinecone",' cypress.config.ts
      - name: "Run cypress tests"
        uses: cypress-io/github-action@v4.1.1
        with:
          browser: chrome
          start: npx serve -p 8080 ./element-web/webapp
          wait-on: 'http://localhost:8080'
        env:
          PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: true
          TMPDIR: ${{ runner.temp }}
