|
| 1 | +name: bughunt-nuget |
| 2 | +on: |
| 3 | + push: |
| 4 | + branches: ['bughunt/nuget/**'] |
| 5 | +permissions: |
| 6 | + contents: read |
| 7 | +jobs: |
| 8 | + probe: |
| 9 | + strategy: |
| 10 | + fail-fast: false |
| 11 | + matrix: |
| 12 | + os: [ubuntu-latest, macos-latest, windows-latest] |
| 13 | + dotnet: ['8', '10'] |
| 14 | + runs-on: ${{ matrix.os }} |
| 15 | + timeout-minutes: 45 |
| 16 | + steps: |
| 17 | + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 |
| 18 | + - run: rustup show |
| 19 | + - uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6.0.0 |
| 20 | + with: |
| 21 | + dotnet-version: ${{ matrix.dotnet }}.0.x |
| 22 | + - name: Write probe files |
| 23 | + shell: bash |
| 24 | + run: | |
| 25 | + src=crates/socket-patch-cli/tests/e2e_nuget_dotnet_build.rs |
| 26 | + head -n $(($(grep -n '^// ── hosted ──' $src | cut -d: -f1)-1)) $src > crates/socket-patch-cli/tests/e2e_scratch_nuget.rs |
| 27 | + cat >> crates/socket-patch-cli/tests/e2e_scratch_nuget.rs <<'RSEOF' |
| 28 | + #[test] |
| 29 | + #[ignore] |
| 30 | + fn scratch_serve() { |
| 31 | + let sb = Sandbox::new(); |
| 32 | + let dn = Dotnet::probe("scratch", &sb).unwrap(); |
| 33 | + let out = PathBuf::from(std::env::var("SCRATCH_OUT").unwrap()); |
| 34 | + std::fs::create_dir_all(&out).unwrap(); |
| 35 | + let fixture = sb.dir("fixture"); |
| 36 | + let store_fx = sb.dir("store-fixture"); |
| 37 | + let _ = restore_fixture(&dn, &sb, &fixture, &store_fx); |
| 38 | + let pristine = std::fs::read(pkg_dir(&store_fx).join(FILE_KEY)).unwrap(); |
| 39 | + let mut patched = pristine.clone(); |
| 40 | + patched.extend_from_slice(MARKER); |
| 41 | + let upstream = std::fs::read(pkg_dir(&store_fx).join(NUPKG_NAME)).unwrap(); |
| 42 | + let nupkg = patched_nupkg(&upstream, &patched); |
| 43 | + let uuid = std::env::var("SCRATCH_UUID").unwrap_or(VENDORED_UUID.to_string()); |
| 44 | + let backend = Backend::start(&uuid, &pristine, &patched, Some(&nupkg)); |
| 45 | + std::fs::write(out.join("pristine"), &pristine).unwrap(); |
| 46 | + std::fs::write(out.join("patched"), &patched).unwrap(); |
| 47 | + std::fs::write(out.join("patched.nupkg"), &nupkg).unwrap(); |
| 48 | + std::fs::write(out.join("hash_patched"), content_hash(&nupkg)).unwrap(); |
| 49 | + std::fs::write(out.join("hash_upstream"), content_hash(&upstream)).unwrap(); |
| 50 | + std::fs::write(out.join("uri"), backend.uri()).unwrap(); |
| 51 | + if let Ok(script) = std::env::var("SCRATCH_SCRIPT") { |
| 52 | + let bash = std::env::var("SCRATCH_BASH").unwrap_or("bash".into()); |
| 53 | + let st = Command::new(bash).arg(script) |
| 54 | + .env("SCRATCH_SP", binary()).env("SCRATCH_WORK", sb.root()) |
| 55 | + .env("SCRATCH_MAJOR", dn.major.to_string()) |
| 56 | + .status().unwrap(); |
| 57 | + println!("probe script exit {st:?}"); |
| 58 | + return; |
| 59 | + } |
| 60 | + while !out.join("stop").exists() { |
| 61 | + std::thread::sleep(std::time::Duration::from_millis(500)); |
| 62 | + } |
| 63 | + } |
| 64 | + RSEOF |
| 65 | + mkdir -p "$RUNNER_TEMP/probe" |
| 66 | + cat > "$RUNNER_TEMP/probe/probe.sh" <<'SHEOF' |
| 67 | + #!/usr/bin/env bash |
| 68 | + # Probe cells: (A) vendored + autocrlf checkout -> vendor --revert/remove; (B) #514 named lock. |
| 69 | + set -u |
| 70 | + up(){ if command -v cygpath >/dev/null 2>&1; then cygpath -u "$1"; else echo "$1"; fi; } |
| 71 | + O="$(up "$SCRATCH_OUT")"; URI=$(cat "$O/uri"); SP="$(up "$SCRATCH_SP")"; W="$(up "$SCRATCH_WORK")"; MAJ="$SCRATCH_MAJOR" |
| 72 | + wp(){ if command -v cygpath >/dev/null 2>&1; then cygpath -w "$1"; else echo "$1"; fi; } |
| 73 | + export DOTNET_CLI_TELEMETRY_OPTOUT=1 DOTNET_NOLOGO=1 SOCKET_TELEMETRY_DISABLED=1 SOCKET_NO_CONFIG=1 |
| 74 | + export NUGET_HTTP_CACHE_PATH="$(wp "$W/httpcache")" |
| 75 | + mkproj(){ rm -rf "$1"; mkdir -p "$1"; cd "$1" |
| 76 | + printf '<Project Sdk="Microsoft.NET.Sdk">\n <PropertyGroup>\n <TargetFramework>net%s.0</TargetFramework>\n <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>\n <NuGetAudit>false</NuGetAudit>\n </PropertyGroup>\n <ItemGroup>\n <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />\n </ItemGroup>\n</Project>\n' "$MAJ" > app.csproj |
| 77 | + printf '<?xml version="1.0" encoding="utf-8"?>\n<configuration>\n <packageSources>\n <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />\n </packageSources>\n</configuration>\n' > nuget.config |
| 78 | + cp "$W/global.json" . 2>/dev/null || true; } |
| 79 | + rst(){ local st="$1"; shift; NUGET_PACKAGES="$(wp "$st")" dotnet restore -p:NuGetAudit=false "$@" > "$W/r.log" 2>&1; local rc=$?; grep -E "error NU[0-9]+" "$W/r.log" | head -1; echo "restore $* rc=$rc"; } |
| 80 | + chk(){ local f="$1/newtonsoft.json/13.0.3/LICENSE.md"; if cmp -s "$f" "$O/patched"; then echo "INSTALLED: PATCHED"; elif cmp -s "$f" "$O/pristine"; then echo "INSTALLED: PRISTINE"; else echo "INSTALLED: none"; fi; } |
| 81 | + sp(){ NUGET_PACKAGES="$(wp "$STORE")" "$SP" "$@" --api-url "$URI" --org test-org --api-token fake-token; } |
| 82 | + spn(){ NUGET_PACKAGES="$(wp "$STORE")" "$SP" "$@"; } |
| 83 | + codes(){ grep -oE '"(errorCode|status|code)": *"[a-zA-Z_]*"' "$1" | tr '\n' ' '; echo; } |
| 84 | + echo "### OS=${RUNNER_OS:-local} SDK=$(dotnet --version) git autocrlf(global/system)=$(git config --get core.autocrlf || echo unset)" |
| 85 | + git config --global user.email a@b; git config --global user.name a |
| 86 | + # (A) |
| 87 | + STORE="$W/stA"; mkproj "$W/A"; rst "$STORE" |
| 88 | + sp scan --mode vendored --vendor-source service --json --yes > "$W/A.scan.json" 2>/dev/null; echo "A scan rc=$?"; codes "$W/A.scan.json" |
| 89 | + printf 'bin/\nobj/\n' > .gitignore; git init -q . && git add -A && git commit -qm v |
| 90 | + for c in revert remove rollback rescan-revert; do |
| 91 | + echo "--- A/$c"; cd "$W"; rm -rf "$W/A-$c"; git clone -q -c core.autocrlf=true "$W/A" "$W/A-$c"; cd "$W/A-$c" |
| 92 | + file nuget.config | sed 's/.*: //' |
| 93 | + rm -rf "$W/stA0"; rst "$W/stA0" --locked-mode; chk "$W/stA0" |
| 94 | + case $c in |
| 95 | + revert) spn vendor --revert --json;; remove) spn remove pkg:nuget/Newtonsoft.Json@13.0.3 --json;; rollback) spn rollback --json;; |
| 96 | + rescan-revert) sp scan --mode vendored --vendor-source service --json --yes >/dev/null 2>&1; echo "rescan rc=$?"; spn vendor --revert --json;; |
| 97 | + esac > "$W/A-$c.json" 2>/dev/null; echo "$c rc=$?"; codes "$W/A-$c.json" |
| 98 | + echo "git status: $(git status --short | tr '\n' ' ')"; echo "socket-patch refs in nuget.config: $(grep -c socket-patch nuget.config)" |
| 99 | + rm -rf obj "$W/stA1"; rst "$W/stA1" --locked-mode; chk "$W/stA1" |
| 100 | + done |
| 101 | + # (B) #514 named lock, vendored |
| 102 | + echo "--- B named lock"; STORE="$W/stB"; mkproj "$W/B"; rst "$STORE"; mv packages.lock.json packages.app.lock.json; rm -rf obj; rst "$STORE" --locked-mode; ls packages*.json |
| 103 | + sp scan --mode vendored --vendor-source service --json --yes > "$W/B.json" 2>/dev/null; echo "B scan rc=$?"; codes "$W/B.json" |
| 104 | + mkdir -p "$W/B2"; cp -r app.csproj nuget.config packages.app.lock.json .socket "$W/B2/"; cd "$W/B2"; rm -rf "$W/stB2"; rst "$W/stB2" --locked-mode; chk "$W/stB2"; rm -rf obj; rst "$W/stB2" |
| 105 | + # (B') custom NuGetLockFilePath |
| 106 | + echo "--- B' NuGetLockFilePath"; STORE="$W/stC"; mkproj "$W/C"; sed -i.bak 's#<NuGetAudit>false</NuGetAudit>#<NuGetAudit>false</NuGetAudit>\n <NuGetLockFilePath>locks/app.lock.json</NuGetLockFilePath>#' app.csproj; rm -f app.csproj.bak; rst "$STORE"; ls locks packages*.json 2>&1 | tr '\n' ' '; echo |
| 107 | + sp scan --mode vendored --vendor-source service --json --yes > "$W/C.json" 2>/dev/null; echo "C scan rc=$?"; codes "$W/C.json" |
| 108 | + mkdir -p "$W/C2"; cp -r app.csproj nuget.config locks .socket "$W/C2/"; cd "$W/C2"; rm -rf "$W/stC2"; rst "$W/stC2" --locked-mode; chk "$W/stC2" |
| 109 | + echo "### done" |
| 110 | + SHEOF |
| 111 | + - name: Run probe |
| 112 | + shell: bash |
| 113 | + env: |
| 114 | + SOCKET_PATCH_DOTNET_E2E_REQUIRED: '1' |
| 115 | + SOCKET_PATCH_DOTNET_E2E_VERSION: ${{ matrix.dotnet }} |
| 116 | + run: | |
| 117 | + wp(){ if command -v cygpath >/dev/null 2>&1; then cygpath -w "$1"; else echo "$1"; fi; } |
| 118 | + echo "system autocrlf: $(git config --system --get core.autocrlf || echo unset)" |
| 119 | + mkdir -p "$RUNNER_TEMP/out" |
| 120 | + export SCRATCH_OUT="$(wp "$RUNNER_TEMP/out")" SCRATCH_SCRIPT="$(wp "$RUNNER_TEMP/probe/probe.sh")" SCRATCH_BASH="$(wp "$(command -v bash)")" |
| 121 | + cargo test --release -p socket-patch-cli --test e2e_scratch_nuget -- --ignored --nocapture 2>&1 | sed -n '/^running 1 test/,$p' |
0 commit comments