From dbafe6c3f588149bc45d0b8c1a43a94d874c48b6 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Sun, 14 May 2023 16:47:36 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=A8=F0=9F=A7=AA=20Modularize=20GHA=20w?= =?UTF-8?q?orkflow=20through=20reuse?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This change slightly refactors parts of the GitHub Actions CI/CD workflow definitions to make it possible to rely on the main check gate in branch protection and declutter the generic workflow. It reproduces the original efforts of skipping the unnecessary checks depending on the files changed via dynamically determined variables. --- .../workflows/reusable-change-detection.yml | 58 +++++++ .../{check.yml => reusable-docs.yml} | 9 +- .github/workflows/reusable-pytest.yml | 100 ++++++++++++ .github/workflows/reusable-type.yml | 26 +++ .github/workflows/test.yml | 152 ++++-------------- README.md | 1 - 6 files changed, 216 insertions(+), 130 deletions(-) create mode 100644 .github/workflows/reusable-change-detection.yml rename .github/workflows/{check.yml => reusable-docs.yml} (81%) create mode 100644 .github/workflows/reusable-pytest.yml create mode 100644 .github/workflows/reusable-type.yml diff --git a/.github/workflows/reusable-change-detection.yml b/.github/workflows/reusable-change-detection.yml new file mode 100644 index 00000000..6f1ef936 --- /dev/null +++ b/.github/workflows/reusable-change-detection.yml @@ -0,0 +1,58 @@ +name: change detection +on: + workflow_call: + outputs: + run-docs: + description: Whether or not build the docs + value: ${{ jobs.change-detection.outputs.run-docs || false }} + run-tests: + description: Whether or not run the tests + value: ${{ jobs.change-detection.outputs.run-tests || false }} + +jobs: + change-detection: + name: Identify source changes + runs-on: ubuntu-latest + timeout-minutes: 1 + outputs: + run-docs: ${{ steps.docs-changes.outputs.run-docs || false }} + run-tests: ${{ steps.tests-changes.outputs.run-tests || false }} + steps: + - uses: actions/checkout@v3 + - name: Get a list of the changed runtime-related files + if: github.event_name == 'pull_request' + id: changed-testable-files + uses: Ana06/get-changed-files@v2.2.0 + with: + filter: | + src/** + tests/** + tox.ini + .github/workflows/test.yml + .github/workflows/reusable-type.yml + .github/workflows/reusable-pytest.yml + - name: Set a flag for running the tests + if: >- + github.event_name != 'pull_request' + || steps.changed-testable-files.outputs.added_modified_renamed != '' + id: tests-changes + run: >- + echo "run-tests=true" >> "${GITHUB_OUTPUT}" + - name: Get a list of the changed documentation-related files + if: github.event_name == 'pull_request' + id: changed-docs-files + uses: Ana06/get-changed-files@v2.2.0 + with: + filter: | + docs/** + CHANGELOG.rst + README.md + .github/workflows/test.yml + .github/workflows/reusable-check.yml + - name: Set a flag for building the docs + if: >- + github.event_name != 'pull_request' + || steps.changed-docs-files.outputs.added_modified_renamed != '' + id: docs-changes + run: >- + echo "run-docs=true" >> "${GITHUB_OUTPUT}" diff --git a/.github/workflows/check.yml b/.github/workflows/reusable-docs.yml similarity index 81% rename from .github/workflows/check.yml rename to .github/workflows/reusable-docs.yml index 213a70b9..efb43e8e 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/reusable-docs.yml @@ -1,13 +1,6 @@ name: check on: - push: - branches: - - main - pull_request: - branches: - - main - schedule: - - cron: "0 8 * * *" + workflow_call: jobs: docs: diff --git a/.github/workflows/reusable-pytest.yml b/.github/workflows/reusable-pytest.yml new file mode 100644 index 00000000..a66d3312 --- /dev/null +++ b/.github/workflows/reusable-pytest.yml @@ -0,0 +1,100 @@ +name: pytest +on: + workflow_call: + +jobs: + pytest: + runs-on: ${{ matrix.os }}-latest + env: + PYTEST_ADDOPTS: "--run-integration --showlocals -vv --durations=10 --reruns 5 --only-rerun subprocess.CalledProcessError" + strategy: + fail-fast: false + matrix: + os: + - ubuntu + - macos + - windows + py: + - "pypy-3.7" + - "pypy-3.8" + - "pypy-3.9" + - "3.11" + - "3.10" + - "3.9" + - "3.8" + - "3.7" + tox-target: + - "tox" + - "min" + + continue-on-error: >- # jobs not required in branch protection + ${{ + ( + startsWith(matrix.py, 'pypy-') + && (!endsWith(matrix.py, '-3.7') || matrix.os == 'windows') + ) + && true + || false + }} + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Setup python for test ${{ matrix.py }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.py }} + + - name: Pick environment to run + run: | + import platform + import os + import sys + + if platform.python_implementation() == "PyPy": + base = f"pypy{sys.version_info.major}{sys.version_info.minor}" + else: + base = f"py{sys.version_info.major}{sys.version_info.minor}" + env = f"BASE={base}\n" + print(f"Picked:\n{env}for {sys.version}") + with open(os.environ["GITHUB_ENV"], "a", encoding="utf-8") as file: + file.write(env) + shell: python + + - name: Setup python for tox + uses: actions/setup-python@v4 + with: + python-version: 3.9 + + - name: Install tox + run: python -m pip install tox + + - name: Run test suite via tox + if: matrix.tox-target == 'tox' + run: | + tox -vv --notest -e ${{env.BASE}} + tox -e ${{env.BASE}} --skip-pkg-install + + - name: Run minimum version test + if: matrix.tox-target == 'min' + run: tox -e ${{env.BASE}}-${{ matrix.tox-target }} + + - name: Run path test + if: matrix.tox-target == 'tox' && matrix.py == '3.10' + run: tox -e path + + - name: Combine coverage files + if: always() + run: tox -e coverage + + - uses: codecov/codecov-action@v3 + if: always() + env: + PYTHON: ${{ matrix.python }} + with: + file: ./.tox/coverage.xml + flags: tests + env_vars: PYTHON + name: ${{ matrix.py }} - ${{ matrix.os }} diff --git a/.github/workflows/reusable-type.yml b/.github/workflows/reusable-type.yml new file mode 100644 index 00000000..09078485 --- /dev/null +++ b/.github/workflows/reusable-type.yml @@ -0,0 +1,26 @@ +name: type +on: + workflow_call: + +jobs: + type: + runs-on: ubuntu-latest + env: + PY_COLORS: 1 + TOX_PARALLEL_NO_SPINNER: 1 + steps: + - uses: actions/checkout@v3 + + - name: Setup Python 3.9 + uses: actions/setup-python@v4 + with: + python-version: 3.9 + + - name: Install tox + run: python -m pip install tox + + - name: Setup run environment + run: tox -vv --notest -e type + + - name: Run check for type + run: tox -e type --skip-pkg-install diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3664cb79..8edc0ca8 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,17 +3,9 @@ on: push: branches: - main - paths-ignore: - - "docs/**" - - "*.md" - - "*.rst" pull_request: branches: - main - paths-ignore: - - "docs/**" - - "*.md" - - "*.rst" schedule: - cron: "0 8 * * *" workflow_dispatch: @@ -23,129 +15,31 @@ concurrency: cancel-in-progress: true jobs: - pytest: - runs-on: ${{ matrix.os }}-latest - env: - PYTEST_ADDOPTS: "--run-integration --showlocals -vv --durations=10 --reruns 5 --only-rerun subprocess.CalledProcessError" - strategy: - fail-fast: false - matrix: - os: - - ubuntu - - macos - - windows - py: - - "pypy-3.7" - - "pypy-3.8" - - "pypy-3.9" - - "3.11" - - "3.10" - - "3.9" - - "3.8" - - "3.7" - tox-target: - - "tox" - - "min" - - continue-on-error: >- # jobs not required in branch protection - ${{ - ( - startsWith(matrix.py, 'pypy-') - && (!endsWith(matrix.py, '-3.7') || matrix.os == 'windows') - ) - && true - || false - }} - - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - - name: Setup python for test ${{ matrix.py }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.py }} - - - name: Pick environment to run - run: | - import platform - import os - import sys - - if platform.python_implementation() == "PyPy": - base = f"pypy{sys.version_info.major}{sys.version_info.minor}" - else: - base = f"py{sys.version_info.major}{sys.version_info.minor}" - env = f"BASE={base}\n" - print(f"Picked:\n{env}for {sys.version}") - with open(os.environ["GITHUB_ENV"], "a", encoding="utf-8") as file: - file.write(env) - shell: python - - - name: Setup python for tox - uses: actions/setup-python@v4 - with: - python-version: 3.9 - - - name: Install tox - run: python -m pip install tox + change-detection: + uses: ./.github/workflows/reusable-change-detection.yml - - name: Run test suite via tox - if: matrix.tox-target == 'tox' - run: | - tox -vv --notest -e ${{env.BASE}} - tox -e ${{env.BASE}} --skip-pkg-install + check-docs: + needs: change-detection + if: fromJSON(needs.change-detection.outputs.run-docs) + uses: ./.github/workflows/reusable-docs.yml - - name: Run minimum version test - if: matrix.tox-target == 'min' - run: tox -e ${{env.BASE}}-${{ matrix.tox-target }} - - - name: Run path test - if: matrix.tox-target == 'tox' && matrix.py == '3.10' - run: tox -e path - - - name: Combine coverage files - if: always() - run: tox -e coverage - - - uses: codecov/codecov-action@v3 - if: always() - env: - PYTHON: ${{ matrix.python }} - with: - file: ./.tox/coverage.xml - flags: tests - env_vars: PYTHON - name: ${{ matrix.py }} - ${{ matrix.os }} + pytest: + needs: change-detection + if: fromJSON(needs.change-detection.outputs.run-tests) + uses: ./.github/workflows/reusable-pytest.yml type: - runs-on: ubuntu-latest - env: - PY_COLORS: 1 - TOX_PARALLEL_NO_SPINNER: 1 - steps: - - uses: actions/checkout@v3 - - - name: Setup Python 3.9 - uses: actions/setup-python@v4 - with: - python-version: 3.9 - - - name: Install tox - run: python -m pip install tox - - - name: Setup run environment - run: tox -vv --notest -e type - - - name: Run check for type - run: tox -e type --skip-pkg-install + needs: change-detection + if: fromJSON(needs.change-detection.outputs.run-tests) + uses: ./.github/workflows/reusable-type.yml # https://github.com/marketplace/actions/alls-green#why required-checks-pass: # This job does nothing and is only used for the branch protection if: always() needs: + - change-detection # transitive + - check-docs - pytest - type @@ -155,4 +49,20 @@ jobs: - name: Decide whether the needed jobs succeeded or failed uses: re-actors/alls-green@release/v1 with: + allowed-skips: >- + ${{ + fromJSON(needs.change-detection.outputs.run-docs) + && '' + || ' + check-docs, + ' + }} + ${{ + fromJSON(needs.change-detection.outputs.run-tests) + && '' + || ' + pytest, + type, + ' + }} jobs: ${{ toJSON(needs) }} diff --git a/README.md b/README.md index a6569875..91acce6d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # build [![pre-commit.ci status](https://results.pre-commit.ci/badge/github/pypa/build/main.svg)](https://results.pre-commit.ci/latest/github/pypa/build/main) -[![CI check](https://github.com/pypa/build/workflows/check/badge.svg)](https://github.com/pypa/build/actions) [![CI test](https://github.com/pypa/build/actions/workflows/test.yml/badge.svg)](https://github.com/pypa/build/actions/workflows/test.yml) [![codecov](https://codecov.io/gh/pypa/build/branch/main/graph/badge.svg)](https://codecov.io/gh/pypa/build)