fold tuple * and + on fixed-length literal tuples
#231
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
| name: CI | |
| permissions: {} | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref_name }}-${{ github.event.pull_request.number || github.sha }} | |
| cancel-in-progress: true | |
| defaults: | |
| run: | |
| shell: bash | |
| env: | |
| CARGO_INCREMENTAL: 0 | |
| CARGO_NET_RETRY: 10 | |
| CARGO_TERM_COLOR: always | |
| RUSTUP_MAX_RETRIES: 10 | |
| PACKAGE_NAME: ruff | |
| PYTHON_VERSION: "3.14" | |
| NEXTEST_PROFILE: ci | |
| jobs: | |
| determine_changes: | |
| name: "Determine changes" | |
| runs-on: ubuntu-latest | |
| outputs: | |
| # Flag that is raised when any code that affects parser is changed | |
| parser: ${{ steps.check_parser.outputs.changed }} | |
| # Flag that is raised when any code that affects linter is changed | |
| linter: ${{ steps.check_linter.outputs.changed }} | |
| # Flag that is raised when any code that affects formatter is changed | |
| formatter: ${{ steps.check_formatter.outputs.changed }} | |
| # Flag that is raised when any code is changed | |
| # This is superset of the linter and formatter | |
| code: ${{ steps.check_code.outputs.changed }} | |
| # Flag that is raised when any code that affects the fuzzer is changed | |
| fuzz: ${{ steps.check_fuzzer.outputs.changed }} | |
| # Flag that is set to "true" when code related to ty changes. | |
| ty: ${{ steps.check_ty.outputs.changed }} | |
| # Flag that is set to "true" when code related to the py-fuzzer folder changes. | |
| py-fuzzer: ${{ steps.check_py_fuzzer.outputs.changed }} | |
| # Flag that is set to "true" when code related to the playground changes. | |
| playground: ${{ steps.check_playground.outputs.changed }} | |
| # Flag that is set to "true" when code related to the benchmarks changes. | |
| benchmarks: ${{ steps.check_benchmarks.outputs.changed }} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| # Faster to do this separately than to use `fetch-depth: 0` with `actions/checkout` | |
| - name: Fetch full history without tags | |
| run: git fetch --no-tags --filter=blob:none --unshallow origin | |
| - name: Determine merge base | |
| id: merge_base | |
| env: | |
| BASE_REF: ${{ github.event.pull_request.base.ref || 'main' }} | |
| run: | | |
| sha=$(git merge-base HEAD "origin/${BASE_REF}") | |
| echo "sha=${sha}" >> "$GITHUB_OUTPUT" | |
| - name: Check if the parser code changed | |
| id: check_parser | |
| env: | |
| MERGE_BASE: ${{ steps.merge_base.outputs.sha }} | |
| run: | | |
| if git diff --quiet "${MERGE_BASE}...HEAD" -- \ | |
| ':Cargo.toml' \ | |
| ':Cargo.lock' \ | |
| ':rust-toolchain.toml' \ | |
| ':cargo/config.toml' \ | |
| ':crates/ruff_python_trivia/**' \ | |
| ':crates/ruff_source_file/**' \ | |
| ':crates/ruff_text_size/**' \ | |
| ':crates/ruff_python_ast/**' \ | |
| ':crates/ruff_python_parser/**' \ | |
| ':.github/workflows/ci.yaml' \ | |
| ; then | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Check if the linter code changed | |
| id: check_linter | |
| env: | |
| MERGE_BASE: ${{ steps.merge_base.outputs.sha }} | |
| run: | | |
| if git diff --quiet "${MERGE_BASE}...HEAD" -- ':Cargo.toml' \ | |
| ':Cargo.lock' \ | |
| ':rust-toolchain.toml' \ | |
| ':cargo/config.toml' \ | |
| ':crates/**' \ | |
| ':!crates/ty*/**' \ | |
| ':!crates/ruff_python_formatter/**' \ | |
| ':!crates/ruff_formatter/**' \ | |
| ':!crates/ruff_dev/**' \ | |
| ':!crates/ruff_benchmark/**' \ | |
| ':scripts/*' \ | |
| ':python/**' \ | |
| ':.github/workflows/ci.yaml' \ | |
| ; then | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Check if the formatter code changed | |
| id: check_formatter | |
| env: | |
| MERGE_BASE: ${{ steps.merge_base.outputs.sha }} | |
| run: | | |
| if git diff --quiet "${MERGE_BASE}...HEAD" -- ':Cargo.toml' \ | |
| ':Cargo.lock' \ | |
| ':rust-toolchain.toml' \ | |
| ':cargo/config.toml' \ | |
| ':crates/ruff_python_formatter/**' \ | |
| ':crates/ruff_formatter/**' \ | |
| ':crates/ruff_python_trivia/**' \ | |
| ':crates/ruff_python_ast/**' \ | |
| ':crates/ruff_source_file/**' \ | |
| ':crates/ruff_python_index/**' \ | |
| ':crates/ruff_python_index/**' \ | |
| ':crates/ruff_text_size/**' \ | |
| ':crates/ruff_python_parser/**' \ | |
| ':scripts/*' \ | |
| ':python/**' \ | |
| ':.github/workflows/ci.yaml' \ | |
| ; then | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Check if the fuzzer code changed | |
| id: check_fuzzer | |
| env: | |
| MERGE_BASE: ${{ steps.merge_base.outputs.sha }} | |
| run: | | |
| if git diff --quiet "${MERGE_BASE}...HEAD" -- ':Cargo.toml' \ | |
| ':Cargo.lock' \ | |
| ':rust-toolchain.toml' \ | |
| ':cargo/config.toml' \ | |
| ':fuzz/fuzz_targets/**' \ | |
| ':.github/workflows/ci.yaml' \ | |
| ; then | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Check if the py-fuzzer code changed | |
| id: check_py_fuzzer | |
| env: | |
| MERGE_BASE: ${{ steps.merge_base.outputs.sha }} | |
| run: | | |
| if git diff --quiet "${MERGE_BASE}...HEAD" -- 'python/py-fuzzer/**' \ | |
| ; then | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Check if there was any code related change | |
| id: check_code | |
| env: | |
| MERGE_BASE: ${{ steps.merge_base.outputs.sha }} | |
| run: | | |
| # NOTE: Do not exclude all Markdown files here, but rather use | |
| # specific exclude patterns like 'docs/**'), because tests for | |
| # 'ty' are written in Markdown. | |
| if git diff --quiet "${MERGE_BASE}...HEAD" -- \ | |
| ':!docs/**' \ | |
| ':!assets/**' \ | |
| ; then | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Check if there was any playground related change | |
| id: check_playground | |
| env: | |
| MERGE_BASE: ${{ steps.merge_base.outputs.sha }} | |
| run: | | |
| if git diff --quiet "${MERGE_BASE}...HEAD" -- \ | |
| ':playground/**' \ | |
| ; then | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Check if the ty code changed | |
| id: check_ty | |
| env: | |
| MERGE_BASE: ${{ steps.merge_base.outputs.sha }} | |
| run: | | |
| if git diff --quiet "${MERGE_BASE}...HEAD" -- \ | |
| ':Cargo.toml' \ | |
| ':Cargo.lock' \ | |
| ':rust-toolchain.toml' \ | |
| ':cargo/config.toml' \ | |
| ':crates/ty*/**' \ | |
| ':crates/ruff_db/**' \ | |
| ':crates/ruff_annotate_snippets/**' \ | |
| ':crates/ruff_python_ast/**' \ | |
| ':crates/ruff_python_parser/**' \ | |
| ':crates/ruff_python_trivia/**' \ | |
| ':crates/ruff_source_file/**' \ | |
| ':crates/ruff_text_size/**' \ | |
| ':.github/workflows/ci.yaml' \ | |
| ; then | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Check if the benchmark code changed | |
| id: check_benchmarks | |
| env: | |
| MERGE_BASE: ${{ steps.merge_base.outputs.sha }} | |
| run: | | |
| if git diff --quiet "${MERGE_BASE}...HEAD" -- \ | |
| ':Cargo.toml' \ | |
| ':Cargo.lock' \ | |
| ':rust-toolchain.toml' \ | |
| ':cargo/config.toml' \ | |
| ':crates/ruff_benchmark/**' \ | |
| ':.github/workflows/ci.yaml' \ | |
| ; then | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| fi | |
| cargo-fmt: | |
| name: "cargo fmt" | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: "Install Rust toolchain" | |
| run: rustup component add rustfmt | |
| - run: cargo fmt --all --check | |
| shellcheck: | |
| name: "shellcheck" | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0 | |
| with: | |
| go-version: "1.26.4" | |
| - name: "Run ShellCheck" | |
| env: | |
| GOSUMDB: sum.golang.org | |
| run: | | |
| files=() | |
| while IFS= read -r -d '' file; do | |
| files+=("${file}") | |
| done < <(git ls-files -z '*.sh') | |
| if ((${#files[@]} == 0)); then | |
| exit 0 | |
| fi | |
| go run github.com/wasilibs/go-shellcheck/cmd/shellcheck@v0.11.1 "${files[@]}" | |
| cargo-clippy: | |
| name: "cargo clippy" | |
| runs-on: ubuntu-latest | |
| needs: determine_changes | |
| if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }} | |
| timeout-minutes: 20 | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: "Install Rust toolchain" | |
| run: | | |
| rustup component add clippy | |
| rustup target add wasm32-unknown-unknown | |
| - name: "Clippy" | |
| run: cargo clippy --workspace --all-targets --all-features --locked -- -D warnings | |
| - name: "Clippy (wasm)" | |
| run: cargo clippy -p ruff_wasm -p ty_wasm --target wasm32-unknown-unknown --all-features --locked -- -D warnings | |
| # upstream's `cargo-publish-dry-run` is dropped: the fork keeps ruff/ty crate | |
| # versions in lock-step with astral's published crates.io versions but modifies | |
| # their apis, so `cargo publish --dry-run` pulls the real published crate for a | |
| # transitive dep and fails on the api skew. the fork publishes only the | |
| # `basedpython` wheel to pypi, never these crates to crates.io | |
| cargo-test-linux: | |
| name: "cargo test (linux)" | |
| runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-16' || 'ubuntu-latest' }} | |
| needs: determine_changes | |
| if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }} | |
| # the fork's `ubuntu-latest` runner is far slower than astral's 16-core depot | |
| # runner, so the full suite overruns the depot-tuned 20-minute budget | |
| timeout-minutes: 45 | |
| env: | |
| # Line-tables-only debug info: faster builds, backtraces still work. | |
| CARGO_PROFILE_DEV_DEBUG: line-tables-only | |
| # Enable mdtests that require external dependencies. These `uv`-install real | |
| # packages and type-check against them — platform-independent behaviour, so | |
| # linux coverage suffices. Keeping them off the windows/macos jobs avoids the | |
| # fork's slow runners blowing the nextest deadlock timeout on heavy stubs | |
| # (django-stubs type-checks in ~8s locally but >180s unoptimised on the fork | |
| # windows runner's slow file I/O). | |
| MDTEST_EXTERNAL: "1" | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| shared-key: ruff-linux-debug | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: "Install Rust toolchain" | |
| run: rustup show | |
| - name: "Install mold" | |
| uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1 | |
| - name: "Install cargo nextest and insta" | |
| uses: taiki-e/install-action@16b05812d776ae1dfaabc8277e421fb6d2506419 # v2.82.7 | |
| with: | |
| tool: | | |
| cargo-nextest | |
| cargo-insta | |
| - name: "Install uv" | |
| uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1 | |
| with: | |
| version: "0.11.28" | |
| enable-cache: "true" | |
| - name: ty mdtests (GitHub annotations) | |
| if: ${{ needs.determine_changes.outputs.ty == 'true' }} | |
| env: | |
| NO_COLOR: 1 | |
| MDTEST_GITHUB_ANNOTATIONS_FORMAT: 1 | |
| # Ignore errors if this step fails; we want to continue to later steps in the workflow anyway. | |
| # This step is just to get nice GitHub annotations on the PR diff in the files-changed tab. | |
| run: cargo test -p ty_python_semantic --test mdtest || true | |
| - name: "Run tests" | |
| run: cargo insta test --all-features --unreferenced reject --test-runner nextest --disable-nextest-doctest | |
| - name: "Run doctests" | |
| run: cargo test --doc --all-features | |
| - name: Dogfood ty on py-fuzzer | |
| run: uv run --project=./python/py-fuzzer cargo run -p ty check --project=./python/py-fuzzer | |
| - name: Dogfood ty on the scripts directory | |
| run: uv run --project=./scripts cargo run -p ty check --project=./scripts | |
| - name: Dogfood ty on ty_benchmark | |
| run: uv run --project=./scripts/ty_benchmark cargo run -p ty check --project=./scripts/ty_benchmark | |
| # Check for broken links in the documentation. | |
| - run: cargo doc --all --no-deps | |
| env: | |
| RUSTDOCFLAGS: "-D warnings" | |
| # Use --document-private-items so that all our doc comments are kept in | |
| # sync, not just public items. Eventually we should do this for all | |
| # crates; for now add crates here as they are warning-clean to prevent | |
| # regression. | |
| - run: cargo doc --no-deps -p ty_python_semantic -p ty_python_core -p ty_module_resolver -p ty_site_packages -p ty_combine -p ty_project -p ty_ide -p ty_wasm -p ty_vendored -p ty_static -p ty -p ty_test -p ruff_db -p ruff_python_formatter --document-private-items | |
| env: | |
| # Setting RUSTDOCFLAGS because `cargo doc --check` isn't yet implemented (https://github.com/rust-lang/cargo/issues/10025). | |
| RUSTDOCFLAGS: "-D warnings" | |
| cargo-test-linux-release: | |
| name: "cargo test (linux, release)" | |
| # release-mode build + test times out on standard github runners, so this | |
| # needs depot's larger runners. gated to astral-sh/ruff so it skips on the | |
| # fork; adopt depot (see ROADMAP) then flip the predicate back to | |
| # 'KotlinIsland/basedpython' to re-enable | |
| runs-on: depot-ubuntu-22.04-16 | |
| needs: determine_changes | |
| if: | | |
| github.repository == 'astral-sh/ruff' && | |
| !contains(github.event.pull_request.labels.*.name, 'no-test') && | |
| (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') | |
| timeout-minutes: 20 | |
| env: | |
| # Line-tables-only debug info: faster builds, backtraces still work. | |
| CARGO_PROFILE_PROFILING_DEBUG: line-tables-only | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: "Install Rust toolchain" | |
| run: rustup show | |
| - name: "Install mold" | |
| uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1 | |
| - name: "Install cargo nextest" | |
| uses: taiki-e/install-action@16b05812d776ae1dfaabc8277e421fb6d2506419 # v2.82.7 | |
| with: | |
| tool: cargo-nextest | |
| - name: "Install uv" | |
| uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1 | |
| with: | |
| version: "0.11.28" | |
| enable-cache: "true" | |
| - name: "Run tests" | |
| run: cargo nextest run --cargo-profile profiling --all-features | |
| - name: "Run doctests" | |
| run: cargo test --doc --profile profiling --all-features | |
| cargo-test-other: | |
| strategy: | |
| matrix: | |
| platform: | |
| - ${{ github.repository == 'astral-sh/ruff' && 'depot-windows-2022-16' || 'windows-latest' }} | |
| - ${{ github.repository == 'astral-sh/ruff' && 'depot-macos-15' || 'macos-latest' }} | |
| name: "cargo test (${{ matrix.platform }})" | |
| runs-on: ${{ matrix.platform }} | |
| needs: determine_changes | |
| if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }} | |
| # the fork's `windows-latest`/`macos-latest` runners are slower than astral's | |
| # depot runners, so the full suite overruns the depot-tuned 20-minute budget | |
| timeout-minutes: 45 | |
| env: | |
| # Line-tables-only debug info: faster builds, backtraces still work. | |
| CARGO_PROFILE_DEV_DEBUG: line-tables-only | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| # Fix for https://github.com/Swatinem/rust-cache/issues/341 | |
| cache-bin: "false" | |
| - name: "Install Rust toolchain" | |
| run: rustup show | |
| - name: "Install cargo nextest" | |
| uses: taiki-e/install-action@16b05812d776ae1dfaabc8277e421fb6d2506419 # v2.82.7 | |
| with: | |
| tool: cargo-nextest | |
| - name: "Install uv" | |
| uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1 | |
| with: | |
| version: "0.11.28" | |
| enable-cache: "true" | |
| - name: "Run tests" | |
| run: | | |
| cargo nextest run --all-features --profile ci | |
| cargo test --all-features --doc | |
| cargo-test-wasm: | |
| name: "cargo test (wasm)" | |
| runs-on: ubuntu-latest | |
| needs: determine_changes | |
| if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }} | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: "Install Rust toolchain" | |
| run: rustup target add wasm32-unknown-unknown | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: 24 | |
| cache: "npm" | |
| cache-dependency-path: playground/package-lock.json | |
| - uses: jetli/wasm-pack-action@0d096b08b4e5a7de8c28de67e11e945404e9eefa # v0.4.0 | |
| with: | |
| version: v0.13.1 | |
| - name: "Test ruff_wasm" | |
| run: | | |
| cd crates/ruff_wasm | |
| wasm-pack test --node | |
| - name: "Test ty_wasm" | |
| run: | | |
| cd crates/ty_wasm | |
| wasm-pack test --node | |
| cargo-build-msrv: | |
| name: "cargo build (msrv)" | |
| runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-latest-8' || 'ubuntu-latest' }} | |
| needs: determine_changes | |
| if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }} | |
| timeout-minutes: 20 | |
| env: | |
| # Line-tables-only debug info: faster builds, backtraces still work. | |
| CARGO_PROFILE_DEV_DEBUG: line-tables-only | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: SebRollen/toml-action@b1b3628f55fc3a28208d4203ada8b737e9687876 # v1.2.0 | |
| id: msrv | |
| with: | |
| file: "Cargo.toml" | |
| field: "workspace.package.rust-version" | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: "Install Rust toolchain" | |
| env: | |
| MSRV: ${{ steps.msrv.outputs.value }} | |
| run: rustup default "${MSRV}" | |
| - name: "Install mold" | |
| uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1 | |
| - name: "Build tests" | |
| env: | |
| MSRV: ${{ steps.msrv.outputs.value }} | |
| run: cargo "+${MSRV}" test --no-run --all-features | |
| # TODO: fork the fuzzer | |
| # cargo-fuzz-build: | |
| # name: "cargo fuzz build" | |
| # runs-on: ubuntu-latest | |
| # needs: determine_changes | |
| # if: ${{ github.ref == 'refs/heads/main' || needs.determine_changes.outputs.fuzz == 'true' || needs.determine_changes.outputs.code == 'true' }} | |
| # timeout-minutes: 10 | |
| # steps: | |
| # - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| # with: | |
| # persist-credentials: false | |
| # - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| # with: | |
| # workspaces: "fuzz -> target" | |
| # save-if: ${{ github.ref == 'refs/heads/main' }} | |
| # - name: "Install Rust toolchain" | |
| # run: rustup show | |
| # - name: "Install mold" | |
| # uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1 | |
| # - name: "Install cargo-binstall" | |
| # uses: cargo-bins/cargo-binstall@dc19f1e48450eefe5a29b8da6c6b00a87d730b37 # v1.18.1 | |
| # - name: "Install cargo-fuzz" | |
| # # Download the latest version from quick install and not the github releases because github releases only has MUSL targets. | |
| # run: cargo binstall cargo-fuzz --force --disable-strategies crate-meta-data --no-confirm | |
| # - run: cargo fuzz build -s none | |
| fuzz-parser: | |
| name: "fuzz parser" | |
| runs-on: ubuntu-latest | |
| needs: determine_changes | |
| if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.parser == 'true' || needs.determine_changes.outputs.py-fuzzer == 'true') }} | |
| timeout-minutes: 20 | |
| env: | |
| FORCE_COLOR: 1 | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1 | |
| with: | |
| version: "0.11.28" | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| shared-key: ruff-linux-debug | |
| save-if: false | |
| - name: "Install Rust toolchain" | |
| run: rustup show | |
| - name: "Install mold" | |
| uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1 | |
| - name: Build buff binary | |
| env: | |
| # Line-tables-only debug info: faster builds, backtraces still work. | |
| CARGO_PROFILE_DEV_DEBUG: line-tables-only | |
| # basedpython renames the `ruff` binary to `buff`. `--bin=ruff` below is | |
| # the py-fuzzer's tool-mode selector (an enum), not a binary name, so it | |
| # stays `ruff` | |
| run: cargo build --bin buff | |
| - name: Fuzz | |
| run: | | |
| ( | |
| uv run \ | |
| --python="${PYTHON_VERSION}" \ | |
| --project=./python/py-fuzzer \ | |
| --locked \ | |
| fuzz \ | |
| --test-executable=target/debug/buff \ | |
| --bin=ruff \ | |
| 0-500 | |
| ) | |
| scripts: | |
| name: "test scripts" | |
| runs-on: ubuntu-latest | |
| needs: determine_changes | |
| if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }} | |
| timeout-minutes: 5 | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1 | |
| with: | |
| version: "0.11.28" | |
| - name: "Install Rust toolchain" | |
| run: rustup component add rustfmt | |
| # Run all code generation scripts, and verify that the current output is | |
| # already checked into git. | |
| - run: python crates/ruff_python_ast/generate.py | |
| - run: python crates/ruff_python_formatter/generate.py | |
| - run: test -z "$(git status --porcelain)" | |
| # Verify that adding a plugin or rule produces clean code. | |
| - run: ./scripts/add_rule.py --name DoTheThing --prefix F --code 999 --linter pyflakes | |
| - run: cargo check | |
| - run: | | |
| ./scripts/add_plugin.py test --url https://pypi.org/project/-test/0.1.0/ --prefix TST | |
| ./scripts/add_rule.py --name FirstRule --prefix TST --code 001 --linter test | |
| - run: cargo check | |
| # Lint/format/type-check py-fuzzer | |
| # (dogfooding with ty is done in a separate job) | |
| - run: uv run --directory=./python/py-fuzzer mypy | |
| - run: uv run --directory=./python/py-fuzzer ruff format --check | |
| - run: uv run --directory=./python/py-fuzzer ruff check | |
| ecosystem: | |
| name: "ecosystem" | |
| runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-latest-8' || 'ubuntu-latest' }} | |
| needs: determine_changes | |
| # Only runs on pull requests, since that is the only we way we can find the base version for comparison. | |
| # Ecosystem check needs linter and/or formatter changes. | |
| if: | | |
| !contains(github.event.pull_request.labels.*.name, 'no-test') && github.event_name == 'pull_request' && | |
| ( | |
| needs.determine_changes.outputs.linter == 'true' || | |
| needs.determine_changes.outputs.formatter == 'true' | |
| ) | |
| # max (6h): the fork runs on slow `ubuntu-latest`, not astral's depot | |
| # runners, so the 70-project ecosystem check overruns a tighter budget | |
| timeout-minutes: 360 | |
| env: | |
| # Line-tables-only debug info: faster builds, backtraces still work. | |
| CARGO_PROFILE_DEV_DEBUG: line-tables-only | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| ref: ${{ github.event.pull_request.base.ref }} | |
| persist-credentials: false | |
| - uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| activate-environment: true | |
| version: "0.11.28" | |
| - name: "Install Rust toolchain" | |
| run: rustup show | |
| - name: "Install mold" | |
| uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1 | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| shared-key: ruff-linux-debug | |
| save-if: false | |
| - name: Build baseline version | |
| # basedpython renames the `ruff` binary to `buff` | |
| run: | | |
| cargo build --bin buff | |
| mv target/debug/buff target/debug/buff-baseline | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| clean: false | |
| - name: Build comparison version | |
| run: cargo build --bin buff | |
| - name: Install ruff-ecosystem | |
| run: | | |
| uv pip install ./python/ruff-ecosystem | |
| - name: Run `ruff check` stable ecosystem check | |
| if: ${{ needs.determine_changes.outputs.linter == 'true' }} | |
| run: | | |
| # Set pipefail to avoid hiding errors with tee | |
| set -eo pipefail | |
| ruff-ecosystem check ./target/debug/buff-baseline ./target/debug/buff --cache ./checkouts --output-format markdown | tee ecosystem-result-check-stable | |
| cat ecosystem-result-check-stable > "$GITHUB_STEP_SUMMARY" | |
| echo "### Linter (stable)" > ecosystem-result | |
| cat ecosystem-result-check-stable >> ecosystem-result | |
| echo "" >> ecosystem-result | |
| - name: Run `ruff check` preview ecosystem check | |
| if: ${{ needs.determine_changes.outputs.linter == 'true' }} | |
| run: | | |
| # Set pipefail to avoid hiding errors with tee | |
| set -eo pipefail | |
| ruff-ecosystem check ./target/debug/buff-baseline ./target/debug/buff --cache ./checkouts --output-format markdown --force-preview | tee ecosystem-result-check-preview | |
| cat ecosystem-result-check-preview > "$GITHUB_STEP_SUMMARY" | |
| echo "### Linter (preview)" >> ecosystem-result | |
| cat ecosystem-result-check-preview >> ecosystem-result | |
| echo "" >> ecosystem-result | |
| # `--max-parallelism 2`: the default (50) oversubscribes the fork's small | |
| # `ubuntu-latest` runner — dozens of concurrent multi-threaded `buff format` | |
| # walks plus git clone/reset churn make the parallel file walk intermittently | |
| # surface a transient `No such file or directory` on one large project (a | |
| # different one each run), which the "Fail on ecosystem errors" step turns | |
| # into a hard failure. astral's 32-core depot runner absorbs the load; ours | |
| # needs the concurrency capped. (format only — the read-only check runs are | |
| # unaffected.) | |
| - name: Run `ruff format` stable ecosystem check | |
| if: ${{ needs.determine_changes.outputs.formatter == 'true' }} | |
| run: | | |
| # Set pipefail to avoid hiding errors with tee | |
| set -eo pipefail | |
| ruff-ecosystem format ./target/debug/buff-baseline ./target/debug/buff --cache ./checkouts --output-format markdown --max-parallelism 2 | tee ecosystem-result-format-stable | |
| cat ecosystem-result-format-stable > "$GITHUB_STEP_SUMMARY" | |
| echo "### Formatter (stable)" >> ecosystem-result | |
| cat ecosystem-result-format-stable >> ecosystem-result | |
| echo "" >> ecosystem-result | |
| - name: Run `ruff format` preview ecosystem check | |
| if: ${{ needs.determine_changes.outputs.formatter == 'true' }} | |
| run: | | |
| # Set pipefail to avoid hiding errors with tee | |
| set -eo pipefail | |
| ruff-ecosystem format ./target/debug/buff-baseline ./target/debug/buff --cache ./checkouts --output-format markdown --force-preview --max-parallelism 2 | tee ecosystem-result-format-preview | |
| cat ecosystem-result-format-preview > "$GITHUB_STEP_SUMMARY" | |
| echo "### Formatter (preview)" >> ecosystem-result | |
| cat ecosystem-result-format-preview >> ecosystem-result | |
| echo "" >> ecosystem-result | |
| # NOTE: astral-sh-bot uses this artifact to post comments on PRs. | |
| # Make sure to update the bot if you rename the artifact. | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| name: Upload Results | |
| with: | |
| name: ecosystem-result | |
| path: ecosystem-result | |
| if-no-files-found: "error" | |
| - name: Fail on ecosystem errors | |
| run: | | |
| if ! grep -q "project error" ecosystem-result; then | |
| echo "no ecosystem project errors" | |
| exit 0 | |
| fi | |
| # a project error is only a `grep` hit in the bare step otherwise, so | |
| # the maintainer can't tell a transient fork-runner `No such file or | |
| # directory` (see the parallelism note above) from a real regression | |
| # without downloading the artifact. surface the errored projects and | |
| # their messages straight into the step log. | |
| projects=$(grep -oE '">[^<]+</a> \(error\)' ecosystem-result \ | |
| | sed -E 's/">([^<]+)<\/a> \(error\)/\1/' | paste -sd', ' -) | |
| echo "::group::ecosystem project errors (${projects:-unknown})" | |
| grep -F "project error" ecosystem-result || true | |
| echo | |
| # print each errored project's section: its `(error)` summary line | |
| # through the closing </details>, which brackets the message body | |
| awk ' | |
| /\(error\)<\/summary>/ { show = 1 } | |
| show { print } | |
| /<\/details>/ && show { show = 0; print "" } | |
| ' ecosystem-result | |
| echo "::endgroup::" | |
| echo "::error title=ecosystem project errors::${projects:-see log} — full report in the ecosystem-result artifact" | |
| exit 1 | |
| fuzz-ty: | |
| name: "Fuzz for new ty panics" | |
| runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-16' || 'ubuntu-latest' }} | |
| needs: | |
| - determine_changes | |
| # Only runs on pull requests, since that is the only we way we can find the base version for comparison. | |
| if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && github.event_name == 'pull_request' && (needs.determine_changes.outputs.ty == 'true' || needs.determine_changes.outputs.py-fuzzer == 'true') }} | |
| # the fork's ubuntu-latest runners are far slower than astral's depot, and | |
| # basedpython parser changes give the fuzzer more to explore, so allow the | |
| # full budget rather than cancelling a healthy run | |
| timeout-minutes: ${{ github.repository == 'astral-sh/ruff' && 10 || 360 }} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| # Faster to do this separately than to use `fetch-depth: 0` with `actions/checkout` | |
| - name: Fetch full history without tags | |
| run: git fetch --no-tags --filter=blob:none --unshallow origin | |
| - uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1 | |
| with: | |
| version: "0.11.28" | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: "Install Rust toolchain" | |
| run: rustup show | |
| - name: "Install mold" | |
| uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1 | |
| - name: Fuzz | |
| env: | |
| FORCE_COLOR: 1 | |
| # Line-tables-only debug info: faster builds, backtraces still work. | |
| CARGO_PROFILE_PROFILING_DEBUG: line-tables-only | |
| run: | | |
| # basedpython renames the `ty` binary to `by`. `--bin=ty` passed to | |
| # the py-fuzzer below is its tool-mode selector (an enum), not a | |
| # binary name, so it stays `ty` | |
| echo "new commit" | |
| git rev-list --format=%s --max-count=1 "$GITHUB_SHA" | |
| cargo build --profile=profiling --bin=by | |
| mv target/profiling/by ty-new | |
| MERGE_BASE="$(git merge-base "$GITHUB_SHA" "origin/$GITHUB_BASE_REF")" | |
| git checkout -b old_commit "$MERGE_BASE" | |
| echo "old commit (merge base)" | |
| git rev-list --format=%s --max-count=1 old_commit | |
| cargo build --profile=profiling --bin=by | |
| mv target/profiling/by ty-old | |
| ( | |
| uv run \ | |
| --python="${PYTHON_VERSION}" \ | |
| --project=./python/py-fuzzer \ | |
| --locked \ | |
| fuzz \ | |
| --test-executable=ty-new \ | |
| --baseline-executable=ty-old \ | |
| --only-new-bugs \ | |
| --bin=ty \ | |
| 0-1000 | |
| ) | |
| cargo-shear: | |
| name: "cargo shear" | |
| runs-on: ubuntu-latest | |
| needs: determine_changes | |
| if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: cargo-bins/cargo-binstall@732870f031d2fb36309d0deaf36abcc704a7be65 # v1.20.1 | |
| - run: cargo binstall --no-confirm cargo-shear@1.12.4 | |
| - run: cargo shear --deny-warnings | |
| ty-completion-evaluation: | |
| name: "ty completion evaluation" | |
| runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-16' || 'ubuntu-latest' }} | |
| needs: determine_changes | |
| if: ${{ needs.determine_changes.outputs.ty == 'true' || github.ref == 'refs/heads/main' }} | |
| env: | |
| # Line-tables-only debug info: faster builds, backtraces still work. | |
| CARGO_PROFILE_PROFILING_DEBUG: line-tables-only | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1 | |
| with: | |
| version: "0.11.28" | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: "Install Rust toolchain" | |
| run: rustup show | |
| - name: "Install mold" | |
| uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1 | |
| - name: "Run ty completion evaluation" | |
| run: cargo run --profile profiling --package ty_completion_eval -- all --threshold 0.4 --tasks /tmp/completion-evaluation-tasks.csv | |
| - name: "Ensure there are no changes" | |
| run: diff ./crates/ty_completion_eval/completion-evaluation-tasks.csv /tmp/completion-evaluation-tasks.csv | |
| python-package: | |
| name: "python package" | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') }} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| architecture: x64 | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: "Prep README.md" | |
| run: python scripts/transform_readme.py --target pypi | |
| - name: "Build wheels" | |
| uses: PyO3/maturin-action@e83996d129638aa358a18fbd1dfb82f0b0fb5d3b # v1.51.0 | |
| with: | |
| args: --out dist | |
| - name: "Test wheel" | |
| run: | | |
| pip install --force-reinstall --find-links dist "${PACKAGE_NAME}" | |
| ruff --help | |
| python -m ruff --help | |
| - name: "Remove wheels from cache" | |
| run: rm -rf target/wheels | |
| prek: | |
| name: "prek" | |
| runs-on: ${{ github.repository == 'astral-sh/ruff' && 'depot-ubuntu-22.04-16' || 'ubuntu-latest' }} | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1 | |
| with: | |
| version: "0.11.28" | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: 24 | |
| - name: "Cache prek" | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.cache/prek | |
| key: prek-${{ hashFiles('.pre-commit-config.yaml') }} | |
| - name: "Run prek" | |
| run: | | |
| echo '```console' > "$GITHUB_STEP_SUMMARY" | |
| # Enable color output for prek and remove it for the summary | |
| # Use --hook-stage=manual to enable slower hooks that are skipped by default | |
| SKIP=rustfmt uv run --only-group dev --locked prek run --all-files --show-diff-on-failure --color always --hook-stage manual | \ | |
| tee >(sed -E 's/\x1B\[([0-9]{1,2}(;[0-9]{1,2})*)?[mGK]//g' >> "$GITHUB_STEP_SUMMARY") >&1 | |
| exit_code="${PIPESTATUS[0]}" | |
| echo '```' >> "$GITHUB_STEP_SUMMARY" | |
| exit "$exit_code" | |
| docs: | |
| name: "mkdocs" | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: "Install Rust toolchain" | |
| run: rustup show | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1 | |
| with: | |
| python-version: 3.13 | |
| activate-environment: true | |
| version: "0.11.28" | |
| - name: "Install dependencies" | |
| run: uv pip install -r docs/requirements.txt | |
| - name: "Update README File" | |
| run: python scripts/transform_readme.py --target mkdocs | |
| - name: "Generate docs" | |
| run: python scripts/generate_mkdocs.py | |
| - name: "Check docs formatting" | |
| run: python scripts/check_docs_formatted.py | |
| - name: "Build docs" | |
| run: mkdocs build --strict -f mkdocs.yml | |
| check-formatter-instability-and-black-similarity: | |
| name: "formatter instabilities and black similarity" | |
| runs-on: ubuntu-latest | |
| needs: determine_changes | |
| if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.formatter == 'true' || github.ref == 'refs/heads/main') }} | |
| timeout-minutes: 10 | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: "Install Rust toolchain" | |
| run: rustup show | |
| - name: "Run checks" | |
| run: scripts/formatter_ecosystem_checks.sh | |
| - name: "Github step summary" | |
| run: cat target/formatter-ecosystem/stats.txt > "$GITHUB_STEP_SUMMARY" | |
| - name: "Remove checkouts from cache" | |
| run: rm -r target/formatter-ecosystem | |
| # check-ruff-lsp: | |
| # name: "test ruff-lsp" | |
| # runs-on: ubuntu-latest | |
| # timeout-minutes: 5 | |
| # needs: determine_changes | |
| # if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-test') && (needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main') }} | |
| # env: | |
| # # Line-tables-only debug info: faster builds, backtraces still work. | |
| # CARGO_PROFILE_DEV_DEBUG: line-tables-only | |
| # steps: | |
| # - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| # name: "Checkout ruff source" | |
| # with: | |
| # persist-credentials: false | |
| # | |
| # - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| # with: | |
| # shared-key: ruff-linux-debug | |
| # save-if: false | |
| # | |
| # - name: "Install Rust toolchain" | |
| # run: rustup show | |
| # | |
| # - name: "Install mold" | |
| # uses: rui314/setup-mold@9c9c13bf4c3f1adef0cc596abc155580bcb04444 # v1 | |
| # | |
| # - name: Build Ruff binary | |
| # run: cargo build -p ruff --bin ruff | |
| # | |
| # - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| # name: "Checkout ruff-lsp source" | |
| # with: | |
| # persist-credentials: false | |
| # repository: "astral-sh/ruff-lsp" | |
| # path: ruff-lsp | |
| # | |
| # - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 | |
| # with: | |
| # # installation fails on 3.13 and newer | |
| # python-version: "3.12" | |
| # | |
| # - uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0 | |
| # | |
| # - name: Install ruff-lsp dependencies | |
| # run: | | |
| # cd ruff-lsp | |
| # uv venv | |
| # uv pip install --no-deps -r requirements.txt | |
| # uv pip install --no-deps -r requirements-dev.txt | |
| # | |
| # - name: Run ruff-lsp tests | |
| # run: | | |
| # # Setup development binary | |
| # export PATH="${PWD}/target/debug:${PATH}" | |
| # ruff version | |
| # | |
| # cd ruff-lsp | |
| # uv pip uninstall ruff | |
| # uv run --no-sync pytest | |
| check-playground: | |
| name: "check playground" | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| needs: | |
| - determine_changes | |
| if: ${{ (needs.determine_changes.outputs.playground == 'true') }} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - name: "Install Rust toolchain" | |
| run: rustup target add wasm32-unknown-unknown | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0 | |
| with: | |
| node-version: 24 | |
| cache: "npm" | |
| cache-dependency-path: playground/package-lock.json | |
| - uses: jetli/wasm-bindgen-action@20b33e20595891ab1a0ed73145d8a21fc96e7c29 # v0.2.0 | |
| - name: "Install Node dependencies" | |
| run: npm ci --ignore-scripts | |
| working-directory: playground | |
| - name: "Build playgrounds" | |
| run: npm run dev:wasm | |
| working-directory: playground | |
| - name: "Run TypeScript checks" | |
| run: npm run check | |
| working-directory: playground | |
| - name: "Check formatting" | |
| run: npm run fmt:check | |
| working-directory: playground | |
| benchmarks-instrumented-ruff: | |
| name: "benchmarks instrumented (ruff)" | |
| runs-on: ubuntu-24.04 | |
| needs: determine_changes | |
| # TODO(basedpython): enable benchmarks for the fork. requires: | |
| # 1. register KotlinIsland/basedpython at https://codspeed.io | |
| # (project must be created with OIDC auth enabled, or set the | |
| # CODSPEED_TOKEN repo secret and pass `token: ${{ secrets.CODSPEED_TOKEN }}` | |
| # to the CodSpeedHQ/action step below) | |
| # 2. flip the predicate below back to 'KotlinIsland/basedpython' | |
| # gated on astral-sh/ruff for now so the job skips on the fork; uploads | |
| # from KotlinIsland/basedpython otherwise fail OIDC auth with 401 | |
| if: | | |
| github.repository == 'astral-sh/ruff' && | |
| ( | |
| github.ref == 'refs/heads/main' || | |
| needs.determine_changes.outputs.formatter == 'true' || | |
| needs.determine_changes.outputs.linter == 'true' || | |
| needs.determine_changes.outputs.parser == 'true' || | |
| needs.determine_changes.outputs.benchmarks == 'true' | |
| ) | |
| timeout-minutes: 20 | |
| permissions: | |
| contents: read # required for actions/checkout | |
| id-token: write # required for OIDC authentication with CodSpeed | |
| steps: | |
| - name: "Checkout Branch" | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1 | |
| with: | |
| version: "0.11.28" | |
| - name: "Install Rust toolchain" | |
| run: rustup show | |
| - name: "Install codspeed" | |
| uses: taiki-e/install-action@16b05812d776ae1dfaabc8277e421fb6d2506419 # v2.82.7 | |
| with: | |
| tool: cargo-codspeed | |
| - name: "Build benchmarks" | |
| run: cargo codspeed build -m simulation -m memory --features "codspeed,ruff_instrumented" --profile profiling --no-default-features -p ruff_benchmark --bench formatter --bench lexer --bench linter --bench parser | |
| - name: "Run benchmarks" | |
| uses: CodSpeedHQ/action@a4a36bb07c0638b0b4ca52bf1f3dad1b4289e52f # v4.18.1 | |
| with: | |
| mode: "simulation,memory" | |
| run: cargo codspeed run | |
| benchmarks-instrumented-ty-build: | |
| name: "benchmarks instrumented ty (build)" | |
| runs-on: depot-ubuntu-24.04-4 | |
| needs: determine_changes | |
| # TODO(basedpython): see `benchmarks-instrumented-ruff` above for how to | |
| # enable benchmarks for the fork (register repo at codspeed.io, then flip | |
| # the predicate below back to 'KotlinIsland/basedpython') | |
| if: | | |
| github.repository == 'astral-sh/ruff' && | |
| ( | |
| github.ref == 'refs/heads/main' || | |
| needs.determine_changes.outputs.ty == 'true' || | |
| needs.determine_changes.outputs.benchmarks == 'true' | |
| ) | |
| timeout-minutes: 20 | |
| steps: | |
| - name: "Checkout Branch" | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: "Install Rust toolchain" | |
| run: rustup show | |
| - name: "Install codspeed" | |
| uses: taiki-e/install-action@16b05812d776ae1dfaabc8277e421fb6d2506419 # v2.82.7 | |
| with: | |
| tool: cargo-codspeed | |
| - name: "Build benchmarks" | |
| run: cargo codspeed build -m simulation -m memory --features "codspeed,module_resolution,ty_instrumented" --profile profiling --no-default-features -p ruff_benchmark --bench module_resolution --bench ty | |
| - name: "Upload benchmark binary" | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: benchmarks-instrumented-ty-binary | |
| compression-level: 1 | |
| path: target/codspeed | |
| if-no-files-found: "error" | |
| retention-days: 1 | |
| benchmarks-instrumented-ty-run: | |
| name: "benchmarks instrumented ty (${{ matrix.mode }}: ${{ matrix.name }})" | |
| runs-on: ubuntu-24.04 | |
| needs: benchmarks-instrumented-ty-build | |
| timeout-minutes: 20 | |
| permissions: | |
| contents: read # required for actions/checkout | |
| id-token: write # required for OIDC authentication with CodSpeed | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - name: micro | |
| target: ty | |
| filter: micro | |
| mode: simulation | |
| - name: micro | |
| target: ty | |
| filter: micro | |
| mode: memory | |
| - name: projects | |
| target: ty | |
| filter: "check_file|anyio|attrs|hydra|datetype" | |
| mode: simulation | |
| - name: projects | |
| target: ty | |
| filter: "check_file|anyio|attrs|hydra|datetype" | |
| mode: memory | |
| - name: module_resolution | |
| target: module_resolution | |
| filter: ty_module_resolver | |
| mode: simulation | |
| steps: | |
| - name: "Checkout Branch" | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1 | |
| with: | |
| version: "0.11.28" | |
| - name: "Install codspeed" | |
| uses: taiki-e/install-action@16b05812d776ae1dfaabc8277e421fb6d2506419 # v2.82.7 | |
| with: | |
| tool: cargo-codspeed | |
| - name: "Download benchmark binary" | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: benchmarks-instrumented-ty-binary | |
| path: target/codspeed | |
| - name: "Restore binary permissions" | |
| # codspeed keeps changing the paths to the executable, so we have to be a bit more flexible | |
| run: find target/codspeed -type f -exec chmod +x {} + | |
| - name: "Run benchmarks" | |
| uses: CodSpeedHQ/action@a4a36bb07c0638b0b4ca52bf1f3dad1b4289e52f # v4.18.1 | |
| with: | |
| mode: ${{ matrix.mode }} | |
| run: cargo codspeed run --bench "${{ matrix.target }}" "${{ matrix.filter }}" | |
| benchmarks-walltime-build: | |
| name: "benchmarks walltime (build)" | |
| # depot runners hardcoded here are fine since the job is upstream-only. | |
| runs-on: depot-ubuntu-22.04-arm-4 | |
| needs: determine_changes | |
| # TODO(basedpython): see `benchmarks-instrumented-ruff` above for how to | |
| # enable benchmarks for the fork (register repo at codspeed.io, then flip | |
| # the predicate below back to 'KotlinIsland/basedpython') | |
| if: | | |
| github.repository == 'astral-sh/ruff' && | |
| ( | |
| !contains(github.event.pull_request.labels.*.name, 'no-test') && | |
| ( | |
| needs.determine_changes.outputs.ty == 'true' || | |
| needs.determine_changes.outputs.benchmarks == 'true' || | |
| github.ref == 'refs/heads/main' | |
| ) | |
| ) | |
| timeout-minutes: 20 | |
| steps: | |
| - name: "Checkout Branch" | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 | |
| with: | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1 | |
| with: | |
| version: "0.11.28" | |
| - name: "Install Rust toolchain" | |
| run: rustup show | |
| - name: "Install codspeed" | |
| uses: taiki-e/install-action@16b05812d776ae1dfaabc8277e421fb6d2506419 # v2.82.7 | |
| with: | |
| tool: cargo-codspeed | |
| - name: "Build benchmarks" | |
| run: cargo codspeed build -m walltime --features "codspeed,ty_walltime" --profile profiling --no-default-features -p ruff_benchmark --bench ty_walltime | |
| - name: "Upload benchmark binary" | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: benchmarks-walltime-binary | |
| compression-level: 1 | |
| path: target/codspeed | |
| if-no-files-found: "error" | |
| retention-days: 1 | |
| benchmarks-walltime-run: | |
| name: "benchmarks walltime (${{ matrix.benchmark.name }})" | |
| runs-on: codspeed-macro | |
| needs: benchmarks-walltime-build | |
| timeout-minutes: 20 | |
| permissions: | |
| contents: read # required for actions/checkout | |
| id-token: write # required for OIDC authentication with CodSpeed | |
| strategy: | |
| matrix: | |
| benchmark: | |
| - name: sympy | |
| target: ty_walltime | |
| filter: sympy | |
| - name: "pandas|tanjun" | |
| target: ty_walltime | |
| filter: "pandas|tanjun" | |
| - name: "colour_science|static_frame" | |
| target: ty_walltime | |
| filter: "colour_science|static_frame" | |
| - name: "pydantic|freqtrade|multithreaded|altair" | |
| target: ty_walltime | |
| filter: "pydantic|freqtrade|multithreaded|altair" | |
| steps: | |
| - name: "Checkout Branch" | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| persist-credentials: false | |
| - uses: astral-sh/setup-uv@f98e06938123ccabd21905ea5d0069192241f9f1 # v8.3.1 | |
| with: | |
| version: "0.11.28" | |
| - name: "Install codspeed" | |
| uses: taiki-e/install-action@16b05812d776ae1dfaabc8277e421fb6d2506419 # v2.82.7 | |
| with: | |
| tool: cargo-codspeed | |
| - name: "Download benchmark binary" | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: benchmarks-walltime-binary | |
| path: target/codspeed | |
| - name: "Restore binary permissions" | |
| # codspeed keeps changing the paths to the executable, so we have to be a bit more flexible | |
| run: find target/codspeed -type f -exec chmod +x {} + | |
| - name: "Run benchmarks" | |
| uses: CodSpeedHQ/action@a4a36bb07c0638b0b4ca52bf1f3dad1b4289e52f # v4.18.1 | |
| env: | |
| # enabling walltime flamegraphs adds ~6 minutes to the CI time, and they don't | |
| # appear to provide much useful insight for our walltime benchmarks right now | |
| # (see https://github.com/astral-sh/ruff/pull/20419) | |
| CODSPEED_PERF_ENABLED: false | |
| with: | |
| mode: walltime | |
| run: cargo codspeed run --bench "${{ matrix.benchmark.target }}" -m walltime "${{ matrix.benchmark.filter }}" | |
| required-checks-passed: | |
| name: "all required checks passed" | |
| if: always() | |
| needs: | |
| - cargo-fmt | |
| - cargo-clippy | |
| - cargo-test-linux | |
| - cargo-test-wasm | |
| - cargo-build-msrv | |
| - shellcheck | |
| - scripts | |
| - prek | |
| - docs | |
| - python-package | |
| runs-on: ubuntu-slim | |
| steps: | |
| - name: "Check required jobs passed" | |
| run: | | |
| failing=$(echo "$NEEDS_JSON" | jq -r 'to_entries[] | select(.value.result != "success" and .value.result != "skipped") | "\(.key): \(.value.result)"') | |
| if [ -n "$failing" ]; then | |
| echo "$failing" | |
| exit 1 | |
| fi | |
| env: | |
| NEEDS_JSON: ${{ toJSON(needs) }} |