# Also note that this name *MUST* match the filename because GHA
# only provides the workflow name (https://docs.github.com/en/free-pro-team@latest/actions/reference/environment-variables#default-environment-variables)
# and GH APIs only support querying by workflow *FILENAME* (https://developer.github.com/v3/actions/workflows/#get-a-workflow)
name: acceptance
on:
  push:
    branches:
      - master
      - releases/**
  pull_request:

# Cancel in progress workflows on pull_requests.
# https://docs.github.com/en/actions/using-jobs/using-concurrency#example-using-a-fallback-value
concurrency:
  group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
  cancel-in-progress: true

# hack for https://github.com/actions/cache/issues/810#issuecomment-1222550359
env:
  SEGMENT_DOWNLOAD_TIMEOUT_MINS: 3
  NODE_OPTIONS: '--max-old-space-size=4096'

jobs:
  files-changed:
    name: detect what files changed
    runs-on: ubuntu-22.04
    timeout-minutes: 3
    # Map a step output to a job output
    outputs:
      acceptance: ${{ steps.changes.outputs.acceptance }}
      backend_all: ${{ steps.changes.outputs.backend_all }}
      frontend_all: ${{ steps.changes.outputs.frontend_all }}
    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

      - name: Check for backend file changes
        uses: dorny/paths-filter@0bc4621a3135347011ad047f9ecf449bf72ce2bd # v3.0.0
        id: changes
        with:
          token: ${{ github.token }}
          filters: .github/file-filters.yml

  acceptance:
    if: needs.files-changed.outputs.acceptance == 'true'
    needs: files-changed
    name: acceptance
    runs-on: ubuntu-22.04
    timeout-minutes: 30
    permissions:
      contents: read
      id-token: write
    strategy:
      # This helps not having to run multiple jobs because one fails, thus, reducing resource usage
      # and reducing the risk that one of many runs would turn red again (read: intermittent tests)
      fail-fast: false
      matrix:
        # XXX: When updating this, make sure you also update MATRIX_INSTANCE_TOTAL.
        instance: [0, 1, 2, 3, 4]
        pg-version: ['14']
    env:
      # XXX: MATRIX_INSTANCE_TOTAL must be hardcoded to the length of strategy.matrix.instance.
      MATRIX_INSTANCE_TOTAL: 5
      TEST_GROUP_STRATEGY: roundrobin

    steps:
      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
        name: Checkout sentry

      - uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4
        id: setup-node
        with:
          node-version-file: '.volta.json'

      - name: Step configurations
        id: config
        run: |
          echo "webpack-path=.webpack_cache" >> "$GITHUB_OUTPUT"
          echo "WEBPACK_CACHE_PATH=.webpack_cache" >> "$GITHUB_ENV"

      - name: webpack cache
        uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
        with:
          path: ${{ steps.config.outputs.webpack-path }}
          key: ${{ runner.os }}-v2-webpack-cache-${{ hashFiles('webpack.config.ts') }}

      - name: node_modules cache
        uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 # v4.0.0
        id: nodemodulescache
        with:
          path: node_modules
          key: ${{ runner.os }}-node-modules-${{ hashFiles('yarn.lock', 'api-docs/yarn.lock', '.volta.json') }}

      - name: Install Javascript Dependencies
        if: steps.nodemodulescache.outputs.cache-hit != 'true'
        run: yarn install --frozen-lockfile

      - name: webpack
        env:
          # this is fine to not have for forks, it shouldn't fail
          SENTRY_WEBPACK_WEBHOOK_SECRET: ${{ secrets.SENTRY_WEBPACK_WEBHOOK_SECRET }}
          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
          # should set value either as `true` or `false`
          CODECOV_ENABLE_BA: ${{ needs.files-changed.outputs.frontend_all == 'true'}}
          GH_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}
        run: |
          yarn build-acceptance

      - name: Build chartcuterie configuration module
        run: |
          make build-chartcuterie-config

      - name: Setup sentry env
        uses: ./.github/actions/setup-sentry
        id: setup
        with:
          snuba: true
          chartcuterie: true
          pg-version: ${{ matrix.pg-version }}

      - name: Run acceptance tests (#${{ steps.setup.outputs.matrix-instance-number }} of ${{ steps.setup.outputs.matrix-instance-total }})
        run: make run-acceptance

      - name: Collect test data
        uses: ./.github/actions/collect-test-data
        if: ${{ !cancelled() && needs.files-changed.outputs.backend_all == 'true' }}
        with:
          artifact_path: .artifacts/pytest.acceptance.json
          gcs_bucket: ${{ secrets.COLLECT_TEST_DATA_GCS_BUCKET }}
          gcp_project_id: ${{ secrets.COLLECT_TEST_DATA_GCP_PROJECT_ID }}
          workload_identity_provider: ${{ secrets.SENTRY_GCP_DEV_WORKLOAD_IDENTITY_POOL }}
          service_account_email: ${{ secrets.COLLECT_TEST_DATA_SERVICE_ACCOUNT_EMAIL }}
          matrix_instance_number: ${{ steps.setup.outputs.matrix-instance-number }}

      # This job runs when FE or BE changes happen, however, we only upload coverage data for
      # BE changes since it conflicts with codecov's carry forward functionality
      # Upload coverage data even if running the tests step fails since
      # it reduces large coverage fluctuations
      - name: Handle artifacts
        uses: ./.github/actions/artifacts
        if: ${{ always() && needs.files-changed.outputs.backend_all == 'true' }}
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          commit_sha: ${{ github.event.pull_request.head.sha }}

  acceptance-required-checks:
    # this is a required check so we need this job to always run and report a status.
    if: always()
    name: Acceptance
    needs: [acceptance, files-changed]
    runs-on: ubuntu-22.04
    timeout-minutes: 3
    steps:
      - name: Check for failures
        if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
        run: |
          echo "One of the dependent jobs have failed. You may need to re-run it." && exit 1