| 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: "4.0.1"}} |
| - {VERSION: "3.14t", NOXSESSION: "rust,tests"} |
| - {VERSION: "pypy-3.11", NOXSESSION: "tests-nocoverage"} |
| - {VERSION: "3.14", NOXSESSION: "tests", OPENSSL: {TYPE: "openssl", VERSION: "4.0.1", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct no-psk"}} |
| - {VERSION: "3.14", NOXSESSION: "tests", OPENSSL: {TYPE: "openssl", VERSION: "4.0.1", CONFIG_FLAGS: "no-legacy", NO_LEGACY: "0"}} |
| - {VERSION: "3.14", NOXSESSION: "tests", OPENSSL: {TYPE: "openssl", VERSION: "4.0.1", 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.3"}} |
| - {VERSION: "3.14", NOXSESSION: "tests", OPENSSL: {TYPE: "openssl", VERSION: "3.0.21"}} |
| - {VERSION: "3.14", NOXSESSION: "tests", OPENSSL: {TYPE: "openssl", VERSION: "3.4.6"}} |
| - {VERSION: "3.14", NOXSESSION: "tests", OPENSSL: {TYPE: "openssl", VERSION: "3.5.7"}} |
| - {VERSION: "3.14", NOXSESSION: "rust,tests", OPENSSL: {TYPE: "openssl", VERSION: "4.0.1"}} |
| - {VERSION: "3.14", NOXSESSION: "tests-ssh", OPENSSL: {TYPE: "openssl", VERSION: "3.6.3"}} |
| - {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.2"}} |
| # Latest commit on the BoringSSL main branch, as of Jun 19, 2026. |
| - {VERSION: "3.14", NOXSESSION: "rust,tests", OPENSSL: {TYPE: "boringssl", VERSION: "606d3a344dae49672ea567f6719e1fc092a4ae6a"}} |
| # Latest tag of AWS-LC main branch, as of May 30, 2026. |
| - {VERSION: "3.14", NOXSESSION: "rust,tests", OPENSSL: {TYPE: "aws-lc", VERSION: "v5.0.0"}} |
| # Latest commit on the OpenSSL master branch, as of Jun 19, 2026. |
| - {VERSION: "3.14", NOXSESSION: "tests", OPENSSL: {TYPE: "openssl", VERSION: "695fef3ec31e360f0e407c3b3f283b9f18711eaa"}} |
| # Builds with various Rust versions. Includes MSRV and next |
| # potential future MSRV. |
| # - 1.85: 2024 edition |
| # - 1.95: cfg_select |
| - {VERSION: "3.14", NOXSESSION: "rust,tests", RUST: "1.83.0"} |
| - {VERSION: "3.14", NOXSESSION: "rust,tests", RUST: "1.83.0", OPENSSL: {TYPE: "aws-lc", VERSION: "v5.0.0"}} |
| - {VERSION: "3.14", NOXSESSION: "rust,tests", RUST: "1.83.0", OPENSSL: {TYPE: "boringssl", VERSION: "606d3a344dae49672ea567f6719e1fc092a4ae6a"}} |
| - {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: "4.0.1"}} |
| - {VERSION: "3.14", NOXSESSION: "tests", RUST: "1.87", NOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.6.3"}} |
| timeout-minutes: 15 |
| steps: |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 |
| 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 |
| |
| # llvm-tools is only used to process Rust coverage data, which the |
| # tests-nocoverage session doesn't collect. |
| - run: rustup component add llvm-tools-preview |
| if: matrix.PYTHON.NOXSESSION != 'flake' && matrix.PYTHON.NOXSESSION != 'docs' && matrix.PYTHON.NOXSESSION != 'tests-nocoverage' |
| - 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 |
| - 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" |
| # This must run after the cache action: rust-cache prunes binaries |
| # that already existed in ~/.cargo/bin before it ran, so installing |
| # bindgen first means it never gets cached. When the cache is warm, |
| # cargo sees the binary is already installed and skips the build. |
| - run: rustup run stable cargo install bindgen-cli |
| if: matrix.PYTHON.OPENSSL.TYPE == 'boringssl' || matrix.PYTHON.OPENSSL.TYPE == 'aws-lc' |
| |
| - 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-stream10", NOXSESSION: "tests", RUNNER: "ubuntu-latest"} |
| |
| - {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@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 |
| 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@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 |
| 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: macos-26 |
| strategy: |
| fail-fast: false |
| matrix: |
| PYTHON: |
| - {VERSION: "3.9", NOXSESSION: "tests"} |
| - {VERSION: "3.14", NOXSESSION: "tests"} |
| - {VERSION: "3.14t", NOXSESSION: "tests"} |
| timeout-minutes: 15 |
| steps: |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 |
| 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 |
| |
| - name: Download OpenSSL |
| uses: ./.github/actions/fetch-openssl |
| with: |
| workflow: build-macos-openssl.yml |
| name: openssl-macos-arm64 |
| path: "../openssl-macos-arm64/" |
| - name: Build nox environment |
| run: | |
| OPENSSL_DIR=$(readlink -f ../openssl-macos-arm64/) \ |
| 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: "11.0" |
| - 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: 'x64', WINDOWS: 'win64', RUNNER: 'windows-latest'} |
| PYTHON: |
| - {VERSION: "3.9", NOXSESSION: "tests-nocoverage"} |
| - {VERSION: "3.14", NOXSESSION: "tests"} |
| - {VERSION: "3.14t", NOXSESSION: "tests"} |
| include: |
| # Windows on ARM is in a stability validation period; the work |
| # step uses `continue-on-error` only for this entry so transient |
| # failures don't block PR validation. |
| - WINDOWS: {ARCH: 'arm64', WINDOWS: 'arm64', RUNNER: 'windows-11-arm'} |
| PYTHON: {VERSION: "3.14", NOXSESSION: "tests-nocoverage"} |
| timeout-minutes: 15 |
| steps: |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 |
| timeout-minutes: 3 |
| with: |
| persist-credentials: false |
| - id: tests |
| continue-on-error: ${{ matrix.WINDOWS.ARCH == 'arm64' }} |
| uses: ./.github/actions/windows-tests |
| with: |
| python-version: ${{ matrix.PYTHON.VERSION }} |
| noxsession: ${{ matrix.PYTHON.NOXSESSION }} |
| arch: ${{ matrix.WINDOWS.ARCH }} |
| openssl-name: ${{ matrix.WINDOWS.WINDOWS }} |
| - name: Report soft failure |
| if: always() && matrix.WINDOWS.ARCH == 'arm64' && steps.tests.outcome != 'success' |
| shell: bash |
| run: | |
| echo "::warning title=windows-arm64 soft failure::A step failed but the job is reported as success while Windows on ARM is in stability validation." |
| |
| - 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 May 10, 2026. |
| REF: d60d5c17d78f344b51ed651e796d2931133a9b22 |
| PATH: paramiko |
| - DOWNSTREAM: pyopenssl |
| REPO: pyca/pyopenssl |
| # Latest commit on the pyopenssl main branch, as of Jun 13, 2026. |
| REF: a34aa1de7e2050d3a83cef74d8265662237f8ba1 |
| PATH: pyopenssl |
| - DOWNSTREAM: pyopenssl-release |
| REPO: pyca/pyopenssl |
| # Latest release tag of pyopenssl-release, as of Jun 13, 2026. |
| REF: 26.3.0 |
| PATH: pyopenssl |
| - DOWNSTREAM: twisted |
| REPO: twisted/twisted |
| # Latest commit on the twisted trunk branch, as of Jun 12, 2026. |
| REF: 802f09462451be320db28b5c111f0c9c944cddbc |
| 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 29, 2026. |
| REF: 61040db041104dfd950d1541039ad996dbe895be |
| PATH: aws-encryption-sdk-python |
| - DOWNSTREAM: certbot |
| REPO: certbot/certbot |
| # Latest commit on the certbot main branch, as of Jun 18, 2026. |
| REF: 184091fa3ed4189f1585a47b53dd6a12b36bff2b |
| PATH: certbot |
| - DOWNSTREAM: certbot-josepy |
| REPO: certbot/josepy |
| # Latest commit on the certbot-josepy main branch, as of Jun 05, 2026. |
| REF: 1a4a224db9504e8b74000e303935ba79929b9fd7 |
| PATH: josepy |
| - DOWNSTREAM: mitmproxy |
| REPO: mitmproxy/mitmproxy |
| # Latest commit on the mitmproxy main branch, as of Jun 18, 2026. |
| REF: c4fa9fb8c8e292512dcc708459d1555fd876fd9e |
| PATH: mitmproxy |
| - DOWNSTREAM: scapy |
| REPO: secdev/scapy |
| # Latest commit on the scapy master branch, as of Jun 17, 2026. |
| REF: 14cc7260f15034cee57cd4729011b78653b04225 |
| PATH: scapy |
| - DOWNSTREAM: sigstore-python |
| REPO: sigstore/sigstore-python |
| # Latest commit on the sigstore-python main branch, as of Jun 15, 2026. |
| REF: 62a429395bf914b11058801cc28cb7ebc7359c2e |
| PATH: sigstore-python |
| name: "Downstream tests for ${{ matrix.DOWNSTREAM }}" |
| timeout-minutes: 15 |
| steps: |
| - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 |
| timeout-minutes: 3 |
| with: |
| persist-credentials: false |
| - name: Checkout downstream repository |
| uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 |
| 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.13' |
| 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 -v . |
| # 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@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 |
| 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' }} |