Skip to content

Commit 2463257

Browse files
feat!: consolidate the v5 patching workflow (#277)
Make scan and get use hosted patches by default, with live dependency files as hosted state and upstream restoration for rollback and remove. Share lockfile models, project snapshots and the hosted engine between disk and in-memory workflows. Use verified service artifacts and a shared backend for vendoring, repair, rollback and removal. Support manifest-free vendored projects, exact artifact reuse, release variants, Maven reactors and Gradle builds. Add socket.yml rollout policy, package and severity filters, directory targets and per-run limits on new patches. Rank patches by highest severity, then most distinct advisories fixed, then publication date; use the same policy for selection and upgrades. Expand lockfile discovery, package-manager compatibility and OpenVEX attestations. Reject multi-directory scans with a single VEX destination before writes, and require TLS 1.2 in CI host-pin handshakes. Remove setup, obsolete hooks and flags, and the PyPI/RubyGems CLI distributions. Consolidate usage, migration and configuration docs, simplify test suites, and run the full v5 compatibility tier on PRs. Keep the version bump and release publication in the separate release workflow. Co-authored-by: Claude <noreply@anthropic.com>
1 parent f6b7fb9 commit 2463257

793 files changed

Lines changed: 83448 additions & 237608 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.cargo/config.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Windows main threads get a 1 MiB stack reserve by default (Unix mains get
22
# 8 MiB). The CLI's async command futures poll deeply nested state machines
3-
# — scan → download → in-process apply, or scan --vendor → the vendor engine
3+
# — scan → download → in-process apply, or a vendored scan → the vendor engine
44
# — and in debug builds (no stack-slot reuse) the summed poll frames exceed
55
# 1 MiB, aborting with "thread 'main' has overflowed its stack" on Windows
66
# only. Raise the PE stack reserve to the Unix default; spawned threads are

‎.gitattributes‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ crates/socket-patch-core/tests/fixtures/redirect/** -text
66

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

9+
# Poetry and Pipenv locks are real `poetry lock` / `pipenv lock` output: the
10+
# upstream restore and VEX tests round-trip them byte for byte and derive
11+
# their CRLF variants from the LF bytes themselves.
12+
crates/socket-patch-core/tests/fixtures/poetry/** -text
13+
crates/socket-patch-core/tests/fixtures/pipenv/** -text
14+
crates/socket-patch-core/tests/fixtures/pipenv-shapes/** -text
15+
916
# The captured pnpm 1-12 locks are byte-real: the hosted/vendored rewriters
1017
# refuse CRLF by design (vendor_lockfile_crlf_unsupported), and the tests
1118
# derive their CRLF variants from the LF bytes themselves.
@@ -22,3 +29,7 @@ crates/socket-patch-core/tests/fixtures/vendor/** -text
2229
# compares the result byte for byte, so a CRLF checkout would change both
2330
# the replayed wiring files and the expected revert.
2431
crates/socket-patch-cli/tests/fixtures/legacy-ledgers/** -text
32+
33+
# The owned Gradle settings script is embedded with include_str! and
34+
# written into user repos byte for byte; a CRLF checkout would change it.
35+
crates/socket-patch-core/src/vendor/jvm/socket-patch.settings.gradle -text
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: Pin Socket patch hosts
2+
description: >-
3+
On macOS runners, resolve the production patch hosts once (system resolver,
4+
then DNS-over-HTTPS by IP literal), TLS-verify every address for its host,
5+
and pin them in /etc/hosts for the rest of the job
6+
inputs:
7+
hosts:
8+
description: Space-separated hostnames to pin
9+
default: patch.socket.dev patches-api.socket.dev
10+
runs:
11+
using: composite
12+
steps:
13+
# GitHub's hosted macOS runners intermittently answer patch.socket.dev
14+
# with EAI_NONAME ("[Errno 8] nodename nor servname provided", bun's
15+
# `FailedToOpenSocket`) for minutes at a time — at job start or mid-job —
16+
# while the service is up: the ubuntu / windows legs of the same run pass
17+
# and the same macOS cells pass before and after the window. A pre-flight
18+
# wait cannot cover a mid-job window and the failing processes are the
19+
# real package managers, not the CLI, so the job takes the runner's
20+
# resolver out of the path instead. Every request still goes to the
21+
# production service over TLS verified for the hostname.
22+
# scripts/pin-socket-hosts.py documents the resolution and verification.
23+
- name: Pin hosts
24+
if: runner.os == 'macOS'
25+
shell: bash
26+
env:
27+
PIN_HOSTS: ${{ inputs.hosts }}
28+
run: |
29+
set -euo pipefail
30+
# shellcheck disable=SC2086 # PIN_HOSTS is a space-separated list
31+
lines=$(python3 "$GITHUB_WORKSPACE/scripts/pin-socket-hosts.py" $PIN_HOSTS)
32+
printf '%s\n' "$lines"
33+
printf '\n# pinned by .github/actions/pin-socket-hosts\n%s\n' "$lines" | sudo tee -a /etc/hosts >/dev/null
34+
sudo dscacheutil -flushcache
35+
sudo killall -HUP mDNSResponder || true
36+
for host in $PIN_HOSTS; do
37+
got=$(python3 -c 'import socket, sys; print(" ".join(sorted({i[4][0] for i in socket.getaddrinfo(sys.argv[1], 443)})))' "$host" || true)
38+
echo "$host now resolves to: ${got:-nothing}"
39+
if [ -z "$got" ] || ! grep -qE "^(${got// /|}) $host\$" <<<"$lines"; then
40+
echo "::warning::$host does not resolve to its pinned address after pinning (got: ${got:-nothing})"
41+
fi
42+
done

‎.github/workflows/bun-compatibility.yml‎

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ on:
1717
pull_request:
1818
paths:
1919
- '.github/actions/upload-artifact/**'
20+
- '.github/actions/pin-socket-hosts/**'
21+
- 'scripts/pin-socket-hosts.py'
2022
- '.github/workflows/bun-compatibility.yml'
2123
- 'scripts/backtest-bun*.py'
2224
- 'scripts/probe-bun-historical-linux.py'
@@ -43,20 +45,22 @@ on:
4345
- 'crates/socket-patch-cli/src/commands/scan/**'
4446
- 'crates/socket-patch-cli/src/commands/rollback.rs'
4547
- 'crates/socket-patch-cli/src/commands/vendor.rs'
46-
- 'crates/socket-patch-cli/src/commands/repair_vendor.rs'
48+
- 'crates/socket-patch-cli/src/commands/vendored_backend/**'
4749
- 'crates/socket-patch-cli/src/commands/remove.rs'
4850
# Main runs are the only rust-cache writers (save-if below), so a
4951
# path-filtered push trigger is what seeds the cache the PR builds restore
5052
# (rust-cache keys on Cargo.lock, so Cargo.lock belongs here) and re-runs
5153
# the matrix post-merge on the code paths it exercises: the vendored engine
5254
# (`vendor/**` — bun_lock.rs, bun_lock_text.rs's shared version gate,
53-
# npm_flavor.rs, lock_inventory.rs), the hosted rewriter + unwinds, and the
55+
# npm_flavor.rs, lock_inventory/), the hosted rewriter + unwinds, and the
5456
# CLI drivers (`scan/**` — hosted.rs, vendor_flow.rs, mod.rs — plus the
5557
# vendor / repair / remove commands the matrix runs).
5658
push:
5759
branches: [main]
5860
paths:
5961
- '.github/workflows/bun-compatibility.yml'
62+
- '.github/actions/pin-socket-hosts/**'
63+
- 'scripts/pin-socket-hosts.py'
6064
- 'scripts/backtest-bun*.py'
6165
- 'scripts/probe-bun-historical-linux.py'
6266
- 'scripts/bun-historical-shas.json'
@@ -75,7 +79,7 @@ on:
7579
- 'crates/socket-patch-cli/src/commands/scan/**'
7680
- 'crates/socket-patch-cli/src/commands/rollback.rs'
7781
- 'crates/socket-patch-cli/src/commands/vendor.rs'
78-
- 'crates/socket-patch-cli/src/commands/repair_vendor.rs'
82+
- 'crates/socket-patch-cli/src/commands/vendored_backend/**'
7983
- 'crates/socket-patch-cli/src/commands/remove.rs'
8084
workflow_dispatch:
8185
inputs:
@@ -95,11 +99,11 @@ on:
9599
permissions:
96100
contents: read
97101

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

104108
env:
105109
CARGO_PROFILE_DEV_DEBUG: '0'
@@ -187,6 +191,11 @@ jobs:
187191
with:
188192
python-version: '3.12'
189193

194+
- name: Pin the production patch hosts (macOS)
195+
# The hosted macOS resolver intermittently loses patch.socket.dev for
196+
# minutes (EAI_NONAME) while the service is up; see the action.
197+
uses: ./.github/actions/pin-socket-hosts
198+
190199
- name: Download Bun ${{ matrix.bun }}
191200
id: bun
192201
# Pre-populate the exact directory layout the script's install_tool()

0 commit comments

Comments
 (0)