feat(scan): unified auto-update engine — --sync, --prune, --dry-run (v3.0) #131
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| permissions: | |
| contents: read | |
| jobs: | |
| clippy: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@efa25f7f19611383d5b0ccf2d1c8914531636bf9 # stable | |
| # toolchain version + components are read from rust-toolchain.toml. | |
| - name: Cache cargo | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ubuntu-latest-cargo-clippy-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: ubuntu-latest-cargo-clippy- | |
| - name: Run clippy | |
| run: cargo clippy --workspace --all-features -- -D warnings | |
| test: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@efa25f7f19611383d5b0ccf2d1c8914531636bf9 # stable | |
| # toolchain version is read from rust-toolchain.toml (exact-pinned). | |
| - name: Cache cargo | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ matrix.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: ${{ matrix.os }}-cargo- | |
| - name: Build | |
| run: cargo build --workspace --all-features | |
| - name: Run tests | |
| run: cargo test --workspace --all-features | |
| test-release: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@efa25f7f19611383d5b0ccf2d1c8914531636bf9 # stable | |
| # toolchain version is read from rust-toolchain.toml (exact-pinned). | |
| - name: Cache cargo | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ubuntu-latest-cargo-release-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: ubuntu-latest-cargo-release- | |
| - name: Run tests (release) | |
| run: cargo test --workspace --all-features --release | |
| coverage: | |
| # Code coverage via cargo-llvm-cov (LLVM source-based instrumentation). | |
| # Reports as a markdown table in the job summary and uploads the raw | |
| # lcov.info file as a workflow artifact. No threshold gating — this is | |
| # report-only so contributors get visibility without flaky CI when | |
| # coverage shifts naturally with test edits. | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@efa25f7f19611383d5b0ccf2d1c8914531636bf9 # stable | |
| with: | |
| # `llvm-tools-preview` is what cargo-llvm-cov uses to merge | |
| # `.profraw` files and emit lcov. The toolchain channel itself | |
| # is read from `rust-toolchain.toml`. | |
| components: llvm-tools-preview | |
| - name: Install cargo-llvm-cov | |
| # taiki-e/install-action ships precompiled binaries — much faster | |
| # than `cargo install` and avoids a per-CI-run compile. | |
| uses: taiki-e/install-action@65851e10cd6c377f11a60e600abc07cb08643468 # v2.79.3 | |
| with: | |
| tool: cargo-llvm-cov@0.8.7 | |
| - name: Cache cargo | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ubuntu-latest-cargo-coverage-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: ubuntu-latest-cargo-coverage- | |
| - name: Run tests with coverage | |
| # Two-step pattern: `--no-report` runs instrumented tests and | |
| # collects the raw profile data, then the two `report` calls | |
| # emit lcov + summary from the same data. Avoids re-running | |
| # tests twice. The output filename matches the `*.lcov` | |
| # gitignore pattern so a stray local run can't accidentally | |
| # commit a 600 KB report. | |
| # | |
| # Explicit feature list (instead of --all-features) excludes the | |
| # docker-e2e feature — those tests need Docker images this job | |
| # doesn't build. The coverage-docker matrix covers them | |
| # separately, and coverage-merge stitches everything together. | |
| run: | | |
| cargo llvm-cov --workspace \ | |
| --features cargo,golang,maven,composer,nuget \ | |
| --no-report | |
| cargo llvm-cov report --lcov --output-path coverage-host.lcov | |
| cargo llvm-cov report --summary-only | tee coverage-summary.txt | |
| - name: Publish coverage summary to job summary | |
| # Render the per-file table cargo-llvm-cov prints as a fenced | |
| # block in the GitHub Actions job summary so reviewers don't | |
| # need to crack open the artifact for a quick look. | |
| run: | | |
| { | |
| echo "## Host coverage summary" | |
| echo "" | |
| echo "(In-process tests only. See coverage-merge for the" | |
| echo "full picture including docker-e2e binary coverage.)" | |
| echo "" | |
| echo '```' | |
| cat coverage-summary.txt | |
| echo '```' | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| - name: Upload host LCOV artifact | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: coverage-host | |
| path: coverage-host.lcov | |
| if-no-files-found: error | |
| retention-days: 30 | |
| coverage-docker: | |
| # Per-ecosystem coverage for the Docker-driven e2e suite. Mirrors | |
| # the e2e-docker matrix but builds an instrumented socket-patch | |
| # binary and mounts it into the container along with a host- | |
| # visible profraw directory, so the in-container code paths | |
| # contribute to the lcov merge. | |
| # | |
| # Hooks: docker_e2e_<eco>.rs reads SOCKET_PATCH_COV_BIN + | |
| # SOCKET_PATCH_COV_PROFRAW_DIR. Both unset is the no-op default | |
| # (used by the e2e-docker matrix above). | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ecosystem: [npm, pypi, gem, cargo, golang, maven, composer, nuget] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@efa25f7f19611383d5b0ccf2d1c8914531636bf9 # stable | |
| with: | |
| components: llvm-tools-preview | |
| - name: Install cargo-llvm-cov | |
| uses: taiki-e/install-action@65851e10cd6c377f11a60e600abc07cb08643468 # v2.79.3 | |
| with: | |
| tool: cargo-llvm-cov@0.8.7 | |
| - name: Cache cargo | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ubuntu-latest-cargo-coverage-docker-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: ubuntu-latest-cargo-coverage-docker- | |
| - name: Build base image | |
| uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 | |
| with: | |
| context: . | |
| file: tests/docker/Dockerfile.base | |
| tags: socket-patch-test-base:latest | |
| load: true | |
| cache-from: type=gha,scope=test-base | |
| cache-to: type=gha,scope=test-base,mode=max | |
| - name: Build ${{ matrix.ecosystem }} image | |
| uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 | |
| with: | |
| context: . | |
| file: tests/docker/Dockerfile.${{ matrix.ecosystem }} | |
| tags: socket-patch-test-${{ matrix.ecosystem }}:latest | |
| load: true | |
| cache-from: type=gha,scope=test-${{ matrix.ecosystem }} | |
| cache-to: type=gha,scope=test-${{ matrix.ecosystem }},mode=max | |
| - name: Build instrumented socket-patch binary | |
| # Source `cargo llvm-cov show-env` into the current shell so this | |
| # `cargo build` picks up RUSTC_WRAPPER=cargo-llvm-cov and the | |
| # same RUSTFLAGS that the subsequent `cargo llvm-cov` test step | |
| # will use. The bin we build ends up byte-compatible with the | |
| # test binaries — same source hashes → unified coverage map at | |
| # report time. Env stays scoped to this step (intentional; | |
| # cargo llvm-cov manages its own env in the test step). | |
| run: | | |
| eval "$(cargo llvm-cov show-env --export-prefix 2>/dev/null)" | |
| cargo build --bin socket-patch --features cargo,golang,maven,composer,nuget | |
| - name: Configure docker-e2e coverage hooks | |
| run: | | |
| echo "SOCKET_PATCH_COV_BIN=$PWD/target/debug/socket-patch" >> "$GITHUB_ENV" | |
| # Profraw files from the in-container binary land here. | |
| # cargo-llvm-cov scans target/ for *.profraw at report time. | |
| echo "SOCKET_PATCH_COV_PROFRAW_DIR=$PWD/target" >> "$GITHUB_ENV" | |
| - name: Run ${{ matrix.ecosystem }} Docker e2e test with coverage | |
| run: | | |
| cargo llvm-cov \ | |
| --features docker-e2e,cargo,golang,maven,composer,nuget \ | |
| --no-report \ | |
| --test docker_e2e_${{ matrix.ecosystem }} | |
| - name: Generate per-ecosystem lcov | |
| run: | | |
| cargo llvm-cov report \ | |
| --lcov \ | |
| --output-path coverage-docker-${{ matrix.ecosystem }}.lcov | |
| - name: Upload per-ecosystem LCOV artifact | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: coverage-docker-${{ matrix.ecosystem }} | |
| path: coverage-docker-${{ matrix.ecosystem }}.lcov | |
| if-no-files-found: error | |
| retention-days: 30 | |
| coverage-merge: | |
| # Merge the host coverage and per-ecosystem docker coverage into a | |
| # single lcov.info. lcov(1) handles the union — same files are | |
| # summed line-by-line so a line covered by ANY test counts. | |
| needs: [coverage, coverage-docker] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Install lcov | |
| run: sudo apt-get update && sudo apt-get install -y lcov | |
| - name: Download all coverage artifacts | |
| uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 | |
| with: | |
| path: coverage-artifacts | |
| pattern: coverage-* | |
| - name: Merge LCOV files | |
| # `--add-tracefile` is repeated per input. lcov sums hit counts | |
| # for identical source/line keys, so files covered by both host | |
| # and docker tests report the higher (union) count. | |
| # `find` (not bash globstar) for portability across runners. | |
| run: | | |
| set -e | |
| ARGS=() | |
| while IFS= read -r f; do | |
| ARGS+=(--add-tracefile "$f") | |
| done < <(find coverage-artifacts -name '*.lcov' -type f) | |
| if [ ${#ARGS[@]} -eq 0 ]; then | |
| echo "No lcov files found to merge" >&2 | |
| exit 1 | |
| fi | |
| lcov "${ARGS[@]}" --output-file coverage.lcov | |
| - name: Render summary | |
| # `lcov --summary` prints a per-file rollup we tee into the job | |
| # summary, same shape as cargo-llvm-cov's own. | |
| run: | | |
| { | |
| echo "## Coverage (host + docker-e2e merged)" | |
| echo "" | |
| echo '```' | |
| lcov --summary coverage.lcov 2>&1 | tail -20 | |
| echo '```' | |
| echo "" | |
| echo "Full merged LCOV uploaded as the \`coverage-lcov\` artifact." | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| - name: Upload merged LCOV artifact | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 | |
| with: | |
| name: coverage-lcov | |
| path: coverage.lcov | |
| if-no-files-found: error | |
| retention-days: 30 | |
| dispatch-tests: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: '20.20.2' | |
| - name: Run npm dispatch tests | |
| run: node --test npm/socket-patch/bin/socket-patch.test.mjs | |
| - name: Setup Python | |
| uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: '3.12.13' | |
| - name: Run pypi dispatch tests | |
| run: python pypi/socket-patch/test_dispatch.py | |
| e2e: | |
| needs: test | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| suite: e2e_npm | |
| - os: ubuntu-latest | |
| suite: e2e_pypi | |
| - os: ubuntu-latest | |
| suite: e2e_cargo | |
| - os: ubuntu-latest | |
| suite: e2e_golang | |
| - os: ubuntu-latest | |
| suite: e2e_maven | |
| - os: ubuntu-latest | |
| suite: e2e_gem | |
| - os: ubuntu-latest | |
| suite: e2e_composer | |
| - os: ubuntu-latest | |
| suite: e2e_nuget | |
| - os: macos-latest | |
| suite: e2e_npm | |
| - os: macos-latest | |
| suite: e2e_pypi | |
| - os: ubuntu-latest | |
| suite: e2e_scan | |
| - os: macos-latest | |
| suite: e2e_scan | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@efa25f7f19611383d5b0ccf2d1c8914531636bf9 # stable | |
| # toolchain version is read from rust-toolchain.toml (exact-pinned). | |
| - name: Cache cargo | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ${{ matrix.os }}-cargo-e2e-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: ${{ matrix.os }}-cargo-e2e- | |
| - name: Setup Node.js | |
| if: matrix.suite == 'e2e_npm' || matrix.suite == 'e2e_scan' | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: '20.20.2' | |
| - name: Setup Python | |
| if: matrix.suite == 'e2e_pypi' | |
| uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 | |
| with: | |
| python-version: '3.12.13' | |
| - name: Setup Ruby | |
| if: matrix.suite == 'e2e_gem' | |
| uses: ruby/setup-ruby@319994f95fa847cf3fb3cd3dbe89f6dcde9f178f # v1.295.0 | |
| with: | |
| ruby-version: '3.2.11' | |
| bundler-cache: false | |
| - name: Run e2e tests | |
| run: cargo test -p socket-patch-cli --all-features --test ${{ matrix.suite }} -- --ignored | |
| # ---------------------------------------------------------------------- | |
| # Docker-driven real-package e2e suite. | |
| # | |
| # For each ecosystem, builds the shared base image (multi-stage: | |
| # Rust → debian + compiled socket-patch) and the per-ecosystem layer, | |
| # then runs the matching `docker_e2e_<eco>` test binary inside the | |
| # repo's checkout. Tests install real packages via real package | |
| # managers and run socket-patch against a wiremock-served fixture — | |
| # no real Socket API contact. Hermetic, reproducible. | |
| # | |
| # Triggered on every PR. The existing `e2e` job above stays for | |
| # `--ignored` real-API smoke runs (manual / scheduled). | |
| # ---------------------------------------------------------------------- | |
| e2e-docker: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| ecosystem: [npm, pypi, gem, cargo, golang, maven, composer, nuget] | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@efa25f7f19611383d5b0ccf2d1c8914531636bf9 # stable | |
| # toolchain version is read from rust-toolchain.toml. | |
| - name: Cache cargo | |
| uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 | |
| with: | |
| path: | | |
| ~/.cargo/registry | |
| ~/.cargo/git | |
| target | |
| key: ubuntu-latest-cargo-e2e-docker-${{ hashFiles('**/Cargo.lock') }} | |
| restore-keys: ubuntu-latest-cargo-e2e-docker- | |
| - name: Build base image | |
| uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 | |
| with: | |
| context: . | |
| file: tests/docker/Dockerfile.base | |
| tags: socket-patch-test-base:latest | |
| load: true | |
| cache-from: type=gha,scope=test-base | |
| cache-to: type=gha,scope=test-base,mode=max | |
| - name: Build ${{ matrix.ecosystem }} image | |
| uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0 | |
| with: | |
| context: . | |
| file: tests/docker/Dockerfile.${{ matrix.ecosystem }} | |
| tags: socket-patch-test-${{ matrix.ecosystem }}:latest | |
| load: true | |
| cache-from: type=gha,scope=test-${{ matrix.ecosystem }} | |
| cache-to: type=gha,scope=test-${{ matrix.ecosystem }},mode=max | |
| - name: Run ${{ matrix.ecosystem }} Docker e2e test | |
| run: cargo test -p socket-patch-cli --features docker-e2e --test docker_e2e_${{ matrix.ecosystem }} |