Skip to content

Fix PyPI agent apply patching only one installed copy (#529, #501) #354

Fix PyPI agent apply patching only one installed copy (#529, #501)

Fix PyPI agent apply patching only one installed copy (#529, #501) #354

name: PDM patch compatibility
# Native PDM installer matrix: builds the CLI and the capstone test binary
# once per OS, bootstraps pinned PDM releases with uv, and runs
# `scripts/backtest-pdm.py` — hosted, vendored and agent mode against the
# public urllib3 free patch, verifying the INSTALLED bytes, lock/manifest
# stability, hash rejection and rollback. No Socket API token is needed. See
# docs/testing/pdm-compatibility.md.
on:
pull_request:
paths:
- '.github/actions/upload-artifact/**'
- '.github/workflows/pdm-compatibility.yml'
- 'scripts/backtest-pdm.py'
- 'crates/socket-patch-core/src/utils/pdm_lock.rs'
- 'crates/socket-patch-core/src/patch/redirect/**'
- 'crates/socket-patch-core/src/vendor/pypi*.rs'
- 'crates/socket-patch-core/src/vendor/common.rs'
- 'crates/socket-patch-core/src/vendor/lock_inventory/**'
- 'crates/socket-patch-cli/src/commands/scan/**'
- 'crates/socket-patch-cli/src/commands/rollback.rs'
- 'crates/socket-patch-core/tests/fixtures/pdm-native/**'
- 'crates/socket-patch-core/src/vex/**'
- 'crates/socket-patch-cli/src/commands/vex*.rs'
- 'crates/socket-patch-cli/tests/e2e_vex_build/main.rs'
- 'crates/socket-patch-cli/tests/e2e_vex_build/pdm.rs'
- 'crates/socket-patch-cli/tests/vex_pypi_real_common/**'
# The capstone skips the cells ci.yml's e2e rows run.
- '.github/workflows/ci.yml'
push:
branches: [main]
paths:
- 'scripts/backtest-pdm.py'
- 'crates/socket-patch-core/src/utils/pdm_lock.rs'
- 'crates/socket-patch-core/src/patch/redirect/pdm.rs'
- 'crates/socket-patch-core/src/vendor/pypi_pdm.rs'
workflow_dispatch:
inputs:
versions:
description: 'Space-separated PDM versions (empty = the required matrix below)'
required: false
default: ''
shapes:
description: 'Space-separated shapes (empty = every shape)'
required: false
default: ''
permissions:
contents: read
concurrency:
group: pdm-compat-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
SOCKET_NO_CONFIG: '1'
SOCKET_NO_UPDATE_CHECK: '1'
PDM_CHECK_UPDATE: 'false'
jobs:
build:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
with:
key: pdm-compat
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Compile the CLI and the capstone once
run: |
set -euo pipefail
cargo test --locked -p socket-patch-cli --test e2e_vex_build --no-run --message-format=json-render-diagnostics > target-build.json
python3 - <<'PY'
import json, pathlib, shutil
dest = pathlib.Path('target/pdm-e2e')
dest.mkdir(parents=True, exist_ok=True)
shutil.copy2('target/debug/socket-patch', dest / 'socket-patch')
for line in pathlib.Path('target-build.json').read_text().splitlines():
item = json.loads(line)
if item.get('target', {}).get('name') == 'e2e_vex_build' and item.get('executable'):
shutil.copy2(item['executable'], dest / 'e2e_vex_build')
assert (dest / 'e2e_vex_build').is_file()
PY
- uses: ./.github/actions/upload-artifact
with:
name: pdm-cli-${{ matrix.os }}
path: target/pdm-e2e/
if-no-files-found: error
retention-days: 7
native:
needs: build
strategy:
fail-fast: false
matrix:
# Every stable PDM major family (0.x, 1.x, 2.x) and each 2.x lock-format
# boundary on Linux; macOS samples the ends of the range. No Windows:
# the harness bootstraps PDM through a POSIX venv layout (bin/pdm), so
# every Windows cell skipped; backtest-pdm.py now fails such a cell.
os: [ubuntu-latest]
pdm: ['0.12.3', '1.15.5', '2.0.3', '2.1.5', '2.3.4', '2.6.1', '2.7.4', '2.8.2', '2.9.3', '2.10.4', '2.11.2', '2.17.3', '2.20.1', '2.22.4', '2.25.9', '2.29.2']
include:
- { os: macos-latest, pdm: '0.12.3' }
- { os: macos-latest, pdm: '2.8.2' }
- { os: macos-latest, pdm: '2.29.2' }
runs-on: ${{ matrix.os }}
timeout-minutes: 45
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
pattern: pdm-cli-${{ matrix.os }}*
merge-multiple: true
path: native-cli
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: '3.12'
# uv bootstraps every pinned PDM release (and its interpreter) itself;
# pinning uv keeps the bootstrap reproducible across runner images.
- run: python -m pip install uv==0.11.19
- name: Exercise the native PDM installers
shell: bash
env:
PDM_VERSION: ${{ matrix.pdm }}
VERSIONS_OVERRIDE: ${{ github.event.inputs.versions }}
SHAPES_OVERRIDE: ${{ github.event.inputs.shapes }}
run: |
chmod +x native-cli/socket-patch* || true
cli="native-cli/socket-patch"
if [ "$RUNNER_OS" = "Windows" ]; then cli="native-cli/socket-patch.exe"; fi
versions="$PDM_VERSION"
if [ -n "$VERSIONS_OVERRIDE" ]; then versions="$VERSIONS_OVERRIDE"; fi
shapes_arg=()
if [ -n "$SHAPES_OVERRIDE" ]; then shapes_arg=(--shapes $SHAPES_OVERRIDE); fi
python3 scripts/backtest-pdm.py \
--socket-patch "$cli" \
--socket-patch-revision "$GITHUB_SHA" \
--output native-pdm \
--versions $versions \
--modes hosted vendored agent \
"${shapes_arg[@]}" \
--jobs 3
- uses: ./.github/actions/upload-artifact
if: always()
with:
name: pdm-results-${{ matrix.os }}-${{ matrix.pdm }}
path: |
native-pdm/summary.json
native-pdm/summary.md
native-pdm/tool-logs/*.log
native-pdm/original/**/*.log
native-pdm/original/**/pdm.lock
native-pdm/original/**/pyproject.toml
native-pdm/cases/**/result.json
native-pdm/cases/**/cli-output.json
native-pdm/cases/**/pdm.lock
native-pdm/cases/**/*.log
retention-days: 14
# The hermetic Rust capstone (wiremock Socket API that also serves the
# hosted wheel) over every PDM release the backtest covers: real hosted +
# vendored flows ending in the manifest-less VEX matrix; refused lock
# formats (3.1, 4.0-4.2) must attest nothing. The cells ci.yml's `e2e`
# job runs on every PR and main push are excluded here
# (scripts/tests/test_ci_e2e_tiers.py keeps the two lists in step).
capstone:
needs: build
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
pdm: ['0.12.3', '1.0.0', '1.4.5', '1.8.5', '1.15.5', '2.0.3', '2.7.4', '2.8.2', '2.10.4', '2.11.2', '2.17.3', '2.20.1', '2.22.4', '2.25.9', '2.29.2']
exclude:
- {os: ubuntu-latest, pdm: '1.4.5'}
- {os: ubuntu-latest, pdm: '1.15.5'}
- {os: ubuntu-latest, pdm: '2.7.4'}
- {os: ubuntu-latest, pdm: '2.8.2'}
- {os: ubuntu-latest, pdm: '2.25.9'}
- {os: ubuntu-latest, pdm: '2.29.2'}
- {os: macos-latest, pdm: '2.29.2'}
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
# The binaries resolve fixtures through the build job's checkout path,
# which is the same on every runner of one OS.
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
pattern: pdm-cli-${{ matrix.os }}*
merge-multiple: true
path: target/pdm-e2e
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: '3.12'
- run: python -m pip install uv==0.11.19
- name: Real-PDM hosted + vendored flows with manifest-less VEX
env:
SOCKET_PATCH_PDM_E2E_REQUIRED: '1'
SOCKET_PATCH_PDM_E2E_VERSION: ${{ matrix.pdm }}
run: |
set -euo pipefail
chmod +x target/pdm-e2e/*
mkdir -p target/debug target/tmp
cp target/pdm-e2e/socket-patch target/debug/socket-patch
cd crates/socket-patch-cli
export CARGO_MANIFEST_DIR="$PWD"
../../target/pdm-e2e/e2e_vex_build 'pdm::' --ignored