name: fast tests

on:
  pull_request:
  workflow_dispatch:
  push:
    branches:
      - master
      - '8.*.x'

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

defaults:
  run:
    shell: bash -c "exec $CONDA_PREFIX/bin/bash -elo pipefail {0}"

env:
  PIP_PROGRESS_BAR: off

jobs:
  test:
    runs-on: ${{ matrix.os }}
    timeout-minutes: 20
    strategy:
      fail-fast: false # don't stop on first failure
      matrix:
        os: ['ubuntu-latest']
        python-version: ['3.12', '3']
        include:
          - os: 'macos-latest'
            python-version: '3.12' # oldest version we support
          # non-utc timezone test
          - os: 'ubuntu-latest'
            python-version: '3'
            time-zone: 'XXX-09:35'
    env:
      TZ: ${{ matrix.time-zone }}
      PYTEST_ADDOPTS: --cov --cov-append -n 5 --color=yes
    steps:
      - name: Checkout
        uses: actions/checkout@v5

      - name: Install System Dependencies
        uses: mamba-org/setup-micromamba@v2
        with:
          cache-environment: true
          post-cleanup: 'all'
          environment-name: cylc-fast-test
          create-args: >-
            python=${{ matrix.python-version }}
            pip
            bash
            subversion
            sqlite
            graphviz

      - name: Install Python Dependencies
        run: |
          pip install -e ."[all]"

      - name: Patch DNS
        uses: cylc/release-actions/patch-dns@v1

      - name: Configure git  # Needed by the odd test
        uses: cylc/release-actions/configure-git@v1

      # Useful debug info:
      - name: Pip list
        run: pip list

      - name: Unit Tests
        timeout-minutes: 5
        run: |
          pytest cylc/flow tests/unit

      - name: Integration Tests
        timeout-minutes: 5
        run: |
          pytest tests/integration --ignore tests/integration/tui/

      - name: Tui Integration Tests
        timeout-minutes: 5
        # Re-run failed Tui tests as they can be flaky
        run: |
          pytest tests/integration/tui || pytest tests/integration/tui --last-failed

      - name: Upload failed tests artifact
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: cylc-run (${{ matrix.os }} py-${{ matrix.python-version }})
          path: ~/cylc-run/
          include-hidden-files: true

      - name: Coverage report
        run: |
          coverage xml
          coverage report

      - name: Upload coverage artifact
        uses: actions/upload-artifact@v4
        with:
          name: coverage_${{ matrix.os }}_py-${{ matrix.python-version }}
          path: coverage.xml
          retention-days: 7

  lint:
    runs-on: 'ubuntu-latest'
    timeout-minutes: 10
    strategy:
      matrix:
        python-version: ['3']
    env:
      FORCE_COLOR: 2
    steps:
      - name: Checkout
        uses: actions/checkout@v5

      - name: Install System Dependencies
        uses: mamba-org/setup-micromamba@v2
        with:
          cache-environment: true
          post-cleanup: 'all'
          environment-name: cylc-lint-test
          create-args: >-
            python=${{ matrix.python-version }}
            pip
            bash
            shellcheck

      - name: Install Python Dependencies
        run: |
          pip install -e ."[tests]"

      - name: Flake8
        run: flake8

      - name: Bandit
        run: |
          bandit -r --ini .bandit cylc/flow

      - name: Shellchecker
        run: etc/bin/shellchecker

      - name: MyPy
        run: mypy

      - name: Towncrier - draft changelog
        uses: cylc/release-actions/towncrier-draft@v1

      - name: Linkcheck
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: pytest -m linkcheck -ra --dist=load --color=yes -n 10 tests/unit/test_links.py

  codecov:
    needs: test
    runs-on: ubuntu-latest
    timeout-minutes: 2
    steps:
      - name: Checkout
        uses: actions/checkout@v5

      - name: Download coverage artifacts
        uses: actions/download-artifact@v5

      - name: Codecov upload
        uses: codecov/codecov-action@v5
        with:
          name: ${{ github.workflow }}
          flags: fast-tests
          fail_ci_if_error: true
          verbose: true
          # Token not required for public repos, but avoids upload failure due
          # to rate-limiting (but not for PRs opened from forks)
          token: ${{ secrets.CODECOV_TOKEN }}
