refactor: Asynchronous cog/extension loading. #8014
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # SPDX-License-Identifier: MIT | |
| name: Lint & Test | |
| on: | |
| push: | |
| branches: | |
| - "master" | |
| - "v[0-9]+.[0-9]+.x" # matches to backport branches, e.g. v3.6.x | |
| - "run-ci/**" | |
| tags: | |
| - "*" | |
| pull_request: | |
| merge_group: | |
| types: [checks_requested] | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} | |
| cancel-in-progress: true | |
| defaults: | |
| run: | |
| shell: bash | |
| env: | |
| # https://docs.astral.sh/uv/reference/environment/ | |
| UV_LOCKED: 1 | |
| UV_NO_SYNC: 1 | |
| UV_PYTHON_DOWNLOADS: never | |
| GITHUB_STEP_SUMMARY_HEADER: "<details><summary>#name#</summary>\n<pre>" | |
| GITHUB_STEP_SUMMARY_FOOTER: "</pre></details>\n" | |
| jobs: | |
| lock-dependencies: | |
| name: Lock dependencies | |
| # The only purpose of this is to create a lockfile, which will be cached | |
| # to be used with subsequent jobs. | |
| # This provides somewhat of a middle ground and avoids having each job lock dependencies on its own, | |
| # while still not needing to commit a lockfile to the repo, which is discouraged for libraries as per | |
| # https://pdm-project.org/en/latest/usage/lockfile/ | |
| runs-on: ubuntu-latest | |
| env: | |
| UV_RESOLUTION: highest | |
| steps: | |
| - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: Set up environment | |
| id: setup-env | |
| uses: ./.github/actions/setup-env | |
| with: | |
| use-cached-uv-lock: 'false' # we don't need the lock here, we will automatically download it below | |
| - name: Restore uv lock | |
| uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 | |
| id: cache-uv-lock | |
| with: | |
| key: uv-lock-resolved-${{ env.UV_RESOLUTION }} | |
| restore-keys: | | |
| uv-lock-resolved-${{ env.UV_RESOLUTION }} | |
| path: uv.lock | |
| enableCrossOsArchive: true | |
| - name: Check if uv.lock changed | |
| id: uv-lock-changed | |
| continue-on-error: true | |
| if: steps.cache-uv-lock.outputs.cache-hit == 'true' || steps.cache-uv-lock.outputs.cache-hit == 'false' | |
| run: | | |
| uv lock --check | |
| - name: Lock dependencies | |
| if: steps.uv-lock-changed.outcome == 'failure' || steps.cache-uv-lock.outputs.cache-hit != 'true' && steps.cache-uv-lock.outputs.cache-hit != 'false' | |
| id: lock-uv-deps | |
| env: | |
| UV_LOCKED: 0 | |
| run: uv lock --refresh | |
| - uses: actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 | |
| if: steps.lock-uv-deps.outcome == 'success' | |
| name: upload-uv-lock | |
| with: | |
| key: uv-lock-resolved-${{ env.UV_RESOLUTION }}-${{ hashFiles('uv.lock') }} | |
| path: uv.lock | |
| enableCrossOsArchive: true | |
| # Used to determine which python versions to test against. | |
| # noxfile.py is the source of truth, which in turn draws from | |
| # pyproject.toml's `project.requires-python` and `project.classifiers`. | |
| python-versions: | |
| name: Export nox sessions | |
| runs-on: ubuntu-latest | |
| outputs: | |
| min-python: ${{ steps.set-matrix.outputs.min-python }} | |
| docs: ${{ steps.set-matrix.outputs.docs }} | |
| libcst: ${{ steps.set-matrix.outputs.libcst }} | |
| pyright-sessions: ${{ steps.set-matrix.outputs.pyright-sessions }} | |
| test-sessions: ${{ steps.set-matrix.outputs.test-sessions }} | |
| steps: | |
| - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: Set up environment | |
| uses: ./.github/actions/setup-env | |
| with: | |
| use-cached-uv-lock: 'false' # we don't need the lock here | |
| - name: Determine Python versions to test and lint against | |
| id: set-matrix | |
| # raw values (without a list) need the raw flag in order to not print quotes | |
| # lists do not need the raw flag, as we parse them with fromJSON() later on | |
| run: | | |
| echo min-python=$(nox -s test --list --json | jq -rc '[.[].python][0]') | tee --append $GITHUB_OUTPUT | |
| echo docs=$(nox -s docs --list --json | jq -rc '.[].python') | tee --append $GITHUB_OUTPUT | |
| echo libcst=$(nox -s codemod --list --json | jq -rc '[.[].python][0]') | tee --append $GITHUB_OUTPUT | |
| echo test-sessions=$(nox -s test --list --json | jq -c '[.[] | { python: .python, name: .session, extras: .call_spec.execution_group.extras, experimental: (.call_spec.execution_group.experimental == true) }]') | tee --append $GITHUB_OUTPUT | |
| echo pyright-sessions=$(nox -s pyright --list --json | jq -c '[.[] | {python: .python, name: .session, paths: .call_spec.execution_group.pyright_paths, experimental: (.call_spec.execution_group.experimental == true) }]') | tee --append $GITHUB_OUTPUT | |
| lint: | |
| name: Run pre-commit hooks | |
| runs-on: ubuntu-latest | |
| env: | |
| RUFF_OUTPUT_FORMAT: github | |
| steps: | |
| - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: Cache pip cache | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 | |
| with: | |
| key: ${{ runner.os }}-prek-pip-${{ hashFiles('**/pyproject.toml') }} | |
| path: ~/.cache/pip | |
| lookup-only: true | |
| - name: Run prek | |
| id: prek | |
| uses: j178/prek-action@91fd7d7cf70ae1dee9f4f44e7dfa5d1073fe6623 # v1.0.11 | |
| # given the interoperability and the nature of prek, we stay unpinned for now | |
| # note that this action by default uses the latest version of prek | |
| # this is exactly how the pre-commit action worked, and we never had any issues | |
| docs: | |
| name: Build documentation | |
| # unlike the other workflows, we explicitly use the same version as | |
| # readthedocs (see .readthedocs.yml) here for consistency | |
| runs-on: ubuntu-24.04 | |
| needs: | |
| - python-versions | |
| - lock-dependencies | |
| - lint | |
| steps: | |
| - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 | |
| with: | |
| fetch-depth: '0' | |
| persist-credentials: false | |
| - name: Set up environment | |
| id: setup-env | |
| uses: ./.github/actions/setup-env | |
| with: | |
| python-version: ${{ needs.python-versions.outputs.docs }} | |
| - name: Run sphinx-build | |
| run: nox -s docs -- --keep-going -W -w $GITHUB_STEP_SUMMARY | |
| typing: | |
| name: ${{matrix.session.name}} | |
| runs-on: ubuntu-latest | |
| needs: | |
| - python-versions | |
| - lock-dependencies | |
| - lint | |
| strategy: | |
| matrix: | |
| session: ${{ fromJson(needs.python-versions.outputs.pyright-sessions) }} | |
| fail-fast: false | |
| continue-on-error: ${{ matrix.session.experimental }} | |
| steps: | |
| - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: Set up environment | |
| id: setup-env | |
| uses: ./.github/actions/setup-env | |
| with: | |
| python-version: ${{ matrix.session.python }} | |
| - name: Add .venv/bin to PATH | |
| id: venv-bin | |
| run: | | |
| uv venv .venv | |
| dirname "$(uv python find)" >> $GITHUB_PATH | |
| echo python="$(uv python find)" >> $GITHUB_OUTPUT | |
| - name: Install dependencies | |
| # `--no-venv` to install in the main pdm venv instead of nox's pyright-specific one | |
| # because nox uses pdm internally to install, this means that the venv that is used is | |
| # the one that pdm would create in project: `.venv` | |
| # python is NOT forced here because the session name is explicit | |
| env: | |
| NOXSESSION: ${{ matrix.session.name }} | |
| NOX_DEFAULT_VENV_BACKEND: "none" | |
| ## needed to install specific dependencies | |
| ## used internally when nox calls pip to install a dependency in the venv | |
| PIP_PYTHON: ${{ steps.venv-bin.outputs.python }} | |
| run: | | |
| nox --install-only | |
| - name: Run pyright (Linux) | |
| uses: jakebailey/pyright-action@6cabc0f01c4994be48fd45cd9dbacdd6e1ee6e5e # v2.3.3 | |
| id: pyright-linux | |
| with: | |
| version: PATH | |
| python-version: ${{ steps.setup-env.outputs.python-version }} | |
| python-platform: "Linux" | |
| annotate: ${{ matrix.session.python == needs.python-versions.outputs.min-python }} # only add comments for one version | |
| warnings: true | |
| extra-args: ${{join(matrix.session.paths, ' ')}} | |
| - name: Run pyright (Windows) | |
| uses: jakebailey/pyright-action@6cabc0f01c4994be48fd45cd9dbacdd6e1ee6e5e # v2.3.3 | |
| if: always() && (steps.pyright-linux.outcome == 'success' || steps.pyright-linux.outcome == 'failure') | |
| with: | |
| version: PATH | |
| python-version: ${{ steps.setup-env.outputs.python-version }} | |
| python-platform: "Windows" | |
| annotate: false # only add comments for one platform (see above) | |
| warnings: true | |
| extra-args: ${{join(matrix.session.paths, ' ')}} | |
| misc: | |
| name: Check slots and build | |
| runs-on: ubuntu-latest | |
| needs: | |
| - python-versions | |
| - lock-dependencies | |
| - lint | |
| steps: | |
| - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 | |
| with: | |
| fetch-depth: '0' | |
| persist-credentials: false | |
| - name: Set up environment | |
| id: setup | |
| uses: ./.github/actions/setup-env | |
| with: | |
| python-version: ${{ needs.python-versions.outputs.min-python }} | |
| - name: Run misc checks | |
| run: | | |
| nox --tags misc | |
| - name: List built files | |
| run: | | |
| ls -la dist/ | |
| - name: Check README.md renders properly on PyPI | |
| run: | | |
| uvx twine~=6.1 check --strict dist/* | |
| codemod: | |
| name: LibCST codemods | |
| runs-on: ubuntu-latest | |
| needs: | |
| - python-versions | |
| - lock-dependencies | |
| - lint | |
| steps: | |
| - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: Set up environment | |
| id: setup | |
| uses: ./.github/actions/setup-env | |
| with: | |
| python-version: ${{ needs.python-versions.outputs.libcst }} | |
| # run the libcst parsers and check for changes | |
| - name: libcst codemod | |
| run: | | |
| nox -s codemod -- run-all | |
| - name: Check for changes by LibCST | |
| run: | | |
| if [ -n "$(git status --porcelain)" ]; then | |
| echo "::error::Please run 'nox -s codemod -- run-all' locally and commit the changes." >&2; | |
| echo "$GITHUB_STEP_SUMMARY_HEADER" | sed "s/#name#/LibCST Codemod/" >> $GITHUB_STEP_SUMMARY | |
| echo "The libcst codemod made changes to the codebase. Please run 'uv run nox -s codemod -- run-all' locally and commit the changes." >> $GITHUB_STEP_SUMMARY | |
| echo "::group::git diff" | |
| git diff |& tee -a $GITHUB_STEP_SUMMARY | |
| echo "::endgroup::" | |
| echo "$GITHUB_STEP_SUMMARY_FOOTER" >> $GITHUB_STEP_SUMMARY | |
| exit 1; | |
| else | |
| exit 0; | |
| fi | |
| test: | |
| name: ${{ matrix.session.name }} on ${{ matrix.os }} | |
| runs-on: ${{ matrix.os }} | |
| needs: | |
| - python-versions | |
| - lock-dependencies | |
| - lint | |
| strategy: | |
| matrix: | |
| os: ["ubuntu-latest", "macos-latest", "windows-latest"] | |
| session: ${{ fromJson(needs.python-versions.outputs.test-sessions) }} | |
| fail-fast: true | |
| continue-on-error: ${{ matrix.session.experimental }} | |
| env: | |
| NOXSESSION: ${{ matrix.session.name }} | |
| steps: | |
| - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: Set up environment | |
| id: setup-env | |
| uses: ./.github/actions/setup-env | |
| with: | |
| python-version: ${{ matrix.session.python }} | |
| - name: Install nox environment | |
| run: | | |
| nox --install-only | |
| - name: Run pytest | |
| id: run_tests | |
| # use non-utc timezone, to test time/date-dependent features properly | |
| env: | |
| TZ: "America/New_York" | |
| run: | | |
| echo "$GITHUB_STEP_SUMMARY_HEADER" | sed "s/#name#/Test Summary/" >> $GITHUB_STEP_SUMMARY | |
| nox --no-install -- --color=no --cov-report= | tee -a $GITHUB_STEP_SUMMARY | |
| echo "$GITHUB_STEP_SUMMARY_FOOTER" >> $GITHUB_STEP_SUMMARY | |
| - name: Print coverage output | |
| if: always() && (steps.run_tests.outcome == 'success' || steps.run_tests.outcome == 'failure') | |
| env: | |
| UV_NO_SYNC: 0 | |
| NOXSESSION: coverage | |
| run: | | |
| echo "$GITHUB_STEP_SUMMARY_HEADER" | sed "s/#name#/Coverage Summary/" >> $GITHUB_STEP_SUMMARY | |
| nox -- report | tee -a $GITHUB_STEP_SUMMARY | |
| echo "$GITHUB_STEP_SUMMARY_FOOTER" >> $GITHUB_STEP_SUMMARY | |
| # thanks to aiohttp for this part of the workflow | |
| check: # This job does nothing and is only used for the branch protection | |
| name: Check CI passed | |
| if: always() | |
| needs: | |
| - lint | |
| - docs | |
| - typing | |
| - misc | |
| - codemod | |
| - test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Decide whether the needed jobs succeeded or failed | |
| uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2 | |
| with: | |
| jobs: ${{ toJSON(needs) }} |