| name: CI |
| on: |
| pull_request: {} |
| push: |
| branches: |
| - main |
| - '*.*.x' |
| |
| permissions: |
| contents: read |
| |
| concurrency: |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} |
| cancel-in-progress: true |
| |
| env: |
| CARGO_INCREMENTAL: 0 |
| |
| jobs: |
| linux: |
| runs-on: ubuntu-latest |
| strategy: |
| fail-fast: false |
| matrix: |
| PYTHON: |
| - {VERSION: "3.9", NOXSESSION: "flake"} |
| - {VERSION: "3.14", NOXSESSION: "flake"} |
| - {VERSION: "3.14", NOXSESSION: "rust"} |
| - {VERSION: "3.12", NOXSESSION: "docs", OPENSSL: {TYPE: "openssl", VERSION: "3.6.2"}} |
| - {VERSION: "3.14t", NOXSESSION: "rust,tests"} |
| - {VERSION: "pypy-3.11", NOXSESSION: "tests-nocoverage"} |
| - {VERSION: "3.14", NOXSESSION: "tests", OPENSSL: {TYPE: "openssl", VERSION: "3.6.2", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct no-psk"}} |
| - {VERSION: "3.14", NOXSESSION: "tests", OPENSSL: {TYPE: "openssl", VERSION: "3.6.2", CONFIG_FLAGS: "no-legacy", NO_LEGACY: "0"}} |
| - {VERSION: "3.14", NOXSESSION: "tests", OPENSSL: {TYPE: "openssl", VERSION: "3.6.2", CONFIG_FLAGS: "no-legacy", NO_LEGACY: "1"}} |
| - {VERSION: "3.14", NOXSESSION: "tests", NOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.6.2"}} |
| - {VERSION: "3.14", NOXSESSION: "tests", OPENSSL: {TYPE: "openssl", VERSION: "3.0.20"}} |
| - {VERSION: "3.14", NOXSESSION: "tests", OPENSSL: {TYPE: "openssl", VERSION: "3.4.5"}} |
| - {VERSION: "3.14", NOXSESSION: "tests", OPENSSL: {TYPE: "openssl", VERSION: "3.5.6"}} |
| - {VERSION: "3.14", NOXSESSION: "rust,tests", OPENSSL: {TYPE: "openssl", VERSION: "4.0.0"}} |
| - {VERSION: "3.14", NOXSESSION: "tests-ssh", OPENSSL: {TYPE: "openssl", VERSION: "3.6.2"}} |
| - {VERSION: "3.14", NOXSESSION: "rust,tests", OPENSSL: {TYPE: "libressl", VERSION: "4.1.2"}} |
| - {VERSION: "3.14", NOXSESSION: "rust,tests", OPENSSL: {TYPE: "libressl", VERSION: "4.2.1"}} |
| - {VERSION: "3.14", NOXSESSION: "rust,tests", OPENSSL: {TYPE: "libressl", VERSION: "4.3.1"}} |
| # Latest commit on the BoringSSL main branch, as of May 02, 2026. |
| - {VERSION: "3.14", NOXSESSION: "rust,tests", OPENSSL: {TYPE: "boringssl", VERSION: "aef0e2df53d9b2357c2e7ee7e93fc869214a00b4"}} |
| # Latest tag of AWS-LC main branch, as of Apr 29, 2026. |
| - {VERSION: "3.14", NOXSESSION: "rust,tests", OPENSSL: {TYPE: "aws-lc", VERSION: "v1.72.1"}} |
| # Latest commit on the OpenSSL master branch, as of May 04, 2026. |
| - {VERSION: "3.14", NOXSESSION: "tests", OPENSSL: {TYPE: "openssl", VERSION: "fa442ca7b5f21b11a864868dd89bb9728caccb19"}} |
| # Builds with various Rust versions. Includes MSRV and next |
| # potential future MSRV. |
| # noclippy due to: https://github.com/PyO3/pyo3/issues/5768 |
| - {VERSION: "3.14", NOXSESSION: "rust-noclippy,tests", RUST: "1.83.0"} |
| - {VERSION: "3.14", NOXSESSION: "rust-noclippy,tests", RUST: "1.83.0", OPENSSL: {TYPE: "aws-lc", VERSION: "v1.72.1"}} |
| - {VERSION: "3.14", NOXSESSION: "rust-noclippy,tests", RUST: "1.83.0", OPENSSL: {TYPE: "boringssl", VERSION: "aef0e2df53d9b2357c2e7ee7e93fc869214a00b4"}} |
| - {VERSION: "3.14", NOXSESSION: "rust,tests", RUST: "beta"} |
| - {VERSION: "3.14", NOXSESSION: "rust,tests", RUST: "nightly"} |
| - {VERSION: "3.14", NOXSESSION: "tests-rust-debug"} |
| # Not actually an MSRV, just for coverage on this |
| - {VERSION: "3.14", NOXSESSION: "tests", RUST: "1.87", OPENSSL: {TYPE: "openssl", VERSION: "3.6.2"}} |
| - {VERSION: "3.14", NOXSESSION: "tests", RUST: "1.87", NOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.6.2"}} |
| timeout-minutes: 15 |
| steps: |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 |
| timeout-minutes: 3 |
| with: |
| persist-credentials: false |
| - name: Setup python |
| id: setup-python |
| uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 |
| with: |
| python-version: ${{ matrix.PYTHON.VERSION }} |
| cache: pip |
| cache-dependency-path: ci-constraints-requirements.txt |
| timeout-minutes: 3 |
| - name: Setup rust |
| uses: dtolnay/rust-toolchain@e97e2d8cc328f1b50210efc529dca0028893a2d9 |
| with: |
| toolchain: ${{ matrix.PYTHON.RUST }} |
| components: rustfmt,clippy |
| if: matrix.PYTHON.RUST |
| |
| - run: rustup component add llvm-tools-preview |
| if: matrix.PYTHON.NOXSESSION != 'flake' && matrix.PYTHON.NOXSESSION != 'docs' |
| - name: Clone test vectors |
| timeout-minutes: 2 |
| uses: ./.github/actions/fetch-vectors |
| if: matrix.PYTHON.NOXSESSION != 'flake' && matrix.PYTHON.NOXSESSION != 'docs' && matrix.PYTHON.NOXSESSION != 'rust' |
| - name: Compute config hash and set config vars |
| run: | |
| DEFAULT_CONFIG_FLAGS="shared no-ssl2 no-ssl3" |
| CONFIG_FLAGS="$DEFAULT_CONFIG_FLAGS $CONFIG_FLAGS" |
| OPENSSL_HASH=$(echo "${{ matrix.PYTHON.OPENSSL.TYPE }}-${{ matrix.PYTHON.OPENSSL.VERSION }}-$CONFIG_FLAGS" | sha1sum | sed 's/ .*$//') |
| echo "CONFIG_FLAGS=${CONFIG_FLAGS}" >> $GITHUB_ENV |
| echo "OPENSSL_HASH=${OPENSSL_HASH}" >> $GITHUB_ENV |
| echo "OSSL_INFO=${{ matrix.PYTHON.OPENSSL.TYPE }}-${{ matrix.PYTHON.OPENSSL.VERSION }}-${CONFIG_FLAGS}" >> $GITHUB_ENV |
| echo "OSSL_PATH=${{ github.workspace }}/osslcache/${{ matrix.PYTHON.OPENSSL.TYPE }}-${{ matrix.PYTHON.OPENSSL.VERSION }}-${OPENSSL_HASH}" >> $GITHUB_ENV |
| env: |
| CONFIG_FLAGS: ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }} |
| if: matrix.PYTHON.OPENSSL |
| - name: Load OpenSSL cache |
| uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 |
| id: ossl-cache |
| timeout-minutes: 2 |
| with: |
| path: ${{ github.workspace }}/osslcache |
| # When altering the openssl build process you may need to increment |
| # the value on the end of this cache key so that you can prevent it |
| # from fetching the cache and skipping the build step. |
| key: "${{ matrix.PYTHON.OPENSSL.TYPE }}-${{ matrix.PYTHON.OPENSSL.VERSION }}-${{ env.OPENSSL_HASH }}-${{ hashFiles('.github/bin/build_openssl.sh') }}-0" |
| if: matrix.PYTHON.OPENSSL |
| - name: Build custom OpenSSL/LibreSSL |
| run: .github/bin/build_openssl.sh |
| env: |
| TYPE: ${{ matrix.PYTHON.OPENSSL.TYPE }} |
| VERSION: ${{ matrix.PYTHON.OPENSSL.VERSION }} |
| if: matrix.PYTHON.OPENSSL && steps.ossl-cache.outputs.cache-hit != 'true' |
| - name: Set CFLAGS/LDFLAGS |
| run: | |
| echo "OPENSSL_DIR=${OSSL_PATH}" >> $GITHUB_ENV |
| echo "CFLAGS=${CFLAGS} -Werror=implicit-function-declaration" >> $GITHUB_ENV |
| echo "RUSTFLAGS=-Clink-arg=-Wl,-rpath=${OSSL_PATH}/lib -Clink-arg=-Wl,-rpath=${OSSL_PATH}/lib64" >> $GITHUB_ENV |
| if: matrix.PYTHON.OPENSSL |
| - run: rustup run stable cargo install bindgen-cli |
| if: matrix.PYTHON.OPENSSL.TYPE == 'boringssl' || matrix.PYTHON.OPENSSL.TYPE == 'aws-lc' |
| - name: Cache rust and pip |
| uses: ./.github/actions/cache |
| timeout-minutes: 2 |
| with: |
| # We have both the Python version from the matrix and from the |
| # setup-python step because the latter doesn't distinguish |
| # different Python versions of PyPy that share the same PyPy |
| # version number. |
| key: "${{ matrix.PYTHON.VERSION }}-${{ steps.setup-python.outputs.python-version }}-${{ matrix.PYTHON.NOXSESSION }}-${{ env.OPENSSL_HASH }}-0" |
| |
| - run: python -m pip install -c ci-constraints-requirements.txt 'nox[uv]' 'tomli; python_version < "3.11"' |
| - name: Create nox environment |
| run: | |
| nox -v --install-only |
| env: |
| NOXSESSION: ${{ matrix.PYTHON.NOXSESSION }} |
| # Needed until https://github.com/PyO3/pyo3/issues/5093 |
| PYO3_USE_ABI3_FORWARD_COMPATIBILITY: 1 |
| - name: Tests |
| run: | |
| nox --no-install -- --color=yes --wycheproof-root=wycheproof --x509-limbo-root=x509-limbo ${{ matrix.PYTHON.NOXARGS }} |
| env: |
| NOXSESSION: ${{ matrix.PYTHON.NOXSESSION }} |
| COLUMNS: 80 |
| CRYPTOGRAPHY_OPENSSL_NO_LEGACY: ${{ matrix.PYTHON.OPENSSL.NO_LEGACY }} |
| |
| - uses: ./.github/actions/upload-coverage |
| |
| distros: |
| runs-on: ${{ matrix.IMAGE.RUNNER }} |
| container: ghcr.io/pyca/cryptography-runner-${{ matrix.IMAGE.IMAGE }} |
| strategy: |
| fail-fast: false |
| matrix: |
| IMAGE: |
| - {IMAGE: "bookworm", NOXSESSION: "tests", RUNNER: "ubuntu-latest"} |
| - {IMAGE: "trixie", NOXSESSION: "tests", RUNNER: "ubuntu-latest"} |
| - {IMAGE: "sid", NOXSESSION: "tests", RUNNER: "ubuntu-latest"} |
| - {IMAGE: "ubuntu-jammy", NOXSESSION: "tests", RUNNER: "ubuntu-latest"} |
| - {IMAGE: "ubuntu-noble", NOXSESSION: "tests", RUNNER: "ubuntu-latest"} |
| - {IMAGE: "ubuntu-resolute", NOXSESSION: "tests", RUNNER: "ubuntu-latest"} |
| - {IMAGE: "ubuntu-rolling", NOXSESSION: "tests", RUNNER: "ubuntu-latest"} |
| - {IMAGE: "fedora", NOXSESSION: "tests", RUNNER: "ubuntu-latest"} |
| - {IMAGE: "centos-stream9", NOXSESSION: "tests", RUNNER: "ubuntu-latest"} |
| - {IMAGE: "centos-stream9-fips", NOXSESSION: "tests", RUNNER: "ubuntu-latest", FIPS: true} |
| - {IMAGE: "centos-stream10", NOXSESSION: "tests", RUNNER: "ubuntu-latest"} |
| - {IMAGE: "centos-stream10-fips", NOXSESSION: "tests", RUNNER: "ubuntu-latest", FIPS: true} |
| |
| - {IMAGE: "ubuntu-rolling:aarch64", NOXSESSION: "tests", RUNNER: "ubuntu-24.04-arm"} |
| - {IMAGE: "ubuntu-rolling:armv7l", NOXSESSION: "tests", RUNNER: "ubuntu-24.04-arm"} |
| - {IMAGE: "ubuntu-rolling:ppc64le", NOXSESSION: "tests", RUNNER: "ubuntu-24.04-ppc64le"} |
| timeout-minutes: 15 |
| env: |
| RUSTUP_HOME: /root/.rustup |
| steps: |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 |
| timeout-minutes: 3 |
| with: |
| persist-credentials: false |
| - name: Cache rust and pip |
| uses: ./.github/actions/cache |
| timeout-minutes: 2 |
| with: |
| key: ${{ matrix.IMAGE.IMAGE }} |
| - name: Clone test vectors |
| timeout-minutes: 2 |
| uses: ./.github/actions/fetch-vectors |
| # When run in a docker container the home directory doesn't have the same owner as the |
| # apparent user so pip refuses to create a cache dir |
| - name: create pip cache dir |
| run: mkdir -p "${HOME}/.cache/pip" |
| - run: | |
| echo "OPENSSL_FORCE_FIPS_MODE=1" >> $GITHUB_ENV |
| if: matrix.IMAGE.FIPS |
| - run: /venv/bin/python -m pip install -c ci-constraints-requirements.txt 'nox[uv]' 'tomli; python_version < "3.11"' |
| - run: '/venv/bin/nox -v --install-only' |
| env: |
| # OPENSSL_ENABLE_SHA1_SIGNATURES is for CentOS 9 Stream |
| OPENSSL_ENABLE_SHA1_SIGNATURES: 1 |
| NOXSESSION: ${{ matrix.IMAGE.NOXSESSION }} |
| - run: '/venv/bin/nox --no-install -- --color=yes --wycheproof-root="wycheproof" --x509-limbo-root="x509-limbo"' |
| env: |
| COLUMNS: 80 |
| # OPENSSL_ENABLE_SHA1_SIGNATURES is for CentOS 9 Stream |
| OPENSSL_ENABLE_SHA1_SIGNATURES: 1 |
| NOXSESSION: ${{ matrix.IMAGE.NOXSESSION }} |
| - uses: ./.github/actions/upload-coverage |
| |
| alpine: |
| runs-on: ${{ matrix.IMAGE.RUNNER }} |
| container: |
| image: ghcr.io/pyca/cryptography-runner-${{ matrix.IMAGE.IMAGE }} |
| volumes: |
| - /staticnodehost:/staticnodecontainer:rw,rshared |
| - /staticnodehost/24:/__e/node24:ro,rshared |
| strategy: |
| fail-fast: false |
| matrix: |
| IMAGE: |
| - {IMAGE: "alpine", NOXSESSION: "tests", RUNNER: "ubuntu-latest"} |
| - {IMAGE: "alpine:aarch64", NOXSESSION: "tests", RUNNER: "ubuntu-24.04-arm"} |
| timeout-minutes: 15 |
| env: |
| RUSTUP_HOME: /root/.rustup |
| steps: |
| - name: Ridiculous-er workaround for static node |
| run: | |
| cp -R /staticnode/* /staticnodecontainer/ |
| - name: Ridiculous alpine workaround for actions support on arm64 |
| run: | |
| # This modifies /etc/os-release so the JS actions |
| # from GH can't detect that it's on alpine:aarch64. It will |
| # then use a glibc nodejs, which works fine when gcompat |
| # is installed in the container (which it is) |
| sed -i "s:ID=alpine:ID=NotpineForGHA:" /etc/os-release |
| if: matrix.IMAGE.IMAGE == 'alpine:aarch64' |
| |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 |
| timeout-minutes: 3 |
| with: |
| persist-credentials: false |
| - name: Cache rust and pip |
| uses: ./.github/actions/cache |
| timeout-minutes: 2 |
| with: |
| key: ${{ matrix.IMAGE.IMAGE }} |
| - name: Clone test vectors |
| timeout-minutes: 2 |
| uses: ./.github/actions/fetch-vectors |
| # When run in a docker container the home directory doesn't have the same owner as the |
| # apparent user so pip refuses to create a cache dir |
| - name: create pip cache dir |
| run: mkdir -p "${HOME}/.cache/pip" |
| - run: | |
| echo "OPENSSL_FORCE_FIPS_MODE=1" >> $GITHUB_ENV |
| if: matrix.IMAGE.FIPS |
| - run: /venv/bin/python -m pip install -c ci-constraints-requirements.txt 'nox[uv]' 'tomli; python_version < "3.11"' |
| - run: '/venv/bin/nox -v --install-only' |
| env: |
| # OPENSSL_ENABLE_SHA1_SIGNATURES is for CentOS 9 Stream |
| OPENSSL_ENABLE_SHA1_SIGNATURES: 1 |
| NOXSESSION: ${{ matrix.IMAGE.NOXSESSION }} |
| - run: '/venv/bin/nox --no-install -- --color=yes --wycheproof-root="wycheproof" --x509-limbo-root="x509-limbo"' |
| env: |
| COLUMNS: 80 |
| # OPENSSL_ENABLE_SHA1_SIGNATURES is for CentOS 9 Stream |
| OPENSSL_ENABLE_SHA1_SIGNATURES: 1 |
| NOXSESSION: ${{ matrix.IMAGE.NOXSESSION }} |
| - uses: ./.github/actions/upload-coverage |
| |
| macos: |
| runs-on: ${{ matrix.RUNNER.OS }} |
| strategy: |
| fail-fast: false |
| matrix: |
| RUNNER: |
| - {OS: 'macos-15-intel', ARCH: 'x86_64'} |
| - {OS: 'macos-15', ARCH: 'arm64'} |
| PYTHON: |
| - {VERSION: "3.9", NOXSESSION: "tests"} |
| - {VERSION: "3.14", NOXSESSION: "tests"} |
| - {VERSION: "3.14t", NOXSESSION: "tests"} |
| timeout-minutes: 15 |
| steps: |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 |
| timeout-minutes: 3 |
| with: |
| persist-credentials: false |
| - name: Cache rust and pip |
| uses: ./.github/actions/cache |
| timeout-minutes: 2 |
| with: |
| key: ${{ matrix.PYTHON.NOXSESSION }}-${{ matrix.PYTHON.VERSION }} |
| |
| - name: Setup python |
| uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 |
| with: |
| python-version: ${{ matrix.PYTHON.VERSION }} |
| cache: pip |
| cache-dependency-path: ci-constraints-requirements.txt |
| timeout-minutes: 3 |
| - run: rustup component add llvm-tools-preview |
| |
| - run: python -m pip install -c ci-constraints-requirements.txt 'nox[uv]' 'tomli; python_version < "3.11"' |
| |
| - name: Clone test vectors |
| timeout-minutes: 2 |
| uses: ./.github/actions/fetch-vectors |
| |
| - uses: dawidd6/action-download-artifact@8305c0f1062bb0d184d09ef4493ecb9288447732 # v20 |
| with: |
| repo: pyca/infra |
| workflow: build-macos-openssl.yml |
| branch: main |
| workflow_conclusion: success |
| name: openssl-macos-universal2 |
| path: "../openssl-macos-universal2/" |
| github_token: ${{ secrets.GITHUB_TOKEN }} |
| - name: Build nox environment |
| run: | |
| OPENSSL_DIR=$(readlink -f ../openssl-macos-universal2/) \ |
| OPENSSL_STATIC=1 \ |
| CFLAGS="-Werror -Wno-error=deprecated-declarations -Wno-error=incompatible-pointer-types-discards-qualifiers -Wno-error=unused-function" \ |
| nox -v --install-only |
| env: |
| NOXSESSION: ${{ matrix.PYTHON.NOXSESSION }} |
| MACOSX_DEPLOYMENT_TARGET: "10.13" |
| - name: Tests |
| run: nox --no-install -- --color=yes --wycheproof-root=wycheproof --x509-limbo-root=x509-limbo |
| env: |
| NOXSESSION: ${{ matrix.PYTHON.NOXSESSION }} |
| COLUMNS: 80 |
| |
| - uses: ./.github/actions/upload-coverage |
| |
| windows: |
| runs-on: ${{ matrix.WINDOWS.RUNNER }} |
| strategy: |
| fail-fast: false |
| matrix: |
| WINDOWS: |
| - {ARCH: 'x86', WINDOWS: 'win32', RUNNER: 'windows-latest'} |
| - {ARCH: 'x64', WINDOWS: 'win64', RUNNER: 'windows-latest'} |
| PYTHON: |
| - {VERSION: "3.9", NOXSESSION: "tests-nocoverage"} |
| - {VERSION: "3.14", NOXSESSION: "tests"} |
| - {VERSION: "3.14t", NOXSESSION: "tests"} |
| timeout-minutes: 15 |
| steps: |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 |
| timeout-minutes: 3 |
| with: |
| persist-credentials: false |
| - name: Setup python |
| id: setup-python |
| uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 |
| with: |
| python-version: ${{ matrix.PYTHON.VERSION }} |
| architecture: ${{ matrix.WINDOWS.ARCH }} |
| cache: pip |
| cache-dependency-path: ci-constraints-requirements.txt |
| timeout-minutes: 3 |
| - run: rustup component add llvm-tools-preview |
| - name: Cache rust and pip |
| uses: ./.github/actions/cache |
| timeout-minutes: 2 |
| with: |
| key: ${{ matrix.PYTHON.NOXSESSION }}-${{ matrix.WINDOWS.ARCH }}-${{ steps.setup-python.outputs.python-version }} |
| - run: python -m pip install -c ci-constraints-requirements.txt "nox[uv]" "tomli; python_version < '3.11'" |
| |
| - uses: dawidd6/action-download-artifact@8305c0f1062bb0d184d09ef4493ecb9288447732 # v20 |
| with: |
| repo: pyca/infra |
| workflow: build-windows-openssl.yml |
| branch: main |
| workflow_conclusion: success |
| name: "openssl-${{ matrix.WINDOWS.WINDOWS }}" |
| path: "C:/openssl-${{ matrix.WINDOWS.WINDOWS }}/" |
| github_token: ${{ secrets.GITHUB_TOKEN }} |
| - name: Configure |
| run: | |
| echo "OPENSSL_DIR=C:/openssl-${{ matrix.WINDOWS.WINDOWS }}" >> $GITHUB_ENV |
| shell: bash |
| |
| - name: Clone test vectors |
| timeout-minutes: 2 |
| uses: ./.github/actions/fetch-vectors |
| |
| - name: Build nox environment |
| run: nox -v --install-only |
| env: |
| NOXSESSION: ${{ matrix.PYTHON.NOXSESSION }} |
| - name: Tests |
| run: nox --no-install -- --color=yes --wycheproof-root=wycheproof --x509-limbo-root=x509-limbo |
| env: |
| NOXSESSION: ${{ matrix.PYTHON.NOXSESSION }} |
| COLUMNS: 80 |
| |
| - uses: ./.github/actions/upload-coverage |
| |
| linux-downstream: |
| runs-on: ubuntu-latest |
| strategy: |
| fail-fast: false |
| matrix: |
| include: |
| - DOWNSTREAM: paramiko |
| REPO: paramiko/paramiko |
| # Latest commit on the paramiko main branch, as of Oct 20, 2025. |
| REF: 8697158113a3eab25ed1d1d541ebe2cad10169a7 |
| PATH: paramiko |
| - DOWNSTREAM: pyopenssl |
| REPO: pyca/pyopenssl |
| # Latest commit on the pyopenssl main branch, as of May 02, 2026. |
| REF: 068c200587bd7898f43a7a47a94915284e3a82be |
| PATH: pyopenssl |
| - DOWNSTREAM: pyopenssl-release |
| REPO: pyca/pyopenssl |
| # Latest release tag of pyopenssl-release, as of Apr 25, 2026. |
| REF: 26.1.0 |
| PATH: pyopenssl |
| - DOWNSTREAM: twisted |
| REPO: twisted/twisted |
| # Latest commit on the twisted trunk branch, as of Apr 30, 2026. |
| REF: 2d196123264efb0027eecfe1b430be4a9babdbd8 |
| PATH: twisted |
| - DOWNSTREAM: aws-encryption-sdk-python |
| REPO: awslabs/aws-encryption-sdk-python |
| # Latest commit on the aws-encryption-sdk-python master branch, as of May 01, 2026. |
| REF: 6e958bd4e25c25d5cdbd88860cb679e70a89f198 |
| PATH: aws-encryption-sdk-python |
| - DOWNSTREAM: aws-dynamodb-encryption-python |
| REPO: awslabs/aws-dynamodb-encryption-python |
| # Latest commit on the aws-dynamodb-encryption-python master branch, as of Apr 29, 2026. |
| REF: fbdf52978e99f06b1b513b4be33d826c5ac5ada1 |
| PATH: aws-dynamodb-encryption-python |
| - DOWNSTREAM: certbot |
| REPO: certbot/certbot |
| # Latest commit on the certbot main branch, as of Apr 29, 2026. |
| REF: 9ec4105ff3c00582b628de4761260b0b0e643da8 |
| PATH: certbot |
| - DOWNSTREAM: certbot-josepy |
| REPO: certbot/josepy |
| # Latest commit on the certbot-josepy main branch, as of Apr 07, 2026. |
| REF: a40f3a8bde9c0fe4d0ecc7b1e46c9ea3cbc3c373 |
| PATH: josepy |
| - DOWNSTREAM: mitmproxy |
| REPO: mitmproxy/mitmproxy |
| # Latest commit on the mitmproxy main branch, as of Apr 29, 2026. |
| REF: ab470e5397d8cb73b3c44b9ee75834e6cda83ae7 |
| PATH: mitmproxy |
| - DOWNSTREAM: scapy |
| REPO: secdev/scapy |
| # Latest commit on the scapy master branch, as of May 02, 2026. |
| REF: 8c5a9a8f76a771518caac7aa74b5b94e887c24b8 |
| PATH: scapy |
| - DOWNSTREAM: sigstore-python |
| REPO: sigstore/sigstore-python |
| # Latest commit on the sigstore-python main branch, as of Apr 29, 2026. |
| REF: ec6e833ee36805ac4fde4f5252cc1d96acb944f5 |
| PATH: sigstore-python |
| name: "Downstream tests for ${{ matrix.DOWNSTREAM }}" |
| timeout-minutes: 15 |
| steps: |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 |
| timeout-minutes: 3 |
| with: |
| persist-credentials: false |
| - name: Checkout downstream repository |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 |
| timeout-minutes: 3 |
| with: |
| repository: ${{ matrix.REPO }} |
| ref: ${{ matrix.REF }} |
| path: ${{ matrix.PATH }} |
| persist-credentials: false |
| - name: Cache rust and pip |
| uses: ./.github/actions/cache |
| timeout-minutes: 2 |
| - name: Setup python |
| uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 |
| with: |
| python-version: '3.12' |
| cache: pip |
| cache-dependency-path: ci-constraints-requirements.txt |
| timeout-minutes: 3 |
| |
| - run: python -m pip install -c ci-constraints-requirements.txt 'uv' |
| - run: uv venv |
| - run: source .venv/bin/activate && ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh install |
| - run: uv pip install . |
| # cryptography main has a version of "(X+1).0.0.dev1" where X is the |
| # most recently released major version. A package used by a downstream |
| # may depend on cryptography <=X. If you use entrypoints stuff, this can |
| # lead to runtime errors due to version incompatibilities. Rename the |
| # dist-info directory to pretend to be an older version to "solve" this. |
| - run: | |
| .venv/bin/python <<EOF |
| import json |
| import importlib.metadata |
| import shutil |
| import urllib.request |
| |
| d = importlib.metadata.distribution("cryptography") |
| with urllib.request.urlopen("https://pypi.org/pypi/cryptography/json") as r: |
| latest_version = json.load(r)["info"]["version"] |
| new_path = d.locate_file(f"cryptography-{latest_version}.dist-info") |
| shutil.move(d.locate_file(f"cryptography-{d.version}.dist-info"), new_path) |
| |
| EOF |
| - run: source .venv/bin/activate && ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh run |
| |
| all-green: |
| # https://github.community/t/is-it-possible-to-require-all-github-actions-tasks-to-pass-without-enumerating-them/117957/4?u=graingert |
| runs-on: ubuntu-latest |
| needs: [linux, alpine, distros, macos, windows, linux-downstream] |
| if: ${{ always() }} |
| timeout-minutes: 3 |
| steps: |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 |
| timeout-minutes: 3 |
| with: |
| persist-credentials: false |
| - name: Decide whether the needed jobs succeeded or failed |
| uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2 |
| with: |
| jobs: ${{ toJSON(needs) }} |
| - name: Setup python |
| if: ${{ always() }} |
| uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 |
| with: |
| python-version: '3.14' |
| cache: pip |
| cache-dependency-path: ci-constraints-requirements.txt |
| timeout-minutes: 3 |
| - run: pip install -c ci-constraints-requirements.txt coverage[toml] |
| if: ${{ always() }} |
| - name: Download coverage data |
| if: ${{ always() }} |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 |
| with: |
| pattern: coverage-data-* |
| merge-multiple: true |
| path: coverage-data/ |
| - name: Combine coverage and fail if it's <100%. |
| if: ${{ always() }} |
| id: combinecoverage |
| run: | |
| set +e |
| echo "## Coverage" >> $GITHUB_STEP_SUMMARY |
| python -u .github/bin/merge_rust_coverage.py coverage-data/ | tee COV_REPORT |
| COV_EXIT_CODE=${PIPESTATUS[0]} |
| if [ $COV_EXIT_CODE -ne 0 ]; then |
| echo "🚨 Coverage failed. Under 100" | tee -a $GITHUB_STEP_SUMMARY |
| fi |
| echo '```' >> $GITHUB_STEP_SUMMARY |
| cat COV_REPORT >> $GITHUB_STEP_SUMMARY |
| echo '```' >> $GITHUB_STEP_SUMMARY |
| exit $COV_EXIT_CODE |
| - name: Upload HTML report. |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 |
| with: |
| name: _html-coverage-report |
| path: htmlcov |
| if-no-files-found: ignore |
| if: ${{ failure() && steps.combinecoverage.outcome == 'failure' }} |