diff --git a/.github/bors.toml b/.github/bors.toml new file mode 100644 index 000000000..d6f8af7a6 --- /dev/null +++ b/.github/bors.toml @@ -0,0 +1,12 @@ +delete_merged_branches = true +required_approvals = 0 +use_codeowners = false +status = [ + # GitHub Actions + "conclusion", + # Cirrus CI + "Test (x86_64 FreeBSD)", + "Test (arm64 macOS)", + "Test (arm64 Linux)" +] +timeout_sec = 21600 \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8e3948cdc..63a1c23d0 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,7 +3,10 @@ name: Test on: push: branches: - - main + # for bors r+ + - staging + # for bors try + - trying pull_request: workflow_dispatch: @@ -12,12 +15,85 @@ concurrency: cancel-in-progress: true jobs: + generate-matrix: + name: Generate Matrix + runs-on: ubuntu-latest + outputs: + python-version: ${{ steps.generate-matrix.outputs.python-version }} + fail-fast: ${{ steps.generate-matrix.outputs.fail-fast }} + steps: + - uses: actions/setup-node@v2 + with: + node-version: 16 + - run: npm install js-yaml + - name: Generate matrix + id: generate-matrix + uses: actions/github-script@v6 + with: + script: | + const yaml = require('js-yaml') + const PYTHON_VERSIONS = yaml.load(process.env.PYTHON_VERSION) + + if (context.eventName == 'workflow_dispatch') { + // Run all of them on workflow dispatch + core.setOutput('python-version', PYTHON_VERSIONS) + core.setOutput('fail-fast', 'false') + } else if (context.eventName == 'push') { + const commitMessage = process.env.COMMIT_MESSAGE.trim() + const matches = commitMessage.match(/(Try|Merge) #([0-9]+):/) + if (matches) { + const prNumber = matches[2] + const { data: { labels: labels } } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber + }) + const labelNames = labels.map(label => label.name) + if (labelNames.includes('CI-no-fail-fast')) { + core.setOutput('fail-fast', 'false') + } + } + core.setOutput('python-version', PYTHON_VERSIONS) + } else if (context.eventName == 'pull_request') { + const { data: { labels: labels } } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.payload.pull_request.number + }) + const labelNames = labels.map(label => label.name) + if (labelNames.includes('CI-no-fail-fast')) { + core.setOutput('fail-fast', 'false') + } + // Only run latest CPython and PyPy tests on pull requests + const firstPyPy = PYTHON_VERSIONS.findIndex(version => version.startsWith('pypy')) + const pythonVersions = [PYTHON_VERSIONS[firstPyPy - 1], PYTHON_VERSIONS[PYTHON_VERSIONS.length - 1]] + core.setOutput('python-version', pythonVersions) + } + env: + COMMIT_MESSAGE: > + ${{ + (( + (startsWith(github.event.head_commit.message, 'Try #') || startsWith(github.event.head_commit.message, 'Merge #')) && + github.event.head_commit.author.username == 'bors[bot]' + ) && github.event.head_commit.message) || '' + }} + PYTHON_VERSION: | + - '3.7' + - '3.8' + - '3.9' + - '3.10' + - 'pypy-3.7' + - 'pypy-3.8' + - 'pypy-3.9' + test: name: Test + needs: [ generate-matrix ] strategy: - fail-fast: ${{ !contains(github.event.pull_request.labels.*.name, 'CI-no-fail-fast') }} + fail-fast: ${{ needs.generate-matrix.outputs.fail-fast != 'false' }} matrix: os: [ ubuntu-latest, macos-latest, windows-latest ] + python-version: ${{ fromJson(needs.generate-matrix.outputs.python-version) }} runs-on: ${{ matrix.os }} env: RUST_BACKTRACE: '1' @@ -29,18 +105,13 @@ jobs: activate-environment: '' - uses: actions/setup-python@v4 with: - python-version: "3.7" - - uses: actions/setup-python@v4 - with: - python-version: "3.8" - - uses: actions/setup-python@v4 - with: - python-version: "3.9" - - uses: actions/setup-python@v4 - with: - python-version: "3.10.0" - - name: Install cffi and virtualenv - run: pip install cffi virtualenv ziglang~=0.9.0 twine + python-version: ${{ matrix.python-version }} + architecture: 'x64' + - name: Install cffi + if: ${{ !contains(matrix.python-version, 'pypy') }} + run: pip install cffi + - name: Install python packages + run: pip install virtualenv ziglang~=0.9.0 twine - uses: actions-rs/toolchain@v1 id: rustup with: @@ -84,34 +155,10 @@ jobs: with: path: test-crates/targets key: test-crates-${{ runner.os }}-${{ steps.rustup.outputs.rustc_hash }}-${{ hashFiles('test-crates/*/Cargo.lock') }} - - name: cargo test run: cargo nextest run --features password-storage - - uses: actions/setup-python@v4 - with: - python-version: "pypy-3.7" - - name: test build pypy wheel - shell: bash - run: | - set -ex - cargo run -- build -i pypy3 -m test-crates/pyo3-mixed-submodule/Cargo.toml - pypy3 -m pip install --force-reinstall --no-index --find-links test-crates/pyo3-mixed-submodule/target/wheels pyo3-mixed-submodule - pypy3 -m pip install pytest - pypy3 -m pytest test-crates/pyo3-mixed-submodule/tests/ - - name: test build pypy wheel with abi3 - shell: bash - run: | - set -ex - cargo run -- build -i pypy3 -m test-crates/pyo3-pure/Cargo.toml -vv - pypy3 -m pip install --force-reinstall --no-index --find-links test-crates/pyo3-pure/target/wheels pyo3-pure - pypy3 -m pip install pytest - pypy3 -m pytest test-crates/pyo3-pure/tests - - cargo run -- pep517 build-wheel -i pypy3 -m test-crates/pyo3-pure/Cargo.toml -vv - - uses: actions/setup-python@v4 - with: - python-version: "3.10.0" - name: test cross compiling with zig + if: ${{ !contains(matrix.python-version, 'pypy') }} shell: bash run: | set -ex @@ -120,19 +167,19 @@ jobs: rustup target add aarch64-apple-darwin # abi3 - cargo run -- build -i python -m test-crates/pyo3-pure/Cargo.toml --target aarch64-unknown-linux-gnu --zig - cargo run -- build -i python -m test-crates/pyo3-pure/Cargo.toml --target aarch64-unknown-linux-musl --zig - cargo run -- build -i python -m test-crates/pyo3-pure/Cargo.toml --target aarch64-apple-darwin --zig + cargo run -- build -m test-crates/pyo3-pure/Cargo.toml --target aarch64-unknown-linux-gnu --zig + cargo run -- build -m test-crates/pyo3-pure/Cargo.toml --target aarch64-unknown-linux-musl --zig + cargo run -- build -m test-crates/pyo3-pure/Cargo.toml --target aarch64-apple-darwin --zig # Check wheels with twine twine check --strict test-crates/pyo3-pure/target/wheels/*.whl # non-abi3 - cargo run -- build -i python3.9 -m test-crates/pyo3-mixed/Cargo.toml --target aarch64-unknown-linux-gnu --zig - cargo run -- build -i python3.9 -m test-crates/pyo3-mixed/Cargo.toml --target aarch64-apple-darwin --zig + cargo run -- build -i python${{ matrix.python-version }} -m test-crates/pyo3-mixed/Cargo.toml --target aarch64-unknown-linux-gnu --zig + cargo run -- build -i python${{ matrix.python-version }} -m test-crates/pyo3-mixed/Cargo.toml --target aarch64-apple-darwin --zig # Check wheels with twine twine check --strict test-crates/pyo3-mixed/target/wheels/*.whl - name: test cross compiling windows wheel - if: matrix.os == 'ubuntu-latest' + if: ${{ matrix.os == 'ubuntu-latest' && !contains(matrix.python-version, 'pypy') }} run: | set -ex sudo apt-get install -y mingw-w64 @@ -145,7 +192,7 @@ jobs: cargo run -- build -m test-crates/pyo3-pure/Cargo.toml --target x86_64-pc-windows-msvc # no-abi3 - cargo run -- build -i python3.9 -m test-crates/pyo3-mixed/Cargo.toml --target x86_64-pc-windows-msvc + cargo run -- build -i python${{ matrix.python-version }} -m test-crates/pyo3-mixed/Cargo.toml --target x86_64-pc-windows-msvc - name: test compiling with PYO3_CONFIG_FILE shell: bash run: | @@ -235,7 +282,7 @@ jobs: fail-fast: ${{ !contains(github.event.pull_request.labels.*.name, 'CI-no-fail-fast') }} matrix: # manylinux2014 fails with `/lib64/libc.so.6: version `GLIBC_2.18'` not found recently - # could be a upstream Rust issue, disable it for now + # could be an upstream Rust issue, disable it for now # # manylinux: [ 'manylinux2014', 'manylinux_2_24' ] manylinux: [ 'manylinux_2_24' ] @@ -444,3 +491,24 @@ jobs: uses: Swatinem/rust-cache@v1 - name: cargo check run: cargo check --target ${{ matrix.platform.target }} + + conclusion: + needs: + - test + - test-alpine + - test-auditwheel + - test-docker + - test-cross-compile + - test-bootstrap + - test-msrv + - check + if: always() + runs-on: ubuntu-latest + steps: + - name: Result + run: | + jq -C <<< "${needs}" + # Check if all needs were successful or skipped. + "$(jq -r 'all(.result as $result | (["success", "skipped"] | contains([$result])))' <<< "${needs}")" + env: + needs: ${{ toJson(needs) }}