on: push: branches: [main, release] pull_request: types: [unlabeled, opened, synchronize, reopened] merge_group: workflow_dispatch: name: CI # Cancel previous workflows if they are the same workflow on same ref (branch/tags) # with the same event (push/pull_request) even they are in progress. # This setting will help reduce the number of duplicated workflows. concurrency: group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} cancel-in-progress: true env: CARGO_ARGS: --no-default-features --features stdlib,importlib,stdio,encodings,sqlite,ssl-rustls CARGO_ARGS_NO_SSL: --no-default-features --features stdlib,importlib,stdio,encodings,sqlite # Skip additional tests on Windows. They are checked on Linux and MacOS. # test_glob: many failing tests # test_io: many failing tests # test_os: many failing tests # test_pathlib: support.rmtree() failing # test_posixpath: OSError: (22, 'The filename, directory name, or volume label syntax is incorrect. (os error 123)') # test_venv: couple of failing tests WINDOWS_SKIPS: >- test_glob test_io test_os test_rlcompleter test_pathlib test_posixpath test_venv # PLATFORM_INDEPENDENT_TESTS are tests that do not depend on the underlying OS. They are currently # only run on Linux to speed up the CI. PLATFORM_INDEPENDENT_TESTS: >- test__colorize test_array test_asyncgen test_binop test_bisect test_bool test_bytes test_call test_class test_cmath test_collections test_complex test_contains test_copy test_dataclasses test_decimal test_decorators test_defaultdict test_deque test_dict test_dictcomps test_dictviews test_dis test_enumerate test_exception_variations test_float test_format test_fractions test_genericalias test_genericclass test_grammar test_range test_index test_int test_int_literal test_isinstance test_iter test_iterlen test_itertools test_json test_keyword test_keywordonlyarg test_list test_long test_longexp test_math test_operator test_ordered_dict test_pow test_raise test_richcmp test_scope test_set test_slice test_sort test_string test_string_literals test_strtod test_structseq test_subclassinit test_super test_syntax test_tuple test_types test_unary test_unpack test_weakref test_yield_from # Python version targeted by the CI. PYTHON_VERSION: "3.13.1" jobs: rust_tests: if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }} env: RUST_BACKTRACE: full name: Run rust tests runs-on: ${{ matrix.os }} timeout-minutes: ${{ contains(matrix.os, 'windows') && 45 || 35 }} strategy: matrix: os: [macos-latest, ubuntu-latest, windows-latest] fail-fast: false steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable with: components: clippy - uses: Swatinem/rust-cache@v2 - name: Set up the Windows environment shell: bash run: | git config --system core.longpaths true cargo install --target-dir=target -v cargo-vcpkg cargo vcpkg -v build if: runner.os == 'Windows' - name: Set up the Mac environment run: brew install autoconf automake libtool if: runner.os == 'macOS' - name: run clippy run: cargo clippy ${{ env.CARGO_ARGS }} --workspace --all-targets --exclude rustpython_wasm --exclude rustpython-compiler-source -- -Dwarnings - name: run rust tests run: cargo test --workspace --exclude rustpython_wasm --exclude rustpython-compiler-source --verbose --features threading ${{ env.CARGO_ARGS }} if: runner.os != 'macOS' - name: run rust tests run: cargo test --workspace --exclude rustpython_wasm --exclude rustpython-jit --exclude rustpython-compiler-source --verbose --features threading ${{ env.CARGO_ARGS }} if: runner.os == 'macOS' - name: check compilation without threading run: cargo check ${{ env.CARGO_ARGS }} - name: Test example projects run: cargo run --manifest-path example_projects/barebone/Cargo.toml cargo run --manifest-path example_projects/frozen_stdlib/Cargo.toml if: runner.os == 'Linux' - name: prepare AppleSilicon build uses: dtolnay/rust-toolchain@stable with: target: aarch64-apple-darwin if: runner.os == 'macOS' - name: Check compilation for Apple Silicon run: cargo check --target aarch64-apple-darwin if: runner.os == 'macOS' - name: prepare iOS build uses: dtolnay/rust-toolchain@stable with: target: aarch64-apple-ios if: runner.os == 'macOS' - name: Check compilation for iOS run: cargo check --target aarch64-apple-ios ${{ env.CARGO_ARGS_NO_SSL }} if: runner.os == 'macOS' exotic_targets: if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }} name: Ensure compilation on various targets runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable with: target: i686-unknown-linux-gnu - name: Install gcc-multilib and musl-tools run: sudo apt-get update && sudo apt-get install gcc-multilib musl-tools - name: Check compilation for x86 32bit run: cargo check --target i686-unknown-linux-gnu ${{ env.CARGO_ARGS_NO_SSL }} - uses: dtolnay/rust-toolchain@stable with: target: aarch64-linux-android - name: Check compilation for android run: cargo check --target aarch64-linux-android ${{ env.CARGO_ARGS_NO_SSL }} - uses: dtolnay/rust-toolchain@stable with: target: aarch64-unknown-linux-gnu - name: Install gcc-aarch64-linux-gnu run: sudo apt install gcc-aarch64-linux-gnu - name: Check compilation for aarch64 linux gnu run: cargo check --target aarch64-unknown-linux-gnu ${{ env.CARGO_ARGS_NO_SSL }} - uses: dtolnay/rust-toolchain@stable with: target: i686-unknown-linux-musl - name: Check compilation for musl run: cargo check --target i686-unknown-linux-musl ${{ env.CARGO_ARGS_NO_SSL }} - uses: dtolnay/rust-toolchain@stable with: target: x86_64-unknown-freebsd - name: Check compilation for freebsd run: cargo check --target x86_64-unknown-freebsd ${{ env.CARGO_ARGS_NO_SSL }} - uses: dtolnay/rust-toolchain@stable with: target: x86_64-unknown-freebsd - name: Check compilation for freeBSD run: cargo check --target x86_64-unknown-freebsd ${{ env.CARGO_ARGS_NO_SSL }} # - name: Prepare repository for redox compilation # run: bash scripts/redox/uncomment-cargo.sh # - name: Check compilation for Redox # uses: coolreader18/redoxer-action@v1 # with: # command: check # args: --ignore-rust-version snippets_cpython: if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }} env: RUST_BACKTRACE: full name: Run snippets and cpython tests runs-on: ${{ matrix.os }} timeout-minutes: ${{ contains(matrix.os, 'windows') && 45 || 35 }} strategy: matrix: os: [macos-latest, ubuntu-latest, windows-latest] fail-fast: false steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - uses: actions/setup-python@v6 with: python-version: ${{ env.PYTHON_VERSION }} - name: Set up the Windows environment shell: bash run: | git config --system core.longpaths true cargo install cargo-vcpkg cargo vcpkg build if: runner.os == 'Windows' - name: Set up the Mac environment run: brew install autoconf automake libtool openssl@3 if: runner.os == 'macOS' - name: build rustpython run: cargo build --release --verbose --features=threading ${{ env.CARGO_ARGS }} if: runner.os == 'macOS' - name: build rustpython run: cargo build --release --verbose --features=threading ${{ env.CARGO_ARGS }},jit if: runner.os != 'macOS' - uses: actions/setup-python@v6 with: python-version: ${{ env.PYTHON_VERSION }} - name: run snippets run: python -m pip install -r requirements.txt && pytest -v working-directory: ./extra_tests - if: runner.os == 'Linux' name: run cpython platform-independent tests run: target/release/rustpython -m test -j 1 -u all --slowest --fail-env-changed -v ${{ env.PLATFORM_INDEPENDENT_TESTS }} - if: runner.os == 'Linux' name: run cpython platform-dependent tests (Linux) run: target/release/rustpython -m test -j 1 -u all --slowest --fail-env-changed -v -x ${{ env.PLATFORM_INDEPENDENT_TESTS }} - if: runner.os == 'macOS' name: run cpython platform-dependent tests (MacOS) run: target/release/rustpython -m test -j 1 --slowest --fail-env-changed -v -x ${{ env.PLATFORM_INDEPENDENT_TESTS }} - if: runner.os == 'Windows' name: run cpython platform-dependent tests (windows partial - fixme) run: target/release/rustpython -m test -j 1 --slowest --fail-env-changed -v -x ${{ env.PLATFORM_INDEPENDENT_TESTS }} ${{ env.WINDOWS_SKIPS }} - if: runner.os != 'Windows' name: check that --install-pip succeeds run: | mkdir site-packages target/release/rustpython --install-pip ensurepip --user target/release/rustpython -m pip install six - if: runner.os != 'Windows' name: Check that ensurepip succeeds. run: | target/release/rustpython -m ensurepip target/release/rustpython -c "import pip" - if: runner.os != 'Windows' name: Check if pip inside venv is functional run: | target/release/rustpython -m venv testvenv testvenv/bin/rustpython -m pip install wheel - name: Check whats_left is not broken run: python -I whats_left.py lint: name: Check Rust code with clippy runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable with: components: clippy - name: run clippy on wasm run: cargo clippy --manifest-path=crates/wasm/Cargo.toml -- -Dwarnings - uses: actions/setup-python@v6 with: python-version: ${{ env.PYTHON_VERSION }} - name: install ruff run: python -m pip install ruff==0.11.8 - name: Ensure docs generate no warnings run: cargo doc - name: run ruff check run: ruff check --diff - name: run ruff format run: ruff format --check - name: install prettier run: yarn global add prettier && echo "$(yarn global bin)" >>$GITHUB_PATH - name: check wasm code with prettier # prettier doesn't handle ignore files very well: https://github.com/prettier/prettier/issues/8506 run: cd wasm && git ls-files -z | xargs -0 prettier --check -u # Keep cspell check as the last step. This is optional test. - name: install extra dictionaries run: npm install @cspell/dict-en_us @cspell/dict-cpp @cspell/dict-python @cspell/dict-rust @cspell/dict-win32 @cspell/dict-shell - name: spell checker uses: streetsidesoftware/cspell-action@v8 with: files: '**/*.rs' incremental_files_only: true miri: if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }} name: Run tests under miri runs-on: ubuntu-latest timeout-minutes: 30 env: NIGHTLY_CHANNEL: nightly steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ env.NIGHTLY_CHANNEL }} components: miri - uses: Swatinem/rust-cache@v2 - name: Run tests under miri run: cargo +${{ env.NIGHTLY_CHANNEL }} miri test -p rustpython-vm -- miri_test env: # miri-ignore-leaks because the type-object circular reference means that there will always be # a memory leak, at least until we have proper cyclic gc MIRIFLAGS: '-Zmiri-ignore-leaks' wasm: if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }} name: Check the WASM package and demo runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable - uses: Swatinem/rust-cache@v2 - name: install wasm-pack run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh - name: install geckodriver run: | wget https://github.com/mozilla/geckodriver/releases/download/v0.36.0/geckodriver-v0.36.0-linux64.tar.gz mkdir geckodriver tar -xzf geckodriver-v0.36.0-linux64.tar.gz -C geckodriver - uses: actions/setup-python@v6 with: python-version: ${{ env.PYTHON_VERSION }} - run: python -m pip install -r requirements.txt working-directory: ./wasm/tests - uses: actions/setup-node@v6 with: cache: "npm" cache-dependency-path: "wasm/demo/package-lock.json" - name: run test run: | export PATH=$PATH:`pwd`/../../geckodriver npm install npm run test env: NODE_OPTIONS: "--openssl-legacy-provider" working-directory: ./wasm/demo - uses: mwilliamson/setup-wabt-action@v3 with: { wabt-version: "1.0.36" } - name: check wasm32-unknown without js run: | cd example_projects/wasm32_without_js/rustpython-without-js cargo build cd .. if wasm-objdump -xj Import rustpython-without-js/target/wasm32-unknown-unknown/debug/rustpython_without_js.wasm; then echo "ERROR: wasm32-unknown module expects imports from the host environment" >&2 fi cargo run --release --manifest-path wasm-runtime/Cargo.toml rustpython-without-js/target/wasm32-unknown-unknown/debug/rustpython_without_js.wasm - name: build notebook demo if: github.ref == 'refs/heads/release' run: | npm install npm run dist mv dist ../demo/dist/notebook env: NODE_OPTIONS: "--openssl-legacy-provider" working-directory: ./wasm/notebook - name: Deploy demo to Github Pages if: success() && github.ref == 'refs/heads/release' uses: peaceiris/actions-gh-pages@v4 env: ACTIONS_DEPLOY_KEY: ${{ secrets.ACTIONS_DEMO_DEPLOY_KEY }} PUBLISH_DIR: ./wasm/demo/dist EXTERNAL_REPOSITORY: RustPython/demo PUBLISH_BRANCH: master wasm-wasi: if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }} name: Run snippets and cpython tests on wasm-wasi runs-on: ubuntu-latest timeout-minutes: 30 steps: - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable with: target: wasm32-wasip1 - uses: Swatinem/rust-cache@v2 - name: Setup Wasmer uses: wasmerio/setup-wasmer@v3 - name: Install clang run: sudo apt-get update && sudo apt-get install clang -y - name: build rustpython run: cargo build --release --target wasm32-wasip1 --features freeze-stdlib,stdlib --verbose - name: run snippets run: wasmer run --dir `pwd` target/wasm32-wasip1/release/rustpython.wasm -- `pwd`/extra_tests/snippets/stdlib_random.py - name: run cpython unittest run: wasmer run --dir `pwd` target/wasm32-wasip1/release/rustpython.wasm -- `pwd`/Lib/test/test_int.py