name: CI on: pull_request: types: [opened, synchronize] workflow_dispatch: jobs: quality: runs-on: docker timeout-minutes: 10 steps: - uses: actions/checkout@v4 - name: Set up environment run: make setup - name: Lint all run: | . .venv/bin/activate export PATH="$HOME/.local/bin:$PATH" make lint-all - name: Unit tests with 100% coverage run: | . .venv/bin/activate make pytest-cov - name: Check unit test speed run: | . .venv/bin/activate python3 scripts/check_test_speed.py --max-seconds 10 - name: Documentation coverage check env: PYTHONPATH: src run: | . .venv/bin/activate python3 scripts/ci/doc_coverage.py release-dry-run: needs: [quality, detect-changes] if: needs.detect-changes.outputs.user-facing-changed == 'true' runs-on: docker timeout-minutes: 10 steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up environment run: make setup - name: Release dry-run validation env: PYTHONPATH: . run: | . .venv/bin/activate export PATH="$HOME/.local/bin:$PATH" python3 scripts/ci/release.py --dry-run || true detect-changes: runs-on: docker timeout-minutes: 10 outputs: ansible-changed: ${{ steps.detect.outputs.ansible-changed }} user-facing-changed: ${{ steps.detect.outputs.user-facing-changed }} steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up environment run: make setup - name: Detect changed paths id: detect env: PYTHONPATH: src run: | . .venv/bin/activate python3 scripts/ci/classify_changes.py \ --base "origin/master" \ --head "${{ github.event.pull_request.head.sha || github.sha }}" \ --github-output discover-runners: needs: [detect-changes] if: needs.detect-changes.outputs.ansible-changed == 'true' runs-on: docker timeout-minutes: 10 outputs: runner-count: ${{ steps.discover.outputs.runner-count }} runner-indices: ${{ steps.discover.outputs.runner-indices }} steps: - uses: actions/checkout@v4 - name: Set up environment run: make setup - name: Discover available runners id: discover env: REPO_TOKEN: ${{ secrets.REPO_TOKEN }} MOLECULE_RUNNERS: ${{ vars.MOLECULE_RUNNERS }} PYTHONPATH: src run: | . .venv/bin/activate python3 scripts/ci/discover_runners.py \ --owner "${{ github.repository_owner }}" \ --repo "${{ github.event.repository.name }}" \ --github-output molecule-tests: needs: [quality, detect-changes, discover-runners] if: needs.detect-changes.outputs.ansible-changed == 'true' runs-on: docker timeout-minutes: 10 strategy: matrix: runner-index: [1, 2, 3] steps: - uses: actions/checkout@v4 - name: Set up environment run: make setup - name: Discover assigned test pairs env: RUNNER_INDEX: ${{ matrix.runner-index }} MAX_RUNNERS: ${{ needs.discover-runners.outputs.runner-count }} run: | . .venv/bin/activate python3 scripts/ci/distribute_molecule.py \ --runner-index "$RUNNER_INDEX" \ --max-runners "$MAX_RUNNERS" \ --github-env --skip-if-excess - name: Run molecule tests if: env.SKIP != 'true' run: | . .venv/bin/activate if [ -z "$TEST_PAIRS" ]; then exit 0; fi # shellcheck disable=SC2086 # intentional word splitting for argument expansion python3 scripts/ci/molecule_ci_guard.py $TEST_PAIRS env: GITEA_URL: ${{ github.server_url }} REPO_TOKEN: ${{ secrets.REPO_TOKEN }} RUN_ID: ${{ github.run_id }} JOB_NAME: ${{ github.job }} MATRIX_INDEX: ${{ matrix.runner-index }} GITEA_REPOSITORY: ${{ github.repository }} pr-review: if: github.event_name == 'pull_request' runs-on: docker timeout-minutes: 10 steps: - uses: actions/checkout@v4 - name: Set up environment run: make setup - name: Run automated PR review env: REPO_TOKEN: ${{ secrets.REPO_TOKEN }} PYTHONPATH: src run: | set -euo pipefail . .venv/bin/activate python3 scripts/ci/pr_review.py \ "${{ github.event.number }}" \ "${{ github.repository }}"