Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
981b44e
Lead the CLI help with the v5 workflow
mikolalysenko Sep 27, 2026
d891d3b
Prefer the newest merged patch when choosing one per package
mikolalysenko Sep 27, 2026
b0a2ce6
Make scan default to hosted mode and never prompt
mikolalysenko Sep 27, 2026
c1ee18f
Detect hosted patch updates from the lockfile's own pins
mikolalysenko Sep 27, 2026
da1ccc5
Share the crawler-options and ecosystem-scope helpers across commands
mikolalysenko Sep 27, 2026
62f07c7
Let hosted and vendored scans take project directories
mikolalysenko Sep 27, 2026
6091833
Rank [UPDATE] detection by the same rule scan installs by
mikolalysenko Sep 27, 2026
5e5f5ed
Default get to hosted mode, like scan
mikolalysenko Sep 27, 2026
462a35b
Rewrite the README, CLI contract and docs for v5
mikolalysenko Sep 27, 2026
d6438a3
Clean up stale and narrative comments across the tree
mikolalysenko Sep 27, 2026
962acc4
Fix follow-ups from the stale-doc sweep
mikolalysenko Sep 27, 2026
8ae7dc3
Add the v5 plan: decisions and workstreams
mikolalysenko Sep 27, 2026
686e5fb
v5 WS1+WS2: ledger-free hosted mode, upstream-restore rollback, vendo…
mikolalysenko Sep 28, 2026
06437d2
WS5: one VendoredBackend for vendored apply/revert/repair; cut repair…
mikolalysenko Sep 28, 2026
c7aa5a5
v5 fix: unblock the e2e tier on the v5 base (#288)
mikolalysenko Sep 28, 2026
c02ccf8
Add the NuGet vendoring design (docs only) (#285)
mikolalysenko Sep 28, 2026
388eea3
docs: keep v5 waste review and repacking design (#289)
mikolalysenko Sep 28, 2026
0f2de18
v5 design: staged patch rollout (socket.yml + scan limit) (#290)
mikolalysenko Sep 28, 2026
28cebf7
Attribute vlt pins and uv overrides in ledger-free hosted rollback
mikolalysenko Sep 28, 2026
73c0c4f
WS3: one lockfile model per ecosystem (#281)
mikolalysenko Sep 28, 2026
f6bdad5
v5: remove `setup` (WS7) + patch UI streamlining (WS8) (#279)
mikolalysenko Sep 28, 2026
14a9cb0
v5 WS4/WS6: one hosted engine for disk + memory; unified Ledgers view…
mikolalysenko Sep 28, 2026
f9cb7e1
v5 CI: build e2e binaries once and tier the PM matrix (#291)
mikolalysenko Sep 28, 2026
a7b0d00
v5: fix partial-stage repair bug, cut redundant downloads (#292)
mikolalysenko Sep 29, 2026
1e3ace6
v5: remove dead code and v3 compatibility shims (#296)
mikolalysenko Sep 29, 2026
b97a1c2
v5 tests: one suite per command, retire #257 oracles (#297)
mikolalysenko Sep 29, 2026
b9e106d
v5: socket.yml patch rollout config and filtering (#293)
mikolalysenko Sep 29, 2026
180f10f
v5: cap new patches per scan, most critical first (#294)
mikolalysenko Sep 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Windows main threads get a 1 MiB stack reserve by default (Unix mains get
# 8 MiB). The CLI's async command futures poll deeply nested state machines
# — scan → download → in-process apply, or scan --vendor → the vendor engine
# — scan → download → in-process apply, or a vendored scan → the vendor engine
# — and in debug builds (no stack-slot reuse) the summed poll frames exceed
# 1 MiB, aborting with "thread 'main' has overflowed its stack" on Windows
# only. Raise the PE stack reserve to the Unix default; spawned threads are
Expand Down
7 changes: 7 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ crates/socket-patch-core/tests/fixtures/redirect/** -text

crates/socket-patch-core/tests/fixtures/pdm-native/*.lock -text

# Poetry and Pipenv locks are real `poetry lock` / `pipenv lock` output: the
# upstream restore and VEX tests round-trip them byte for byte and derive
# their CRLF variants from the LF bytes themselves.
crates/socket-patch-core/tests/fixtures/poetry/** -text
crates/socket-patch-core/tests/fixtures/pipenv/** -text
crates/socket-patch-core/tests/fixtures/pipenv-shapes/** -text

# The captured pnpm 1-12 locks are byte-real: the hosted/vendored rewriters
# refuse CRLF by design (vendor_lockfile_crlf_unsupported), and the tests
# derive their CRLF variants from the LF bytes themselves.
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/bun-compatibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ on:
- 'crates/socket-patch-cli/src/commands/scan/**'
- 'crates/socket-patch-cli/src/commands/rollback.rs'
- 'crates/socket-patch-cli/src/commands/vendor.rs'
- 'crates/socket-patch-cli/src/commands/repair_vendor.rs'
- 'crates/socket-patch-cli/src/commands/vendored_backend/**'
- 'crates/socket-patch-cli/src/commands/remove.rs'
# Main runs are the only rust-cache writers (save-if below), so a
# path-filtered push trigger is what seeds the cache the PR builds restore
# (rust-cache keys on Cargo.lock, so Cargo.lock belongs here) and re-runs
# the matrix post-merge on the code paths it exercises: the vendored engine
# (`vendor/**` — bun_lock.rs, bun_lock_text.rs's shared version gate,
# npm_flavor.rs, lock_inventory.rs), the hosted rewriter + unwinds, and the
# npm_flavor.rs, lock_inventory/), the hosted rewriter + unwinds, and the
# CLI drivers (`scan/**` — hosted.rs, vendor_flow.rs, mod.rs — plus the
# vendor / repair / remove commands the matrix runs).
push:
Expand All @@ -75,7 +75,7 @@ on:
- 'crates/socket-patch-cli/src/commands/scan/**'
- 'crates/socket-patch-cli/src/commands/rollback.rs'
- 'crates/socket-patch-cli/src/commands/vendor.rs'
- 'crates/socket-patch-cli/src/commands/repair_vendor.rs'
- 'crates/socket-patch-cli/src/commands/vendored_backend/**'
- 'crates/socket-patch-cli/src/commands/remove.rs'
workflow_dispatch:
inputs:
Expand All @@ -95,11 +95,11 @@ on:
permissions:
contents: read

# Supersede stale PR runs. The `main` guard is load-bearing: main runs are the
# ONLY rust-cache writers (save-if), so they must never be cancelled mid-save.
# Supersede stale PR runs only: main runs are the ONLY rust-cache writers
# (save-if), so push, dispatch and schedule runs are never cancelled mid-save.
concurrency:
group: bun-patch-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
CARGO_PROFILE_DEV_DEBUG: '0'
Expand Down
680 changes: 384 additions & 296 deletions .github/workflows/ci.yml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion .github/workflows/go-compatibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ permissions:

concurrency:
group: go-compat-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
SOCKET_NO_CONFIG: '1'
Expand Down
21 changes: 21 additions & 0 deletions .github/workflows/npm-compatibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,28 @@ name: npm hosted/vendored compatibility
# installs one pinned npm and runs them. See docs/testing/npm-compatibility.md.

on:
# PRs: any crate source, but only the test files these capstones
# compile (a later `!` pattern excludes, a later plain one re-includes).
# Main pushes stay unfiltered.
pull_request:
paths:
- '.github/actions/upload-artifact/**'
- 'Cargo.lock'
- 'Cargo.toml'
- 'rust-toolchain.toml'
- '.cargo/config.toml'
- '.github/workflows/npm-compatibility.yml'
- 'docs/testing/npm-compatibility.md'
- 'crates/**'
- '!crates/**/*.md'
- '!crates/socket-patch-node/**'
- '!crates/socket-patch-core/tests/**'
- '!crates/socket-patch-cli/tests/**'
- 'crates/socket-patch-cli/tests/vex_e2e_common/**'
- 'crates/socket-patch-cli/tests/e2e_redirect_npm_build.rs'
- 'crates/socket-patch-cli/tests/e2e_vendor_npm_build.rs'
- 'crates/socket-patch-cli/tests/npm_e2e_common/**'
- 'crates/socket-patch-cli/tests/common/cache_env.rs'
push:
branches: [main]
workflow_dispatch:
Expand Down
79 changes: 58 additions & 21 deletions .github/workflows/pdm-compatibility.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
name: PDM patch compatibility

# Native PDM installer matrix: builds the CLI 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.
# 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:
Expand All @@ -16,7 +17,7 @@ on:
- '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.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/**'
Expand All @@ -25,6 +26,8 @@ on:
- '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:
Expand All @@ -48,7 +51,7 @@ permissions:

concurrency:
group: pdm-compat-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
SOCKET_NO_CONFIG: '1'
Expand All @@ -60,7 +63,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
timeout-minutes: 30
steps:
Expand All @@ -70,13 +73,26 @@ jobs:
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
with:
key: pdm-compat
- run: cargo build --locked -p socket-patch-cli
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/debug/socket-patch
target/debug/socket-patch.exe
path: target/pdm-e2e/
if-no-files-found: error
retention-days: 7

Expand All @@ -86,8 +102,10 @@ jobs:
fail-fast: false
matrix:
# Every stable PDM major family (0.x, 1.x, 2.x) and each 2.x lock-format
# boundary, on Linux and Windows; macOS samples the ends of the range.
os: [ubuntu-latest, windows-latest]
# 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' }
Expand Down Expand Up @@ -152,25 +170,37 @@ jobs:
# 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.
# 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: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
key: pdm-vex-capstone
# Only main writes the cache: 30 PR matrix cells saving would churn
# the repo's 10 GiB budget (ci.yml's rust-cache note).
save-if: ${{ github.ref == 'refs/heads/main' }}
pattern: pdm-cli-${{ matrix.os }}*
merge-multiple: true
path: target/pdm-e2e
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
with:
python-version: '3.12'
Expand All @@ -179,4 +209,11 @@ jobs:
env:
SOCKET_PATCH_PDM_E2E_REQUIRED: '1'
SOCKET_PATCH_PDM_E2E_VERSION: ${{ matrix.pdm }}
run: cargo test --locked -p socket-patch-cli --test e2e_vex_build -- 'pdm::' --ignored
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
2 changes: 1 addition & 1 deletion .github/workflows/pipenv-compatibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ on:
- 'crates/socket-patch-core/src/patch/redirect/pipenv.rs'
- 'crates/socket-patch-core/src/vendor/pypi_pipenv.rs'
- 'crates/socket-patch-core/src/vendor/pypi.rs'
- 'crates/socket-patch-core/src/vendor/lock_inventory.rs'
- 'crates/socket-patch-core/src/vendor/lock_inventory/**'
- 'crates/socket-patch-core/src/crawlers/python_crawler.rs'
- 'crates/socket-patch-core/src/utils/pipenv.rs'
- 'crates/socket-patch-cli/src/commands/scan/hosted.rs'
Expand Down
19 changes: 19 additions & 0 deletions .github/workflows/pnpm-compatibility.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
name: pnpm hosted compatibility

on:
# PRs: any crate source, but only the test files these capstones
# compile (a later `!` pattern excludes, a later plain one re-includes).
# Main pushes stay unfiltered.
pull_request:
paths:
- '.github/actions/upload-artifact/**'
- 'Cargo.lock'
- 'Cargo.toml'
- 'rust-toolchain.toml'
- '.cargo/config.toml'
- '.github/workflows/pnpm-compatibility.yml'
- 'crates/**'
- '!crates/**/*.md'
- '!crates/socket-patch-node/**'
- '!crates/socket-patch-core/tests/**'
- '!crates/socket-patch-cli/tests/**'
- 'crates/socket-patch-cli/tests/vex_e2e_common/**'
- 'crates/socket-patch-cli/tests/e2e_redirect_pnpm_build.rs'
- 'crates/socket-patch-cli/tests/e2e_vendor_pnpm_build.rs'
- 'crates/socket-patch-cli/tests/common/cache_env.rs'
push:
branches: [main]
workflow_dispatch:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/poetry-compatibility.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ permissions:

concurrency:
group: poetry-compat-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

env:
SOCKET_NO_CONFIG: '1'
Expand Down
24 changes: 5 additions & 19 deletions .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
name: Publish PyPI
run-name: "Publish PyPI ${{ inputs.version }}${{ inputs.distinct-id != '' && format(' [{0}]', inputs.distinct-id) || '' }}"

# Publishes socket-patch (platform wheels) + socket-patch-hook (pure-python
# .pth carrier) to PyPI for an existing v<version> release. Dispatched two
# Publishes socket-patch (platform wheels) to PyPI for an existing
# v<version> release. (The socket-patch-hook .pth wheel is no longer
# published: `setup` was removed in v5.) Dispatched two
# ways, both as a plain workflow_dispatch run:
# - by release.yml (scripts/dispatch-publish.sh), as one leg of the
# single-dispatch release fan-out — distinct-id carries the release
Expand Down Expand Up @@ -137,29 +138,14 @@ jobs:
- name: Copy README for PyPI package
run: cp README.md pypi/socket-patch/README.md

- name: Build wheels (platform socket-patch + pure-python socket-patch-hook)
- name: Build wheels (platform socket-patch)
env:
VERSION: ${{ inputs.version }}
run: |
# Builds the platform-tagged socket-patch wheels AND the pure-python
# socket-patch-hook wheel (the .pth carrier behind `socket-patch[hook]`).
python scripts/build-pypi-wheels.py --version "$VERSION" --artifacts artifacts --dist dist
# socket-patch and socket-patch-hook are two distinct PyPI projects.
# Publish each from its own dir so trusted publishing mints an OIDC
# token scoped to the right project (one upload spanning both projects
# can be rejected). Each needs its own trusted publisher on PyPI.
mkdir -p dist-hook
mv dist/socket_patch_hook-*.whl dist-hook/
run: python scripts/build-pypi-wheels.py --version "$VERSION" --artifacts artifacts --dist dist

- name: Publish socket-patch to PyPI
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
with:
packages-dir: dist/
# Idempotent for re-runs: already-uploaded files skip.
skip-existing: true

- name: Publish socket-patch-hook to PyPI
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
with:
packages-dir: dist-hook/
skip-existing: true
Loading
Loading