name: CI
run-name: "CI (${{ github.event_name == 'pull_request' && format('pr: #{0}', github.event.number) || format('{0}: {1}', startsWith(github.event.ref, 'refs/tags') && 'tag' || 'branch', github.ref_name) }})"

on:
  - push
  - pull_request

env:
  COLUMNS: 190

concurrency:
  # Concurrency is defined in a way that concurrent builds against branches do
  # not cancel previous builds.
  # However, for every new build against the same pull request source branch,
  # all older builds against that same branch get canceled.
  group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.repository }}-${{ github.head_ref || github.run_id }}
  cancel-in-progress: true

jobs:
  Pre-Commit:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - uses: ./.github/actions/setup-actionlint
    - uses: ./.github/actions/setup-shellcheck
    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: 3.11
    - name: Set Cache Key
      run: echo "PY=$(python --version --version | sha256sum | cut -d' ' -f1)" >> "$GITHUB_ENV"
    - uses: actions/cache@v4
      with:
        path: ~/.cache/pre-commit
        key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}|${{ hashFiles('.pre-commit-hooks/*') }}
    - name: Install Dependencies
      run: |
        python -m pip install pre-commit
        pre-commit install --install-hooks
    - name: Run Pre-Commit
      run: |
        pre-commit run --show-diff-on-failure --color=always --all-files

  Docs:
    runs-on: ubuntu-22.04
    needs: Pre-Commit

    timeout-minutes: 10

    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0

    - name: Set up Python 3.11 For Nox
      uses: actions/setup-python@v5
      with:
        python-version: 3.11

    - name: Install Nox
      run: |
        python -m pip install --upgrade pip
        python -m pip install nox

    - name: Install Doc Requirements
      run: |
        nox --force-color -e docs --install-only

    - name: Build Docs
      env:
        SKIP_REQUIREMENTS_INSTALL: YES
      run: |
        nox --force-color -e docs


  PyLint:
    runs-on: ubuntu-latest
    needs: Pre-Commit

    timeout-minutes: 10

    steps:
    - uses: actions/checkout@v4

    - name: Set up Python 3.11 For Nox
      uses: actions/setup-python@v5
      with:
        python-version: 3.11

    - name: Install Nox
      run: |
        python -m pip install --upgrade pip
        python -m pip install nox

    - name: Install Lint Requirements
      run: |
        nox --force-color -e lint --install-only

    - name: Lint Code
      env:
        SKIP_REQUIREMENTS_INSTALL: YES
      run: |
        nox --force-color -e lint


  Linux-System-Service:
    runs-on: ubuntu-22.04
    needs: Pre-Commit

    timeout-minutes: 25

    strategy:
      fail-fast: false
      matrix:
        pytest-version:
          - "7.4.0"
        salt-version:
          - "3006"

    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0

    - name: Install Nox
      run: |
        sudo -E apt-get update
        sudo -E apt-get install -y python3-setuptools python-is-python3
        sudo -E python3 -m pip install --upgrade pip
        sudo -E python3 -m pip install 'nox<2022.8.7'
        sudo mv /usr/bin/pip /usr/bin/pip2
        sudo ln -sf /usr/bin/pip3 /usr/bin/pip

    - name: Install Salt
      run: |
        curl -L https://github.com/saltstack/salt-bootstrap/releases/latest/download/bootstrap-salt.sh | sudo sh -s -- -M -X -x python3 stable ${{ matrix.salt-version }}
        sudo apt-get install -y salt-api salt-ssh salt-syndic salt-cloud python3-pip
        for service in $(sudo systemctl list-unit-files | grep salt | grep -v @ | awk '{ print $1 }'); do sudo systemctl stop "$service"; done

    - name: Install Test Requirements
      run: |
        sudo -E nox --force-color -e tests --no-venv --install-only

    - name: Test
      id: run-tests
      env:
        SKIP_REQUIREMENTS_INSTALL: YES
        SALT_FACTORIES_SYSTEM_SERVICE: "1"
      run: |
        sudo -E nox --force-color -e tests --no-venv -- -vv --system-service tests/

    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v5
      with:
        token: ${{ secrets.CODECOV_TOKEN }}
        directory: artifacts/
        fail_ci_if_error: false
        files: coverage-project.xml
        flags: src,${{ runner.os }},salt-${{ matrix.salt-version }},system,pytest-${{ matrix.pytest-version }}
        name: project-${{ runner.os }}-Salt-${{ matrix.salt-version }}-System-Pytest${{ matrix.pytest-version }}
        verbose: true

    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v5
      with:
        token: ${{ secrets.CODECOV_TOKEN }}
        directory: artifacts/
        env_vars: PYTHON,SALT,TESTSUITE,SOURCE
        fail_ci_if_error: false
        files: coverage-tests.xml
        flags: tests,${{ runner.os }},salt-${{ matrix.salt-version }},system,pytest-${{ matrix.pytest-version }}
        name: tests-${{ runner.os }}-Salt-${{ matrix.salt-version }}-System-Pytest${{ matrix.pytest-version }}
        verbose: true

    - name: Upload Logs
      if: always()
      uses: actions/upload-artifact@v4
      with:
        name: runtests-${{ runner.os }}-Salt-${{ matrix.salt-version }}-System-Pytest${{ matrix.pytest-version }}.log
        path: artifacts/runtests-*.log


  Windows:
    runs-on: windows-latest
    needs: Pre-Commit

    timeout-minutes: 60

    strategy:
      fail-fast: false
      max-parallel: 16
      matrix:
        python-version:
          - "3.10"
        salt-version:
          - "3006.9"
          - "3007.1"
        pytest-version:
          - "7.4.0"
          - "8.0.0"
          - "8.1.1"
          - "8.2.0"
          - "8.3.3"

    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0

    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v5
      with:
        python-version: ${{ matrix.python-version }}

    - name: Install Nox
      run: |
        python -m pip install --upgrade pip
        python -m pip install nox

    - name: Install Test Requirements
      shell: bash
      env:
        SALT_REQUIREMENT: salt~=${{ matrix.salt-version }}
        PYTEST_VERSION_REQUIREMENT: pytest~=${{ matrix.pytest-version }}
      run: |
        export PATH="/C/Program Files (x86)/Windows Kits/10/bin/10.0.18362.0/x64;$PATH"
        nox --force-color -e tests-${{ matrix.python-version }} --install-only

    - name: Test
      id: run-tests
      shell: bash
      env:
        SALT_REQUIREMENT: salt~=${{ matrix.salt-version }}
        PYTEST_VERSION_REQUIREMENT: pytest~=${{ matrix.pytest-version }}
        SKIP_REQUIREMENTS_INSTALL: YES
      run: |
        export PATH="/C/Program Files (x86)/Windows Kits/10/bin/10.0.18362.0/x64;$PATH"
        nox --force-color -e tests-${{ matrix.python-version }} -- -vv tests/

    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v5
      with:
        token: ${{ secrets.CODECOV_TOKEN }}
        directory: artifacts/
        fail_ci_if_error: false
        files: coverage-project.xml
        flags: src,${{ runner.os }},salt-${{ matrix.salt-version }},py${{ matrix.python-version }},pytest-${{ matrix.pytest-version }}
        name: project-${{ runner.os }}-Salt-${{ matrix.salt-version }}-Py${{ matrix.python-version}}-Pytest${{ matrix.pytest-version }}
        verbose: true

    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v5
      with:
        token: ${{ secrets.CODECOV_TOKEN }}
        directory: artifacts/
        env_vars: PYTHON,SALT,TESTSUITE,SOURCE
        fail_ci_if_error: false
        files: coverage-tests.xml
        flags: tests,${{ runner.os }},salt-${{ matrix.salt-version }},py${{ matrix.python-version }},pytest-${{ matrix.pytest-version }}
        name: tests-${{ runner.os }}-Salt-${{ matrix.salt-version }}-Py${{ matrix.python-version}}-Pytest${{ matrix.pytest-version }}
        verbose: true

    - name: Upload Logs
      if: always()
      uses: actions/upload-artifact@v4
      with:
        name: runtests-${{ runner.os }}-Salt-${{ matrix.salt-version }}-Py${{ matrix.python-version}}-Pytest${{ matrix.pytest-version }}.log
        path: artifacts/runtests-*.log


  MacOS:
    runs-on: ${{ github.event.repository.fork && 'macos-latest' || 'macos-13' }}
    needs: Pre-Commit

    timeout-minutes: 90

    strategy:
      fail-fast: false
      max-parallel: 16
      matrix:
        python-version:
          - "3.10"
        salt-version:
          - "3006.9"
        pytest-version:
          - "7.4.0"
          - "8.0.0"
          - "8.1.1"
          - "8.2.0"
          - "8.3.3"

    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0

    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v5
      with:
        python-version: ${{ matrix.python-version }}

    - name: Install Nox
      run: |
        python -m pip install --upgrade pip
        python -m pip install nox

    - name: Install Test Requirements
      env:
        SALT_REQUIREMENT: salt~=${{ matrix.salt-version }}
        PYTEST_VERSION_REQUIREMENT: pytest~=${{ matrix.pytest-version }}
      run: |
        nox --force-color -e tests-${{ matrix.python-version }} --install-only

    - name: Test
      id: run-tests
      env:
        SALT_REQUIREMENT: salt~=${{ matrix.salt-version }}
        PYTEST_VERSION_REQUIREMENT: pytest~=${{ matrix.pytest-version }}
        SKIP_REQUIREMENTS_INSTALL: YES
      run: |
        nox --force-color -e tests-${{ matrix.python-version }} -- -vv tests/

    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v5
      with:
        token: ${{ secrets.CODECOV_TOKEN }}
        directory: artifacts/
        fail_ci_if_error: false
        files: coverage-project.xml
        flags: src,${{ runner.os }},salt-${{ matrix.salt-version }},py${{ matrix.python-version }},pytest-${{ matrix.pytest-version }}
        name: project-${{ runner.os }}-Salt-${{ matrix.salt-version }}-Py${{ matrix.python-version}}-Pytest${{ matrix.pytest-version }}
        verbose: true

    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v5
      with:
        token: ${{ secrets.CODECOV_TOKEN }}
        directory: artifacts/
        env_vars: PYTHON,SALT,TESTSUITE,SOURCE
        fail_ci_if_error: false
        files: coverage-tests.xml
        flags: tests,${{ runner.os }},salt-${{ matrix.salt-version }},py${{ matrix.python-version }},pytest-${{ matrix.pytest-version }}
        name: tests-${{ runner.os }}-Salt-${{ matrix.salt-version }}-Py${{ matrix.python-version}}-Pytest${{ matrix.pytest-version }}
        verbose: true

    - name: Upload Logs
      if: always()
      uses: actions/upload-artifact@v4
      with:
        name: runtests-${{ runner.os }}-Salt-${{ matrix.salt-version }}-Py${{ matrix.python-version}}-Pytest${{ matrix.pytest-version }}.log
        path: artifacts/runtests-*.log


  Linux:
    runs-on: ubuntu-22.04
    needs: Pre-Commit

    timeout-minutes: 25

    strategy:
      fail-fast: false
      max-parallel: 16
      matrix:
        python-version:
          - "3.10"
        salt-version:
          - "3006.9"
          - "3007.1"
        pytest-version:
          - "7.4.0"
          - "8.0.0"
          - "8.1.1"
          - "8.2.0"
          - "8.3.3"

    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0

    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v5
      with:
        python-version: ${{ matrix.python-version }}

    - name: Install Nox
      run: |
        python -m pip install --upgrade pip
        python -m pip install nox

    - name: Install Test Requirements
      env:
        SALT_REQUIREMENT: salt~=${{ matrix.salt-version }}
        PYTEST_VERSION_REQUIREMENT: pytest~=${{ matrix.pytest-version }}
      run: |
        nox --force-color -e tests-${{ matrix.python-version }} --install-only

    - name: Test
      id: run-tests
      env:
        SALT_REQUIREMENT: salt~=${{ matrix.salt-version }}
        PYTEST_VERSION_REQUIREMENT: pytest~=${{ matrix.pytest-version }}
        SKIP_REQUIREMENTS_INSTALL: YES
      run: |
        nox --force-color -e tests-${{ matrix.python-version }} -- -vv --sys-stats tests/

    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v5
      with:
        token: ${{ secrets.CODECOV_TOKEN }}
        directory: artifacts/
        fail_ci_if_error: false
        files: coverage-project.xml
        flags: src,${{ runner.os }},salt-${{ matrix.salt-version }},py${{ matrix.python-version }},pytest-${{ matrix.pytest-version }}
        name: project-${{ runner.os }}-Salt-${{ matrix.salt-version }}-Py${{ matrix.python-version}}-Pytest${{ matrix.pytest-version }}
        verbose: true

    - name: Upload coverage to Codecov
      uses: codecov/codecov-action@v5
      with:
        token: ${{ secrets.CODECOV_TOKEN }}
        directory: artifacts/
        env_vars: PYTHON,SALT,TESTSUITE,SOURCE
        fail_ci_if_error: false
        files: coverage-tests.xml
        flags: tests,${{ runner.os }},salt-${{ matrix.salt-version }},py${{ matrix.python-version }},pytest-${{ matrix.pytest-version }}
        name: tests-${{ runner.os }}-Salt-${{ matrix.salt-version }}-Py${{ matrix.python-version}}-Pytest${{ matrix.pytest-version }}
        verbose: true

    - name: Upload Logs
      if: always()
      uses: actions/upload-artifact@v4
      with:
        name: runtests-${{ runner.os }}-Salt-${{ matrix.salt-version }}-Py${{ matrix.python-version}}-Pytest${{ matrix.pytest-version }}.log
        path: artifacts/runtests-*.log


  Build:
    runs-on: ubuntu-latest
    environment: release
    permissions:
      id-token: write  # IMPORTANT: this permission is mandatory for trusted publishing
    needs:
      - Docs
      - PyLint
      - Linux
      - Windows
      - MacOS
      - Linux-System-Service
    steps:
    - uses: actions/checkout@v4
      with:
        fetch-depth: 0
    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: 3.11

    - name: Install Nox
      run: |
        python -m pip install nox

    - name: Build a binary wheel and a source tarball
      run: |
        nox -e build

    - name: Publish distribution 📦 to Test PyPI
      if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
      uses: pypa/gh-action-pypi-publish@release/v1
      with:
        repository-url: https://test.pypi.org/legacy/
        print-hash: true
        skip-existing: true
        verify-metadata: true

  set-pipeline-exit-status:
    # This step is just so we can make github require this step, to pass checks
    # on a pull request instead of requiring all
    name: Set the ${{ github.workflow }} Pipeline Exit Status
    if: always()
    runs-on: ubuntu-latest
    needs:
      - pre-commit
      - Docs
      - PyLint
      - Linux
      - Windows
      - MacOS
      - Linux-System-Service
      - Build
    steps:
      - name: Get workflow information
        id: get-workflow-info
        uses: technote-space/workflow-conclusion-action@v3

      - name: Set Pipeline Exit Status
        shell: bash
        run: |
          if [ "${{ steps.get-workflow-info.outputs.conclusion }}" != "success" ]; then
            exit 1
          else
            exit 0
          fi

      - name: Done
        if: always()
        run:
          echo "All worflows finished"
