up
Some checks failed
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Some checks failed
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Policy Simulation / policy-simulate (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Docs CI / lint-and-preview (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
This commit is contained in:
@@ -196,6 +196,25 @@ public sealed class BunLanguageAnalyzerTests
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PatchedMultiVersionIsParsedAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "bun", "patched-multi-version");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new BunLanguageAnalyzer()
|
||||
};
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeepDependencyTreeIsParsedAsync()
|
||||
{
|
||||
@@ -252,4 +271,80 @@ public sealed class BunLanguageAnalyzerTests
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ContainerLayersAreDiscoveredAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "bun", "container-layers");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new BunLanguageAnalyzer()
|
||||
};
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BunfigOnlyEmitsDeclaredOnlyAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "bun", "bunfig-only");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new BunLanguageAnalyzer()
|
||||
};
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LockfileDevClassificationIsDeterministicAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "bun", "lockfile-dev-classification");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new BunLanguageAnalyzer()
|
||||
};
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task NonConcreteVersionsUseExplicitKeyAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "bun", "non-concrete-versions");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new BunLanguageAnalyzer()
|
||||
};
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
[install]
|
||||
cache = false
|
||||
@@ -0,0 +1,74 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "bun",
|
||||
"componentKey": "explicit::bun::npm::left-pad::sha256:8ad9c18ee1a619ce3a224346fe984c4ced211ac443ebf7d709a93f1343ef8ba2",
|
||||
"name": "left-pad",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "package.json#dependencies",
|
||||
"declared.scope": "prod",
|
||||
"declared.source": "package.json",
|
||||
"declared.sourceType": "range",
|
||||
"declared.versionSpec": "^1.3.0",
|
||||
"declaredOnly": "true",
|
||||
"packageManager": "bun"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "package.json",
|
||||
"sha256": "465919e1195aa0b066f473c55341df77abff6a6b7d62e25d63ccfb7c13e3287b"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "bun",
|
||||
"componentKey": "explicit::bun::npm::local-file::sha256:61b6ef7b8e24fe3a1e1080296c61f2ca4ad8839f453e24cb8adf874678521caa",
|
||||
"name": "local-file",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "package.json#dependencies",
|
||||
"declared.scope": "prod",
|
||||
"declared.source": "package.json",
|
||||
"declared.sourceType": "file",
|
||||
"declared.versionSpec": "file:../local-file",
|
||||
"declaredOnly": "true",
|
||||
"packageManager": "bun"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "package.json",
|
||||
"sha256": "465919e1195aa0b066f473c55341df77abff6a6b7d62e25d63ccfb7c13e3287b"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "bun",
|
||||
"componentKey": "explicit::bun::npm::typescript::sha256:5a0a88f051ea20b8875334dadc5bce3c0861d146b151ab7bab95654541b7a168",
|
||||
"name": "typescript",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "package.json#devDependencies",
|
||||
"declared.scope": "dev",
|
||||
"declared.source": "package.json",
|
||||
"declared.sourceType": "range",
|
||||
"declared.versionSpec": "~5.3.0",
|
||||
"declaredOnly": "true",
|
||||
"packageManager": "bun"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "package.json",
|
||||
"sha256": "465919e1195aa0b066f473c55341df77abff6a6b7d62e25d63ccfb7c13e3287b"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "bunfig-only-fixture",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"left-pad": "^1.3.0",
|
||||
"local-file": "file:../local-file"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "~5.3.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"packages": {
|
||||
"ms@2.1.3": ["https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "bun-container-layers-fixture",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"ms": "^2.1.3"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "bun",
|
||||
"componentKey": "purl::pkg:npm/ms@2.1.3",
|
||||
"purl": "pkg:npm/ms@2.1.3",
|
||||
"name": "ms",
|
||||
"version": "2.1.3",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"direct": "true",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"packageManager": "bun",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"source": "bun.lock"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "integrity",
|
||||
"locator": ".layers/layer0/app/bun.lock:packages[ms@2.1.3]",
|
||||
"value": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"sha256": "4a384b14aba7740bd500cdf0da7329a41a2940662e9b1fcab1fbc71c6c8389e7"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": ".layers/layer0/app/bun.lock:packages[ms@2.1.3]",
|
||||
"value": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"sha256": "4a384b14aba7740bd500cdf0da7329a41a2940662e9b1fcab1fbc71c6c8389e7"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -22,20 +22,23 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node_modules",
|
||||
"locator": "node_modules/@company/internal-pkg/package.json"
|
||||
"locator": "node_modules/@company/internal-pkg/package.json",
|
||||
"sha256": "f5311f43a95bd76e1912dbd7d0a5b3611baa9e82bcf72d5dc7f34c5f71f0ddf4"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "integrity",
|
||||
"locator": "bun.lock",
|
||||
"value": "sha512-customhash123=="
|
||||
"locator": "bun.lock:packages[@company/internal-pkg@1.0.0]",
|
||||
"value": "sha512-customhash123==",
|
||||
"sha256": "eb3bacf736d4a1b3cf9e02357afc1add9f20323916ce62cf8748c9ad9a80f195"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock",
|
||||
"value": "https://npm.company.com/@company/internal-pkg/-/internal-pkg-1.0.0.tgz"
|
||||
"locator": "bun.lock:packages[@company/internal-pkg@1.0.0]",
|
||||
"value": "https://npm.company.com/@company/internal-pkg/-/internal-pkg-1.0.0.tgz",
|
||||
"sha256": "eb3bacf736d4a1b3cf9e02357afc1add9f20323916ce62cf8748c9ad9a80f195"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -19,19 +19,22 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node_modules",
|
||||
"locator": "node_modules/debug/package.json"
|
||||
"locator": "node_modules/debug/package.json",
|
||||
"sha256": "2258b5b4d7e5ed711aeef1a86d5d9e5abf2a04410e05bd89ea806e423417e493"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "integrity",
|
||||
"locator": "bun.lock",
|
||||
"value": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX\u002B7G/vCNNhehwxfkQ=="
|
||||
"locator": "bun.lock:packages[debug@4.3.4]",
|
||||
"value": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX\u002B7G/vCNNhehwxfkQ==",
|
||||
"sha256": "33d4886c0591242ffb78b5e739c5248c81559312586d59d543d48387e4bb6a2b"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock",
|
||||
"value": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz"
|
||||
"locator": "bun.lock:packages[debug@4.3.4]",
|
||||
"value": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"sha256": "33d4886c0591242ffb78b5e739c5248c81559312586d59d543d48387e4bb6a2b"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -54,20 +57,23 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node_modules",
|
||||
"locator": "node_modules/ms/package.json"
|
||||
"locator": "node_modules/ms/package.json",
|
||||
"sha256": "ae11c4ce44027a95893e8c890aed0c582f04e8cf1b8022931eddcb613cd9d3f7"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "integrity",
|
||||
"locator": "bun.lock",
|
||||
"value": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
"locator": "bun.lock:packages[ms@2.1.3]",
|
||||
"value": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"sha256": "33d4886c0591242ffb78b5e739c5248c81559312586d59d543d48387e4bb6a2b"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock",
|
||||
"value": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz"
|
||||
"locator": "bun.lock:packages[ms@2.1.3]",
|
||||
"value": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"sha256": "33d4886c0591242ffb78b5e739c5248c81559312586d59d543d48387e4bb6a2b"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -21,14 +21,16 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node_modules",
|
||||
"locator": "node_modules/my-git-pkg/package.json"
|
||||
"locator": "node_modules/my-git-pkg/package.json",
|
||||
"sha256": "45687abed9d301c361987ca877da135e830c80dc3ce37f9ea1c74c7df96b8bf2"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock",
|
||||
"value": "git\u002Bhttps://github.com/user/my-git-pkg.git#abc123def456"
|
||||
"locator": "bun.lock:packages[my-git-pkg@1.0.0]",
|
||||
"value": "git\u002Bhttps://github.com/user/my-git-pkg.git#abc123def456",
|
||||
"sha256": "819a7efc185bd1314d21aa7fdc0e5b2134a0c9b758ecd9daa62cb6cba2feddd0"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -18,19 +18,22 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node_modules",
|
||||
"locator": "node_modules/.bun/is-number@6.0.0/package.json"
|
||||
"locator": "node_modules/.bun/is-number@6.0.0/package.json",
|
||||
"sha256": "0324c895ec4aa4049c77371f08e937eed97a58e442595a8834ba21afd8e100b3"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "integrity",
|
||||
"locator": "bun.lock",
|
||||
"value": "sha512-Wu1VZAVuL1snqOnHLxJ0l2p3pjlzLnMcJ8gJhaTZVfP7VFKN7fSJ8X/gR0qFCLwfFJ0Rqd3IxfS\u002BTY/Lc1Q7Pw=="
|
||||
"locator": "bun.lock:packages[is-number@6.0.0]",
|
||||
"value": "sha512-Wu1VZAVuL1snqOnHLxJ0l2p3pjlzLnMcJ8gJhaTZVfP7VFKN7fSJ8X/gR0qFCLwfFJ0Rqd3IxfS\u002BTY/Lc1Q7Pw==",
|
||||
"sha256": "746b6c809e50ee2d7bdb27a0ee43046d48fa5f21d7597bbadd3bd44269798812"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock",
|
||||
"value": "https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz"
|
||||
"locator": "bun.lock:packages[is-number@6.0.0]",
|
||||
"value": "https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz",
|
||||
"sha256": "746b6c809e50ee2d7bdb27a0ee43046d48fa5f21d7597bbadd3bd44269798812"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -54,20 +57,23 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node_modules",
|
||||
"locator": "node_modules/.bun/is-odd@3.0.1/package.json"
|
||||
"locator": "node_modules/.bun/is-odd@3.0.1/package.json",
|
||||
"sha256": "beb18158821ecb86f3bb2a6be3ef817c0b8dcdc3e05a53e0b9a1c62d74a595ac"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "integrity",
|
||||
"locator": "bun.lock",
|
||||
"value": "sha512-CQpnWPrDwmP1\u002BSMHXvTXAoSEu2mCPgMU0VKt1WcA7D8VXCo4HfVNlUbD1k8Tg0BVDX/LhyRaZqKqiS4vI6tTHg=="
|
||||
"locator": "bun.lock:packages[is-odd@3.0.1]",
|
||||
"value": "sha512-CQpnWPrDwmP1\u002BSMHXvTXAoSEu2mCPgMU0VKt1WcA7D8VXCo4HfVNlUbD1k8Tg0BVDX/LhyRaZqKqiS4vI6tTHg==",
|
||||
"sha256": "746b6c809e50ee2d7bdb27a0ee43046d48fa5f21d7597bbadd3bd44269798812"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock",
|
||||
"value": "https://registry.npmjs.org/is-odd/-/is-odd-3.0.1.tgz"
|
||||
"locator": "bun.lock:packages[is-odd@3.0.1]",
|
||||
"value": "https://registry.npmjs.org/is-odd/-/is-odd-3.0.1.tgz",
|
||||
"sha256": "746b6c809e50ee2d7bdb27a0ee43046d48fa5f21d7597bbadd3bd44269798812"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -19,20 +19,23 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node_modules",
|
||||
"locator": "node_modules/lodash/package.json"
|
||||
"locator": "node_modules/lodash/package.json",
|
||||
"sha256": "82145cd4bdc9a690c14843b405179c60aeda1a958029f6ae62776c1b26e42169"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "integrity",
|
||||
"locator": "bun.lock",
|
||||
"value": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vz1kAmtILi\u002B8fm9nJMg7b0GN8sMEJz2mxG/S7mNxhWQ7\u002BD9bF8Q=="
|
||||
"locator": "bun.lock:packages[lodash@4.17.21]",
|
||||
"value": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vz1kAmtILi\u002B8fm9nJMg7b0GN8sMEJz2mxG/S7mNxhWQ7\u002BD9bF8Q==",
|
||||
"sha256": "7b34fdbdf0cb3e0d07e25f7d7f452491dcfad421138449217a1c20b2f66a6475"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock",
|
||||
"value": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
|
||||
"locator": "bun.lock:packages[lodash@4.17.21]",
|
||||
"value": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"sha256": "7b34fdbdf0cb3e0d07e25f7d7f452491dcfad421138449217a1c20b2f66a6475"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"packages": {
|
||||
"prod-pkg@1.0.0": ["https://registry.npmjs.org/prod-pkg/-/prod-pkg-1.0.0.tgz", null, {"shared": "^1.0.0"}],
|
||||
"dev-pkg@1.0.0": ["https://registry.npmjs.org/dev-pkg/-/dev-pkg-1.0.0.tgz", null, {"dev-only": "^1.0.0"}],
|
||||
"shared@1.0.0": ["https://registry.npmjs.org/shared/-/shared-1.0.0.tgz", null],
|
||||
"dev-only@1.0.0": ["https://registry.npmjs.org/dev-only/-/dev-only-1.0.0.tgz", null]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "bun",
|
||||
"componentKey": "purl::pkg:npm/dev-only@1.0.0",
|
||||
"purl": "pkg:npm/dev-only@1.0.0",
|
||||
"name": "dev-only",
|
||||
"version": "1.0.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"dev": "true",
|
||||
"packageManager": "bun",
|
||||
"resolved": "https://registry.npmjs.org/dev-only/-/dev-only-1.0.0.tgz",
|
||||
"source": "bun.lock"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock:packages[dev-only@1.0.0]",
|
||||
"value": "https://registry.npmjs.org/dev-only/-/dev-only-1.0.0.tgz",
|
||||
"sha256": "4d40cc185e492e4544a6dc3b17cdfd77096e4d4260569a243eb694befbada6ac"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "bun",
|
||||
"componentKey": "purl::pkg:npm/dev-pkg@1.0.0",
|
||||
"purl": "pkg:npm/dev-pkg@1.0.0",
|
||||
"name": "dev-pkg",
|
||||
"version": "1.0.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"dev": "true",
|
||||
"direct": "true",
|
||||
"packageManager": "bun",
|
||||
"resolved": "https://registry.npmjs.org/dev-pkg/-/dev-pkg-1.0.0.tgz",
|
||||
"source": "bun.lock"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock:packages[dev-pkg@1.0.0]",
|
||||
"value": "https://registry.npmjs.org/dev-pkg/-/dev-pkg-1.0.0.tgz",
|
||||
"sha256": "4d40cc185e492e4544a6dc3b17cdfd77096e4d4260569a243eb694befbada6ac"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "bun",
|
||||
"componentKey": "purl::pkg:npm/prod-pkg@1.0.0",
|
||||
"purl": "pkg:npm/prod-pkg@1.0.0",
|
||||
"name": "prod-pkg",
|
||||
"version": "1.0.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"direct": "true",
|
||||
"packageManager": "bun",
|
||||
"resolved": "https://registry.npmjs.org/prod-pkg/-/prod-pkg-1.0.0.tgz",
|
||||
"source": "bun.lock"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock:packages[prod-pkg@1.0.0]",
|
||||
"value": "https://registry.npmjs.org/prod-pkg/-/prod-pkg-1.0.0.tgz",
|
||||
"sha256": "4d40cc185e492e4544a6dc3b17cdfd77096e4d4260569a243eb694befbada6ac"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "bun",
|
||||
"componentKey": "purl::pkg:npm/shared@1.0.0",
|
||||
"purl": "pkg:npm/shared@1.0.0",
|
||||
"name": "shared",
|
||||
"version": "1.0.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"packageManager": "bun",
|
||||
"resolved": "https://registry.npmjs.org/shared/-/shared-1.0.0.tgz",
|
||||
"source": "bun.lock"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock:packages[shared@1.0.0]",
|
||||
"value": "https://registry.npmjs.org/shared/-/shared-1.0.0.tgz",
|
||||
"sha256": "4d40cc185e492e4544a6dc3b17cdfd77096e4d4260569a243eb694befbada6ac"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "bun-lockfile-dev-classification-fixture",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"prod-pkg": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dev-pkg": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,15 +18,17 @@
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "integrity",
|
||||
"locator": "bun.lock",
|
||||
"value": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
"locator": "bun.lock:packages[ms@2.1.3]",
|
||||
"value": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"sha256": "4a384b14aba7740bd500cdf0da7329a41a2940662e9b1fcab1fbc71c6c8389e7"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock",
|
||||
"value": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz"
|
||||
"locator": "bun.lock:packages[ms@2.1.3]",
|
||||
"value": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"sha256": "4a384b14aba7740bd500cdf0da7329a41a2940662e9b1fcab1fbc71c6c8389e7"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -19,19 +19,22 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node_modules",
|
||||
"locator": "node_modules/lodash/package.json"
|
||||
"locator": "node_modules/lodash/package.json",
|
||||
"sha256": "82145cd4bdc9a690c14843b405179c60aeda1a958029f6ae62776c1b26e42169"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "integrity",
|
||||
"locator": "bun.lock",
|
||||
"value": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vz1kAmtILi\u002B8fm9nJMg7b0GN8sMEJz2mxG/S7mNxhWQ7\u002BD9bF8Q=="
|
||||
"locator": "bun.lock:packages[lodash@4.17.21]",
|
||||
"value": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vz1kAmtILi\u002B8fm9nJMg7b0GN8sMEJz2mxG/S7mNxhWQ7\u002BD9bF8Q==",
|
||||
"sha256": "8a0d37c3761b81514ee397c3836ccff48167ce6aa1afdfd484ca7679e586df4a"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock",
|
||||
"value": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
|
||||
"locator": "bun.lock:packages[lodash@4.17.21]",
|
||||
"value": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"sha256": "8a0d37c3761b81514ee397c3836ccff48167ce6aa1afdfd484ca7679e586df4a"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -55,20 +58,23 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node_modules",
|
||||
"locator": "node_modules/ms/package.json"
|
||||
"locator": "node_modules/ms/package.json",
|
||||
"sha256": "ae11c4ce44027a95893e8c890aed0c582f04e8cf1b8022931eddcb613cd9d3f7"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "integrity",
|
||||
"locator": "bun.lock",
|
||||
"value": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
"locator": "bun.lock:packages[ms@2.1.3]",
|
||||
"value": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||
"sha256": "8a0d37c3761b81514ee397c3836ccff48167ce6aa1afdfd484ca7679e586df4a"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock",
|
||||
"value": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz"
|
||||
"locator": "bun.lock:packages[ms@2.1.3]",
|
||||
"value": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"sha256": "8a0d37c3761b81514ee397c3836ccff48167ce6aa1afdfd484ca7679e586df4a"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"name": "bun-multi-workspace-fixture",
|
||||
"version": "1.0.0",
|
||||
"workspaces": [
|
||||
"packages/*"
|
||||
],
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.21",
|
||||
"ms": "^2.1.3"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"packages": {
|
||||
"file-pkg@file:../file-pkg.tgz": [
|
||||
"file:../file-pkg.tgz",
|
||||
null,
|
||||
{}
|
||||
],
|
||||
"link-pkg@link:../link-pkg": [
|
||||
"link:../link-pkg",
|
||||
null,
|
||||
{}
|
||||
],
|
||||
"local-pkg@workspace:*": [
|
||||
"workspace:packages/local-pkg",
|
||||
null,
|
||||
{}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "bun",
|
||||
"componentKey": "explicit::bun::npm::file-pkg::sha256:c541f5764a7e2fdea9fc5789b13e404f8e15ffc8db0110a81346552c607c89ff",
|
||||
"name": "file-pkg",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"direct": "true",
|
||||
"nonConcreteVersion": "true",
|
||||
"packageManager": "bun",
|
||||
"resolved": "file:../file-pkg.tgz",
|
||||
"source": "bun.lock",
|
||||
"sourceType": "file",
|
||||
"specifier": "file:../file-pkg.tgz",
|
||||
"versionSpec": "file:../file-pkg.tgz"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock:packages[file-pkg@file:../file-pkg.tgz]",
|
||||
"value": "file:../file-pkg.tgz",
|
||||
"sha256": "d7ae02476b6737ea3056226ea69e36bacb664feacd7a5223bc66ea287757656b"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "bun",
|
||||
"componentKey": "explicit::bun::npm::link-pkg::sha256:ebb0c3119ab319e05c02e2448f1d6b4a23dc69076bf8dbfbe95657a3405d1b11",
|
||||
"name": "link-pkg",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"direct": "true",
|
||||
"nonConcreteVersion": "true",
|
||||
"packageManager": "bun",
|
||||
"resolved": "link:../link-pkg",
|
||||
"source": "bun.lock",
|
||||
"sourceType": "link",
|
||||
"specifier": "link:../link-pkg",
|
||||
"versionSpec": "link:../link-pkg"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock:packages[link-pkg@link:../link-pkg]",
|
||||
"value": "link:../link-pkg",
|
||||
"sha256": "d7ae02476b6737ea3056226ea69e36bacb664feacd7a5223bc66ea287757656b"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "bun",
|
||||
"componentKey": "explicit::bun::npm::local-pkg::sha256:cafb6902358bb6a2503a67d71abe50446cdcb3c8359dfb6f3ab00ee1672a5c07",
|
||||
"name": "local-pkg",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"direct": "true",
|
||||
"nonConcreteVersion": "true",
|
||||
"packageManager": "bun",
|
||||
"resolved": "workspace:packages/local-pkg",
|
||||
"source": "bun.lock",
|
||||
"sourceType": "workspace",
|
||||
"specifier": "workspace:packages/local-pkg",
|
||||
"versionSpec": "workspace:*"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock:packages[local-pkg@workspace:*]",
|
||||
"value": "workspace:packages/local-pkg",
|
||||
"sha256": "d7ae02476b6737ea3056226ea69e36bacb664feacd7a5223bc66ea287757656b"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "non-concrete-versions",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"file-pkg": "file:../file-pkg.tgz",
|
||||
"link-pkg": "link:../link-pkg",
|
||||
"local-pkg": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"packages": {
|
||||
"lodash@4.17.21": ["https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "sha512-lodash-421"],
|
||||
"lodash@4.17.20": ["https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", "sha512-lodash-420"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "bun",
|
||||
"componentKey": "purl::pkg:npm/lodash@4.17.20",
|
||||
"purl": "pkg:npm/lodash@4.17.20",
|
||||
"name": "lodash",
|
||||
"version": "4.17.20",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"direct": "true",
|
||||
"integrity": "sha512-lodash-420",
|
||||
"packageManager": "bun",
|
||||
"patchFile": "patches/lodash@4.17.20.patch",
|
||||
"patched": "true",
|
||||
"path": "node_modules/a/node_modules/lodash",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"scopeUnknown": "true",
|
||||
"source": "node_modules"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node_modules",
|
||||
"locator": "node_modules/a/node_modules/lodash/package.json",
|
||||
"sha256": "a883443850ed2188979ee56e2cf8200fa34935a65aae606d85d1aaa60d8ff32e"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "integrity",
|
||||
"locator": "bun.lock:packages[lodash@4.17.20]",
|
||||
"value": "sha512-lodash-420",
|
||||
"sha256": "e83cd6aa810c1a8af47d6ae0eb621a8a5dc13b23ec08925ad9b5ff4d035cfc7c"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock:packages[lodash@4.17.20]",
|
||||
"value": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"sha256": "e83cd6aa810c1a8af47d6ae0eb621a8a5dc13b23ec08925ad9b5ff4d035cfc7c"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "bun",
|
||||
"componentKey": "purl::pkg:npm/lodash@4.17.21",
|
||||
"purl": "pkg:npm/lodash@4.17.21",
|
||||
"name": "lodash",
|
||||
"version": "4.17.21",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"direct": "true",
|
||||
"integrity": "sha512-lodash-421",
|
||||
"packageManager": "bun",
|
||||
"patchFile": "patches/lodash@4.17.21.patch",
|
||||
"patched": "true",
|
||||
"path": "node_modules/lodash",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"scopeUnknown": "true",
|
||||
"source": "node_modules"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node_modules",
|
||||
"locator": "node_modules/lodash/package.json",
|
||||
"sha256": "1bb77ea984b96ef61781adcc6299a2a1c5f9e42dcf594264cdbb96aa06f5c813"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "integrity",
|
||||
"locator": "bun.lock:packages[lodash@4.17.21]",
|
||||
"value": "sha512-lodash-421",
|
||||
"sha256": "e83cd6aa810c1a8af47d6ae0eb621a8a5dc13b23ec08925ad9b5ff4d035cfc7c"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock:packages[lodash@4.17.21]",
|
||||
"value": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"sha256": "e83cd6aa810c1a8af47d6ae0eb621a8a5dc13b23ec08925ad9b5ff4d035cfc7c"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "patched-multi-version-fixture",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.21"
|
||||
},
|
||||
"patchedDependencies": {
|
||||
"lodash@4.17.21": "patches/lodash@4.17.21.patch",
|
||||
"lodash@4.17.20": "patches/lodash@4.17.20.patch"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
diff --git a/index.js b/index.js
|
||||
index 0000000..2222222 100644
|
||||
--- a/index.js
|
||||
+++ b/index.js
|
||||
@@
|
||||
-// placeholder
|
||||
+// patched
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
diff --git a/index.js b/index.js
|
||||
index 0000000..1111111 100644
|
||||
--- a/index.js
|
||||
+++ b/index.js
|
||||
@@
|
||||
-// placeholder
|
||||
+// patched
|
||||
|
||||
@@ -21,20 +21,23 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node_modules",
|
||||
"locator": "node_modules/lodash/package.json"
|
||||
"locator": "node_modules/lodash/package.json",
|
||||
"sha256": "82145cd4bdc9a690c14843b405179c60aeda1a958029f6ae62776c1b26e42169"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "integrity",
|
||||
"locator": "bun.lock",
|
||||
"value": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vz1kAmtILi\u002B8fm9nJMg7b0GN8sMEJz2mxG/S7mNxhWQ7\u002BD9bF8Q=="
|
||||
"locator": "bun.lock:packages[lodash@4.17.21]",
|
||||
"value": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vz1kAmtILi\u002B8fm9nJMg7b0GN8sMEJz2mxG/S7mNxhWQ7\u002BD9bF8Q==",
|
||||
"sha256": "61ff5c565c08f6564bd16153c10feba4a171986510aaf40f84fe710eabd180c2"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock",
|
||||
"value": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
|
||||
"locator": "bun.lock:packages[lodash@4.17.21]",
|
||||
"value": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"sha256": "61ff5c565c08f6564bd16153c10feba4a171986510aaf40f84fe710eabd180c2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -19,19 +19,22 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node_modules",
|
||||
"locator": "node_modules/@babel/core/package.json"
|
||||
"locator": "node_modules/@babel/core/package.json",
|
||||
"sha256": "c4d995bed6c0ec71ccf6ecb74ee8f20b1431798bd93e54182afcb6870b6cfa23"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "integrity",
|
||||
"locator": "bun.lock",
|
||||
"value": "sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR\u002BK9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw=="
|
||||
"locator": "bun.lock:packages[@babel/core@7.24.0]",
|
||||
"value": "sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR\u002BK9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==",
|
||||
"sha256": "6ffde82e85e550d36bdb577210cd80c56cbd36c02dbfb4d8ec6ada27643bcd2d"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock",
|
||||
"value": "https://registry.npmjs.org/@babel/core/-/core-7.24.0.tgz"
|
||||
"locator": "bun.lock:packages[@babel/core@7.24.0]",
|
||||
"value": "https://registry.npmjs.org/@babel/core/-/core-7.24.0.tgz",
|
||||
"sha256": "6ffde82e85e550d36bdb577210cd80c56cbd36c02dbfb4d8ec6ada27643bcd2d"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -55,20 +58,23 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node_modules",
|
||||
"locator": "node_modules/@types/node/package.json"
|
||||
"locator": "node_modules/@types/node/package.json",
|
||||
"sha256": "db7446931abf3479f92734485e30ee7631923d056bcfa5b210159008524f40e2"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "integrity",
|
||||
"locator": "bun.lock",
|
||||
"value": "sha512-o9bjXmDNcF7GbM4CNQpmi\u002BTutCgap/K3w1JyKgxXjVJa7b8XWCF/wPH2E/0Vz9e\u002BV1B3eXX0WCw\u002BINcAobvUag=="
|
||||
"locator": "bun.lock:packages[@types/node@20.11.0]",
|
||||
"value": "sha512-o9bjXmDNcF7GbM4CNQpmi\u002BTutCgap/K3w1JyKgxXjVJa7b8XWCF/wPH2E/0Vz9e\u002BV1B3eXX0WCw\u002BINcAobvUag==",
|
||||
"sha256": "6ffde82e85e550d36bdb577210cd80c56cbd36c02dbfb4d8ec6ada27643bcd2d"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock",
|
||||
"value": "https://registry.npmjs.org/@types/node/-/node-20.11.0.tgz"
|
||||
"locator": "bun.lock:packages[@types/node@20.11.0]",
|
||||
"value": "https://registry.npmjs.org/@types/node/-/node-20.11.0.tgz",
|
||||
"sha256": "6ffde82e85e550d36bdb577210cd80c56cbd36c02dbfb4d8ec6ada27643bcd2d"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -19,20 +19,23 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node_modules",
|
||||
"locator": "node_modules/lodash/package.json"
|
||||
"locator": "node_modules/lodash/package.json",
|
||||
"sha256": "bfe21067561ba47f62c290400e6208b95ac875f0c41e00c4dddce889e8a8ad4e"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "integrity",
|
||||
"locator": "bun.lock",
|
||||
"value": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vz1kAmtILi\u002B8fm9nJMg7b0GN8sMEJz2mxG/S7mNxhWQ7\u002BD9bF8Q=="
|
||||
"locator": "bun.lock:packages[lodash@4.17.21]",
|
||||
"value": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vz1kAmtILi\u002B8fm9nJMg7b0GN8sMEJz2mxG/S7mNxhWQ7\u002BD9bF8Q==",
|
||||
"sha256": "61ff5c565c08f6564bd16153c10feba4a171986510aaf40f84fe710eabd180c2"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock",
|
||||
"value": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz"
|
||||
"locator": "bun.lock:packages[lodash@4.17.21]",
|
||||
"value": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"sha256": "61ff5c565c08f6564bd16153c10feba4a171986510aaf40f84fe710eabd180c2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -19,20 +19,23 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node_modules",
|
||||
"locator": "node_modules/safe-pkg/package.json"
|
||||
"locator": "node_modules/safe-pkg/package.json",
|
||||
"sha256": "1ade6129984f59a954ec2c175075e74cb2759ba97b9b04acf76537262b0f35af"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "integrity",
|
||||
"locator": "bun.lock",
|
||||
"value": "sha512-abc123"
|
||||
"locator": "bun.lock:packages[safe-pkg@1.0.0]",
|
||||
"value": "sha512-abc123",
|
||||
"sha256": "54dd0b2c2f30e59b29970d34350d083b295789e056e849361da5be932d1ef747"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock",
|
||||
"value": "https://registry.npmjs.org/safe-pkg/-/safe-pkg-1.0.0.tgz"
|
||||
"locator": "bun.lock:packages[safe-pkg@1.0.0]",
|
||||
"value": "https://registry.npmjs.org/safe-pkg/-/safe-pkg-1.0.0.tgz",
|
||||
"sha256": "54dd0b2c2f30e59b29970d34350d083b295789e056e849361da5be932d1ef747"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -19,20 +19,23 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node_modules",
|
||||
"locator": "node_modules/chalk/package.json"
|
||||
"locator": "node_modules/chalk/package.json",
|
||||
"sha256": "7d6ff4f365c8d42bae13a48bb4bc84e4cef4e7a7bd7b211e0662ef62fb675736"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "integrity",
|
||||
"locator": "bun.lock",
|
||||
"value": "sha512-dLitG79d\u002BGV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos\u002Buw7WmWF4wUwBd9jxjocFC2w=="
|
||||
"locator": "bun.lock:packages[chalk@5.3.0]",
|
||||
"value": "sha512-dLitG79d\u002BGV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos\u002Buw7WmWF4wUwBd9jxjocFC2w==",
|
||||
"sha256": "8706c5aecdc68ae4f06c6a2f1bfa9e431e473a961c2f32063911febaba0c65cc"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "resolved",
|
||||
"locator": "bun.lock",
|
||||
"value": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz"
|
||||
"locator": "bun.lock:packages[chalk@5.3.0]",
|
||||
"value": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
|
||||
"sha256": "8706c5aecdc68ae4f06c6a2f1bfa9e431e473a961c2f32063911febaba0c65cc"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -322,7 +322,31 @@ public sealed class BunLockParserTests
|
||||
Assert.Single(result.AllEntries);
|
||||
var entry = result.AllEntries[0];
|
||||
Assert.Single(entry.Dependencies);
|
||||
Assert.Contains("ms", entry.Dependencies);
|
||||
Assert.Equal("ms", entry.Dependencies[0].Name);
|
||||
Assert.Equal("^2.1.3", entry.Dependencies[0].Specifier);
|
||||
Assert.False(entry.Dependencies[0].IsOptionalPeer);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_ArrayFormat_ExtractsOptionalPeerDependencies()
|
||||
{
|
||||
var content = """
|
||||
{
|
||||
"lockfileVersion": 1,
|
||||
"packages": {
|
||||
"pkg@1.0.0": ["https://registry.npmjs.org/pkg/-/pkg-1.0.0.tgz", null, {}, {"react": "^18.0.0"}]
|
||||
}
|
||||
}
|
||||
""";
|
||||
|
||||
var result = BunLockParser.Parse(content);
|
||||
|
||||
Assert.Single(result.AllEntries);
|
||||
var entry = result.AllEntries[0];
|
||||
Assert.Single(entry.Dependencies);
|
||||
Assert.Equal("react", entry.Dependencies[0].Name);
|
||||
Assert.Equal("^18.0.0", entry.Dependencies[0].Specifier);
|
||||
Assert.True(entry.Dependencies[0].IsOptionalPeer);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
using StellaOps.Scanner.Analyzers.Lang.Bun.Internal;
|
||||
using StellaOps.Scanner.Analyzers.Lang.Tests.TestUtilities;
|
||||
|
||||
namespace StellaOps.Scanner.Analyzers.Lang.Bun.Tests.Parsers;
|
||||
|
||||
public sealed class BunLockScopeClassifierTests
|
||||
{
|
||||
[Fact]
|
||||
public void IncludeDevFalse_FiltersDevOnlyPackages()
|
||||
{
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "bun", "lockfile-dev-classification");
|
||||
var lockPath = Path.Combine(fixturePath, "bun.lock");
|
||||
|
||||
var lockData = BunLockParser.Parse(File.ReadAllText(lockPath));
|
||||
var declared = BunDeclaredDependencyCollector.Collect(fixturePath);
|
||||
var classified = BunLockScopeClassifier.Classify(lockData, declared);
|
||||
|
||||
Assert.True(classified.FindEntry("dev-pkg", "1.0.0")?.IsDev ?? false);
|
||||
Assert.True(classified.FindEntry("dev-only", "1.0.0")?.IsDev ?? false);
|
||||
Assert.False(classified.FindEntry("prod-pkg", "1.0.0")?.IsDev ?? true);
|
||||
Assert.False(classified.FindEntry("shared", "1.0.0")?.IsDev ?? true);
|
||||
|
||||
var filtered = BunLockInventory.ExtractPackages(classified, includeDev: false);
|
||||
|
||||
Assert.DoesNotContain(filtered, package => package.Name == "dev-pkg");
|
||||
Assert.DoesNotContain(filtered, package => package.Name == "dev-only");
|
||||
Assert.Contains(filtered, package => package.Name == "prod-pkg");
|
||||
Assert.Contains(filtered, package => package.Name == "shared");
|
||||
}
|
||||
}
|
||||
@@ -222,7 +222,7 @@ public sealed class BunPackageTests
|
||||
var resolvedEvidence = evidence.FirstOrDefault(e => e.Source == "resolved");
|
||||
Assert.NotNull(resolvedEvidence);
|
||||
Assert.Equal(LanguageEvidenceKind.Metadata, resolvedEvidence.Kind);
|
||||
Assert.Equal("bun.lock", resolvedEvidence.Locator);
|
||||
Assert.Equal("bun.lock:packages[lodash@4.17.21]", resolvedEvidence.Locator);
|
||||
Assert.Equal("https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", resolvedEvidence.Value);
|
||||
|
||||
// Integrity evidence
|
||||
@@ -265,7 +265,7 @@ public sealed class BunPackageTests
|
||||
IsOptional = false,
|
||||
IsPeer = false,
|
||||
SourceType = "npm",
|
||||
Dependencies = new List<string> { "debug" }
|
||||
Dependencies = new List<BunLockDependency> { new("debug", "^4.3.4", IsOptionalPeer: false) }
|
||||
};
|
||||
|
||||
var package = BunPackage.FromLockEntry(lockEntry, "bun.lock");
|
||||
|
||||
@@ -192,8 +192,8 @@ public sealed class BunWorkspaceHelperTests : IDisposable
|
||||
var result = BunWorkspaceHelper.ParseWorkspaceInfo(_tempDir);
|
||||
|
||||
Assert.Single(result.PatchedDependencies);
|
||||
Assert.True(result.PatchedDependencies.ContainsKey("lodash"));
|
||||
Assert.Equal("patches/lodash@4.17.21.patch", result.PatchedDependencies["lodash"]);
|
||||
Assert.True(result.PatchedDependencies.ContainsKey("lodash@4.17.21"));
|
||||
Assert.Equal("patches/lodash@4.17.21.patch", result.PatchedDependencies["lodash@4.17.21"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -215,8 +215,10 @@ public sealed class BunWorkspaceHelperTests : IDisposable
|
||||
var result = BunWorkspaceHelper.ParseWorkspaceInfo(_tempDir);
|
||||
|
||||
Assert.Equal(2, result.PatchedDependencies.Count);
|
||||
Assert.True(result.PatchedDependencies.ContainsKey("lodash"));
|
||||
Assert.True(result.PatchedDependencies.ContainsKey("@babel+core"));
|
||||
Assert.True(result.PatchedDependencies.ContainsKey("lodash@4.17.21"));
|
||||
Assert.Equal("patches/lodash@4.17.21.patch", result.PatchedDependencies["lodash@4.17.21"]);
|
||||
Assert.True(result.PatchedDependencies.ContainsKey("@babel/core@7.24.0"));
|
||||
Assert.Equal("patches/@babel+core@7.24.0.patch", result.PatchedDependencies["@babel/core@7.24.0"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -237,7 +239,8 @@ public sealed class BunWorkspaceHelperTests : IDisposable
|
||||
var result = BunWorkspaceHelper.ParseWorkspaceInfo(_tempDir);
|
||||
|
||||
Assert.Single(result.PatchedDependencies);
|
||||
Assert.True(result.PatchedDependencies.ContainsKey("ms"));
|
||||
Assert.True(result.PatchedDependencies.ContainsKey("ms@2.1.3"));
|
||||
Assert.Equal(".patches/ms@2.1.3.patch", result.PatchedDependencies["ms@2.1.3"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -17,12 +17,10 @@
|
||||
<PackageReference Remove="xunit" />
|
||||
<PackageReference Remove="xunit.runner.visualstudio" />
|
||||
<PackageReference Remove="Microsoft.AspNetCore.Mvc.Testing" />
|
||||
<PackageReference Remove="Mongo2Go" />
|
||||
<PackageReference Remove="coverlet.collector" />
|
||||
<PackageReference Remove="Microsoft.Extensions.TimeProvider.Testing" />
|
||||
<ProjectReference Remove="..\StellaOps.Concelier.Testing\StellaOps.Concelier.Testing.csproj" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\StellaOps.Concelier.Tests.Shared\AssemblyInfo.cs" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\StellaOps.Concelier.Tests.Shared\MongoFixtureCollection.cs" />
|
||||
<Using Remove="StellaOps.Concelier.Testing" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ public sealed class DenoRuntimePathHasherTests
|
||||
var identity = DenoRuntimePathHasher.Create(root, absolute);
|
||||
|
||||
Assert.Equal("subdir/main.ts", identity.Normalized);
|
||||
Assert.Equal("2d0ef79c25b433a216f41853e89d8e1e1e1ef0b0e77d12b37a7f4f7c2a25f635", identity.PathSha256);
|
||||
Assert.Equal("c3b59fd8169cee9cc111b4737e733f8c0227403717e04f37cba870c49c7ff2c3", identity.PathSha256);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -33,7 +33,7 @@ public sealed class DenoRuntimePathHasherTests
|
||||
{
|
||||
var identity = DenoRuntimePathHasher.Create(root, root);
|
||||
Assert.Equal(".", identity.Normalized);
|
||||
Assert.Equal("e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", identity.PathSha256);
|
||||
Assert.Equal("cdb4ee2aea69cc6a83331bbe96dc2caa9a299d21329efb0336fc02a82e1839a8", identity.PathSha256);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -27,6 +27,6 @@ public sealed class DenoRuntimeTraceProbeTests
|
||||
Assert.Equal(new[] { "https://deno.land" }, metadata.RemoteOrigins);
|
||||
Assert.Equal(new[] { "fs", "net" }, metadata.UniquePermissions);
|
||||
|
||||
Assert.Equal("8f67e4b77f2ea4155d9101c5e6a45922e4ac1e19006955c3e6c2afe1938f0a8d", hash);
|
||||
Assert.Equal("97f26acf896f0c2da77079885f6462cc7b589597b505532b09ae4bc6d1c0f314", hash);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,13 +45,13 @@ public sealed class DenoRuntimeTraceRecorderTests
|
||||
Assert.Equal(2, snapshot.Metadata.ModuleLoads);
|
||||
Assert.Equal(1, snapshot.Metadata.PermissionUses);
|
||||
Assert.Equal(new[] { "https://deno.land/x/std" }, snapshot.Metadata.RemoteOrigins);
|
||||
Assert.Equal(new[] { "net" }, snapshot.Metadata.UniquePermissions);
|
||||
Assert.Equal(new[] { "fs", "net" }, snapshot.Metadata.UniquePermissions);
|
||||
Assert.Equal(0, snapshot.Metadata.NpmResolutions);
|
||||
Assert.Equal(0, snapshot.Metadata.WasmLoads);
|
||||
Assert.Equal(1, snapshot.Metadata.DynamicImports);
|
||||
|
||||
// Stable hash check
|
||||
Assert.Equal("198c6e038f1c39a78a52b844f051bfa6eaa5312faa66f1bc73d2f6d1048d8a7a", snapshot.Sha256);
|
||||
Assert.Equal("61584731fc2870d972c78a86cb307d6f6dc5e110473d61b5bf61208f8be55e7a", snapshot.Sha256);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -46,6 +46,6 @@ public sealed class DenoRuntimeTraceSerializerTests
|
||||
";
|
||||
|
||||
Assert.Equal(expectedNdjson.Replace("\r\n", "\n"), text.Replace("\r\n", "\n"));
|
||||
Assert.Equal("fdc6f07fe6b18b4cdd228c44b83e61d63063b7bd3422a2d3ab8000ac8420ceb0", hash);
|
||||
Assert.Equal("9e74e46f576beafcfe76cd33b2f2f207bd2f1ba3cc86e045383c1afd52134961", hash);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,9 @@ public sealed class DenoAnalyzerGoldenTests
|
||||
normalized = normalized.TrimEnd();
|
||||
expected = expected.TrimEnd();
|
||||
|
||||
normalized = normalized.Replace("\r\n", "\n", StringComparison.Ordinal).Replace("\r", "\n", StringComparison.Ordinal);
|
||||
expected = expected.Replace("\r\n", "\n", StringComparison.Ordinal).Replace("\r", "\n", StringComparison.Ordinal);
|
||||
|
||||
if (!string.Equals(expected, normalized, StringComparison.Ordinal))
|
||||
{
|
||||
var actualPath = golden + ".actual";
|
||||
@@ -201,9 +204,21 @@ public sealed class DenoAnalyzerGoldenTests
|
||||
|
||||
var altRoot = workspaceRoot.Replace("/", "\\", StringComparison.Ordinal);
|
||||
var altRootLower = altRoot.ToLowerInvariant();
|
||||
var altRootEscaped = altRoot.Replace("\\", "\\\\", StringComparison.Ordinal);
|
||||
var altRootLowerEscaped = altRootLower.Replace("\\", "\\\\", StringComparison.Ordinal);
|
||||
var altRootDoubleEscaped = altRootEscaped.Replace("\\", "\\\\", StringComparison.Ordinal);
|
||||
var altRootLowerDoubleEscaped = altRootLowerEscaped.Replace("\\", "\\\\", StringComparison.Ordinal);
|
||||
result = result
|
||||
.Replace(altRoot, "<workspace>", StringComparison.Ordinal)
|
||||
.Replace(altRootLower, "<workspace>", StringComparison.Ordinal);
|
||||
.Replace(altRootLower, "<workspace>", StringComparison.Ordinal)
|
||||
.Replace(altRootEscaped, "<workspace>", StringComparison.Ordinal)
|
||||
.Replace(altRootLowerEscaped, "<workspace>", StringComparison.Ordinal)
|
||||
.Replace(altRootDoubleEscaped, "<workspace>", StringComparison.Ordinal)
|
||||
.Replace(altRootLowerDoubleEscaped, "<workspace>", StringComparison.Ordinal);
|
||||
|
||||
result = result
|
||||
.Replace("\\\\\\\\", "/", StringComparison.Ordinal)
|
||||
.Replace("\\\\", "/", StringComparison.Ordinal);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -14,12 +14,10 @@
|
||||
<PackageReference Remove="xunit" />
|
||||
<PackageReference Remove="xunit.runner.visualstudio" />
|
||||
<PackageReference Remove="Microsoft.AspNetCore.Mvc.Testing" />
|
||||
<PackageReference Remove="Mongo2Go" />
|
||||
<PackageReference Remove="coverlet.collector" />
|
||||
<PackageReference Remove="Microsoft.Extensions.TimeProvider.Testing" />
|
||||
<ProjectReference Remove="..\\StellaOps.Concelier.Testing\\StellaOps.Concelier.Testing.csproj" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\\StellaOps.Concelier.Tests.Shared\\AssemblyInfo.cs" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\\StellaOps.Concelier.Tests.Shared\\MongoFixtureCollection.cs" />
|
||||
<Using Remove="StellaOps.Concelier.Testing" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<!-- Disable Concelier test infrastructure - this project doesn't need MongoDB -->
|
||||
<!-- Disable Concelier test infrastructure - not needed for scanner tests -->
|
||||
<UseConcelierTestInfra>false</UseConcelierTestInfra>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
<PackageReference Remove="xunit" />
|
||||
<PackageReference Remove="xunit.runner.visualstudio" />
|
||||
<PackageReference Remove="Microsoft.AspNetCore.Mvc.Testing" />
|
||||
<PackageReference Remove="Mongo2Go" />
|
||||
<PackageReference Remove="coverlet.collector" />
|
||||
<PackageReference Remove="Microsoft.Extensions.TimeProvider.Testing" />
|
||||
<PackageReference Remove="SharpCompress" />
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "golang",
|
||||
"componentKey": "golang::bin::sha256:7125d65230b913faa744a33acd884899c81a1dbc6d88cbf251a74b19621cde99",
|
||||
"name": "app",
|
||||
"type": "bin",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"binary.sha256": "7125d65230b913faa744a33acd884899c81a1dbc6d88cbf251a74b19621cde99",
|
||||
"binaryPath": "app",
|
||||
"go.version.hint": "go1.22.8",
|
||||
"languageHint": "golang",
|
||||
"provenance": "binary"
|
||||
{
|
||||
"analyzerId": "golang",
|
||||
"componentKey": "golang::bin::sha256:80f528c90b72a4c4cc3fa078501154e4f2a3f49faea3ec380112d61740bde4c3",
|
||||
"name": "app",
|
||||
"type": "bin",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"binary.sha256": "80f528c90b72a4c4cc3fa078501154e4f2a3f49faea3ec380112d61740bde4c3",
|
||||
"binaryPath": "app",
|
||||
"go.version.hint": "go1.22.8",
|
||||
"languageHint": "golang",
|
||||
"provenance": "binary"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "binary",
|
||||
"locator": "app",
|
||||
"sha256": "7125d65230b913faa744a33acd884899c81a1dbc6d88cbf251a74b19621cde99"
|
||||
},
|
||||
"kind": "file",
|
||||
"source": "binary",
|
||||
"locator": "app",
|
||||
"sha256": "80f528c90b72a4c4cc3fa078501154e4f2a3f49faea3ec380112d61740bde4c3"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "go.heuristic",
|
||||
|
||||
@@ -14,12 +14,10 @@
|
||||
<PackageReference Remove="xunit" />
|
||||
<PackageReference Remove="xunit.runner.visualstudio" />
|
||||
<PackageReference Remove="Microsoft.AspNetCore.Mvc.Testing" />
|
||||
<PackageReference Remove="Mongo2Go" />
|
||||
<PackageReference Remove="coverlet.collector" />
|
||||
<PackageReference Remove="Microsoft.Extensions.TimeProvider.Testing" />
|
||||
<ProjectReference Remove="..\StellaOps.Concelier.Testing\StellaOps.Concelier.Testing.csproj" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\StellaOps.Concelier.Tests.Shared\AssemblyInfo.cs" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\StellaOps.Concelier.Tests.Shared\MongoFixtureCollection.cs" />
|
||||
<Using Remove="StellaOps.Concelier.Testing" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "java",
|
||||
"componentKey": "purl::pkg:maven/com/example/pomxml-only@1.2.3",
|
||||
"purl": "pkg:maven/com/example/pomxml-only@1.2.3",
|
||||
"name": "pomxml-only",
|
||||
"version": "1.2.3",
|
||||
"type": "maven",
|
||||
"usedByEntrypoint": true,
|
||||
"metadata": {
|
||||
"artifactId": "pomxml-only",
|
||||
"displayName": "PomXml Only",
|
||||
"groupId": "com.example",
|
||||
"jarPath": "libs/pomxml-only.jar",
|
||||
"manifestTitle": "PomXml Only",
|
||||
"manifestVendor": "Example Corp",
|
||||
"manifestVersion": "1.2.3",
|
||||
"packaging": "jar"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "MANIFEST.MF",
|
||||
"locator": "libs/pomxml-only.jar!META-INF/MANIFEST.MF",
|
||||
"value": "title=PomXml Only;version=1.2.3;vendor=Example Corp"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "pom.xml",
|
||||
"locator": "libs/pomxml-only.jar!META-INF/maven/com.example/pomxml-only/pom.xml",
|
||||
"sha256": "9a315451470e76bb25c2a77ecdf03982aed210f1cbccab480c79eb1d4a5a79a5"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,65 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "java",
|
||||
"componentKey": "purl::pkg:maven/com/example/app-fat@1.0.0",
|
||||
"purl": "pkg:maven/com/example/app-fat@1.0.0",
|
||||
"name": "app-fat",
|
||||
"version": "1.0.0",
|
||||
"type": "maven",
|
||||
"usedByEntrypoint": true,
|
||||
"metadata": {
|
||||
"artifactId": "app-fat",
|
||||
"displayName": "App Fat",
|
||||
"embeddedScan.candidateJars": "1",
|
||||
"embeddedScan.emittedComponents": "1",
|
||||
"embeddedScan.scannedJars": "1",
|
||||
"groupId": "com.example",
|
||||
"jarPath": "apps/app-fat.jar",
|
||||
"manifestTitle": "App Fat",
|
||||
"manifestVendor": "Example Corp",
|
||||
"manifestVersion": "1.0.0",
|
||||
"packaging": "jar"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "MANIFEST.MF",
|
||||
"locator": "apps/app-fat.jar!META-INF/MANIFEST.MF",
|
||||
"value": "title=App Fat;version=1.0.0;vendor=Example Corp"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "pom.properties",
|
||||
"locator": "apps/app-fat.jar!META-INF/maven/com.example/app-fat/pom.properties",
|
||||
"sha256": "bba5da43d59efe9726f4195a86581d53b01bd449603fd2536fab29d720dcb806"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "java",
|
||||
"componentKey": "purl::pkg:maven/com/example/embedded-lib@2.1.0",
|
||||
"purl": "pkg:maven/com/example/embedded-lib@2.1.0",
|
||||
"name": "embedded-lib",
|
||||
"version": "2.1.0",
|
||||
"type": "maven",
|
||||
"usedByEntrypoint": true,
|
||||
"metadata": {
|
||||
"artifactId": "embedded-lib",
|
||||
"displayName": "Embedded Lib",
|
||||
"embedded": "true",
|
||||
"embedded.containerJarPath": "apps/app-fat.jar",
|
||||
"embedded.entryPath": "BOOT-INF/lib/embedded-lib.jar",
|
||||
"groupId": "com.example",
|
||||
"jarPath": "apps/app-fat.jar!BOOT-INF/lib/embedded-lib.jar",
|
||||
"packaging": "jar"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "pom.properties",
|
||||
"locator": "apps/app-fat.jar!BOOT-INF/lib/embedded-lib.jar!META-INF/maven/com.example/embedded-lib/pom.properties",
|
||||
"sha256": "45cbc64bcc2dcf25ee71a698cd35a676d79b0ed09cc77b61fead907c6345081f"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,65 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "java",
|
||||
"componentKey": "purl::pkg:maven/com/example/demo-war@1.0.0?type=war",
|
||||
"purl": "pkg:maven/com/example/demo-war@1.0.0?type=war",
|
||||
"name": "demo-war",
|
||||
"version": "1.0.0",
|
||||
"type": "maven",
|
||||
"usedByEntrypoint": true,
|
||||
"metadata": {
|
||||
"artifactId": "demo-war",
|
||||
"displayName": "Demo War",
|
||||
"embeddedScan.candidateJars": "1",
|
||||
"embeddedScan.emittedComponents": "1",
|
||||
"embeddedScan.scannedJars": "1",
|
||||
"groupId": "com.example",
|
||||
"jarPath": "apps/demo-war.war",
|
||||
"manifestTitle": "Demo War",
|
||||
"manifestVendor": "Example Corp",
|
||||
"manifestVersion": "1.0.0",
|
||||
"packaging": "war"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "MANIFEST.MF",
|
||||
"locator": "apps/demo-war.war!META-INF/MANIFEST.MF",
|
||||
"value": "title=Demo War;version=1.0.0;vendor=Example Corp"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "pom.properties",
|
||||
"locator": "apps/demo-war.war!META-INF/maven/com.example/demo-war/pom.properties",
|
||||
"sha256": "cb57c79ca5007119bfb0fafd6ae24a6702e508116d5e799835392df742a49460"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "java",
|
||||
"componentKey": "purl::pkg:maven/com/example/web-lib@3.0.0",
|
||||
"purl": "pkg:maven/com/example/web-lib@3.0.0",
|
||||
"name": "web-lib",
|
||||
"version": "3.0.0",
|
||||
"type": "maven",
|
||||
"usedByEntrypoint": true,
|
||||
"metadata": {
|
||||
"artifactId": "web-lib",
|
||||
"displayName": "Web Lib",
|
||||
"embedded": "true",
|
||||
"embedded.containerJarPath": "apps/demo-war.war",
|
||||
"embedded.entryPath": "WEB-INF/lib/web-lib.jar",
|
||||
"groupId": "com.example",
|
||||
"jarPath": "apps/demo-war.war!WEB-INF/lib/web-lib.jar",
|
||||
"packaging": "jar"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "pom.properties",
|
||||
"locator": "apps/demo-war.war!WEB-INF/lib/web-lib.jar!META-INF/maven/com.example/web-lib/pom.properties",
|
||||
"sha256": "ab7151e977ef21d48c459395dbb0f88395a3a33b2f5903a28b7d78b53cb8880d"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -36,6 +36,81 @@ public sealed class JavaLanguageAnalyzerTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractsMavenArtifactsFromSpringBootFatJarEmbeddedLibrariesAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var root = TestPaths.CreateTemporaryDirectory();
|
||||
try
|
||||
{
|
||||
var jarPath = JavaFixtureBuilder.CreateSpringBootFatJarWithEmbeddedMavenLibrary(root);
|
||||
var usageHints = new LanguageUsageHints(new[] { jarPath });
|
||||
var analyzers = new ILanguageAnalyzer[] { new JavaLanguageAnalyzer() };
|
||||
var goldenPath = TestPaths.ResolveFixture("java", "spring-boot-fat-embedded-maven", "expected.json");
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath: root,
|
||||
goldenPath: goldenPath,
|
||||
analyzers: analyzers,
|
||||
cancellationToken: cancellationToken,
|
||||
usageHints: usageHints);
|
||||
}
|
||||
finally
|
||||
{
|
||||
TestPaths.SafeDelete(root);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractsMavenArtifactsFromWarEmbeddedLibrariesAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var root = TestPaths.CreateTemporaryDirectory();
|
||||
try
|
||||
{
|
||||
var warPath = JavaFixtureBuilder.CreateWarArchiveWithEmbeddedMavenLibrary(root);
|
||||
var usageHints = new LanguageUsageHints(new[] { warPath });
|
||||
var analyzers = new ILanguageAnalyzer[] { new JavaLanguageAnalyzer() };
|
||||
var goldenPath = TestPaths.ResolveFixture("java", "war-embedded-maven", "expected.json");
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath: root,
|
||||
goldenPath: goldenPath,
|
||||
analyzers: analyzers,
|
||||
cancellationToken: cancellationToken,
|
||||
usageHints: usageHints);
|
||||
}
|
||||
finally
|
||||
{
|
||||
TestPaths.SafeDelete(root);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractsMavenArtifactsFromPomXmlOnlyJarAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var root = TestPaths.CreateTemporaryDirectory();
|
||||
try
|
||||
{
|
||||
var jarPath = JavaFixtureBuilder.CreatePomXmlOnlyJar(root);
|
||||
var usageHints = new LanguageUsageHints(new[] { jarPath });
|
||||
var analyzers = new ILanguageAnalyzer[] { new JavaLanguageAnalyzer() };
|
||||
var goldenPath = TestPaths.ResolveFixture("java", "pomxml-only-jar", "expected.json");
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath: root,
|
||||
goldenPath: goldenPath,
|
||||
analyzers: analyzers,
|
||||
cancellationToken: cancellationToken,
|
||||
usageHints: usageHints);
|
||||
}
|
||||
finally
|
||||
{
|
||||
TestPaths.SafeDelete(root);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LockfilesProduceDeclaredOnlyComponentsAsync()
|
||||
{
|
||||
@@ -157,7 +232,12 @@ public sealed class JavaLanguageAnalyzerTests
|
||||
WritePomProperties(archive, "com.example", "demo-jni", "1.0.0");
|
||||
WriteManifest(archive, "demo-jni", "1.0.0", "com.example");
|
||||
|
||||
CreateBinaryEntry(archive, "com/example/App.class", "System.loadLibrary(\"foo\")");
|
||||
var classEntry = archive.CreateEntry("com/example/App.class");
|
||||
var classBytes = JavaClassFileFactory.CreateSystemLoadLibraryInvoker("com/example/App", "foo");
|
||||
using (var classStream = classEntry.Open())
|
||||
{
|
||||
classStream.Write(classBytes);
|
||||
}
|
||||
CreateTextEntry(archive, "lib/native/libfoo.so");
|
||||
CreateTextEntry(archive, "META-INF/native-image/demo/jni-config.json");
|
||||
}
|
||||
@@ -177,7 +257,197 @@ public sealed class JavaLanguageAnalyzerTests
|
||||
var metadata = component.GetProperty("metadata");
|
||||
Assert.Equal("libfoo.so", metadata.GetProperty("jni.nativeLibs").GetString());
|
||||
Assert.Equal("demo-jni.jar!META-INF/native-image/demo/jni-config.json", metadata.GetProperty("jni.graalConfig").GetString());
|
||||
Assert.Equal("demo-jni.jar!com/example/App.class", metadata.GetProperty("jni.loadCalls").GetString());
|
||||
Assert.Equal("1", metadata.GetProperty("jni.edgeCount").GetString());
|
||||
Assert.Equal("0", metadata.GetProperty("jni.nativeMethodCount").GetString());
|
||||
Assert.Equal("1", metadata.GetProperty("jni.loadCallCount").GetString());
|
||||
Assert.Equal("SystemLoadLibrary", metadata.GetProperty("jni.reasons").GetString());
|
||||
Assert.Equal("foo", metadata.GetProperty("jni.targetLibraries").GetString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
TestPaths.SafeDelete(root);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractsMavenArtifactFromEmbeddedJarAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var root = TestPaths.CreateTemporaryDirectory();
|
||||
|
||||
try
|
||||
{
|
||||
var jarPath = Path.Combine(root, "demo-fat.jar");
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(jarPath)!);
|
||||
|
||||
using (var archive = ZipFile.Open(jarPath, ZipArchiveMode.Create))
|
||||
{
|
||||
WritePomProperties(archive, "com.example", "demo-fat", "1.0.0");
|
||||
WriteManifest(archive, "demo-fat", "1.0.0", "com.example");
|
||||
|
||||
using var embeddedBuffer = new MemoryStream();
|
||||
using (var embeddedJar = new ZipArchive(embeddedBuffer, ZipArchiveMode.Create, leaveOpen: true))
|
||||
{
|
||||
WritePomProperties(embeddedJar, "com.example", "embedded-lib", "2.0.0");
|
||||
}
|
||||
|
||||
embeddedBuffer.Position = 0;
|
||||
var embeddedEntry = archive.CreateEntry("BOOT-INF/lib/embedded-lib.jar");
|
||||
using var embeddedStream = embeddedEntry.Open();
|
||||
embeddedBuffer.CopyTo(embeddedStream);
|
||||
}
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[] { new JavaLanguageAnalyzer() };
|
||||
var json = await LanguageAnalyzerTestHarness.RunToJsonAsync(
|
||||
root,
|
||||
analyzers,
|
||||
cancellationToken,
|
||||
new LanguageUsageHints(new[] { jarPath }));
|
||||
|
||||
using var document = JsonDocument.Parse(json);
|
||||
var components = document.RootElement.EnumerateArray().ToArray();
|
||||
|
||||
var outer = components.First(c => c.GetProperty("name").GetString() == "demo-fat");
|
||||
var outerMetadata = outer.GetProperty("metadata");
|
||||
Assert.Equal("1", outerMetadata.GetProperty("embeddedScan.candidateJars").GetString());
|
||||
Assert.Equal("1", outerMetadata.GetProperty("embeddedScan.scannedJars").GetString());
|
||||
Assert.Equal("1", outerMetadata.GetProperty("embeddedScan.emittedComponents").GetString());
|
||||
|
||||
var embedded = components.First(c => c.GetProperty("name").GetString() == "embedded-lib");
|
||||
var embeddedMetadata = embedded.GetProperty("metadata");
|
||||
Assert.Equal("true", embeddedMetadata.GetProperty("embedded").GetString());
|
||||
Assert.Equal("demo-fat.jar!BOOT-INF/lib/embedded-lib.jar", embeddedMetadata.GetProperty("jarPath").GetString());
|
||||
|
||||
var embeddedEvidence = embedded.GetProperty("evidence").EnumerateArray().ToArray();
|
||||
Assert.Contains(embeddedEvidence, e =>
|
||||
string.Equals(e.GetProperty("source").GetString(), "pom.properties", StringComparison.OrdinalIgnoreCase) &&
|
||||
string.Equals(e.GetProperty("locator").GetString(), "demo-fat.jar!BOOT-INF/lib/embedded-lib.jar!META-INF/maven/com.example/embedded-lib/pom.properties", StringComparison.OrdinalIgnoreCase) &&
|
||||
e.TryGetProperty("sha256", out var sha) &&
|
||||
!string.IsNullOrWhiteSpace(sha.GetString()));
|
||||
}
|
||||
finally
|
||||
{
|
||||
TestPaths.SafeDelete(root);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ExtractsMavenArtifactFromPomXmlWhenPomPropertiesMissingAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var root = TestPaths.CreateTemporaryDirectory();
|
||||
|
||||
try
|
||||
{
|
||||
var jarPath = Path.Combine(root, "demo-pomxml.jar");
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(jarPath)!);
|
||||
|
||||
using (var archive = ZipFile.Open(jarPath, ZipArchiveMode.Create))
|
||||
{
|
||||
WriteManifest(archive, "demo-pomxml", "1.2.3", "com.example");
|
||||
|
||||
var pomXmlPath = "META-INF/maven/com.example/demo-pomxml/pom.xml";
|
||||
var pomXml = """
|
||||
<project>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>demo-pomxml</artifactId>
|
||||
<version>1.2.3</version>
|
||||
<name>Demo Pom XML</name>
|
||||
</project>
|
||||
""";
|
||||
CreateTextEntry(archive, pomXmlPath, pomXml);
|
||||
}
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[] { new JavaLanguageAnalyzer() };
|
||||
var json = await LanguageAnalyzerTestHarness.RunToJsonAsync(
|
||||
root,
|
||||
analyzers,
|
||||
cancellationToken,
|
||||
new LanguageUsageHints(new[] { jarPath }));
|
||||
|
||||
using var document = JsonDocument.Parse(json);
|
||||
var component = document.RootElement
|
||||
.EnumerateArray()
|
||||
.First(element => string.Equals(element.GetProperty("name").GetString(), "demo-pomxml", StringComparison.Ordinal));
|
||||
|
||||
Assert.Equal("pkg:maven/com/example/demo-pomxml@1.2.3", component.GetProperty("purl").GetString());
|
||||
|
||||
var evidence = component.GetProperty("evidence").EnumerateArray().ToArray();
|
||||
Assert.Contains(evidence, e =>
|
||||
string.Equals(e.GetProperty("source").GetString(), "pom.xml", StringComparison.OrdinalIgnoreCase) &&
|
||||
string.Equals(e.GetProperty("locator").GetString(), "demo-pomxml.jar!META-INF/maven/com.example/demo-pomxml/pom.xml", StringComparison.OrdinalIgnoreCase) &&
|
||||
e.TryGetProperty("sha256", out var sha) &&
|
||||
!string.IsNullOrWhiteSpace(sha.GetString()));
|
||||
}
|
||||
finally
|
||||
{
|
||||
TestPaths.SafeDelete(root);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PomXmlWithIncompleteCoordinatesEmitsUnresolvedComponentAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var root = TestPaths.CreateTemporaryDirectory();
|
||||
|
||||
try
|
||||
{
|
||||
var jarPath = Path.Combine(root, "demo-pomxml-unresolved.jar");
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(jarPath)!);
|
||||
|
||||
using (var archive = ZipFile.Open(jarPath, ZipArchiveMode.Create))
|
||||
{
|
||||
WriteManifest(archive, "demo-pomxml-unresolved", "9.9.9", "com.example");
|
||||
|
||||
var pomXmlPath = "META-INF/maven/com.example/demo-pomxml-unresolved/pom.xml";
|
||||
var pomXml = """
|
||||
<project>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.example</groupId>
|
||||
<artifactId>demo-pomxml-unresolved</artifactId>
|
||||
</project>
|
||||
""";
|
||||
CreateTextEntry(archive, pomXmlPath, pomXml);
|
||||
}
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[] { new JavaLanguageAnalyzer() };
|
||||
var json = await LanguageAnalyzerTestHarness.RunToJsonAsync(
|
||||
root,
|
||||
analyzers,
|
||||
cancellationToken,
|
||||
new LanguageUsageHints(new[] { jarPath }));
|
||||
|
||||
using var document = JsonDocument.Parse(json);
|
||||
var component = document.RootElement
|
||||
.EnumerateArray()
|
||||
.First(element =>
|
||||
{
|
||||
if (!element.TryGetProperty("metadata", out var metadata) || metadata.ValueKind != JsonValueKind.Object)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return metadata.TryGetProperty("unresolvedCoordinates", out var unresolved)
|
||||
&& string.Equals(unresolved.GetString(), "true", StringComparison.Ordinal);
|
||||
});
|
||||
|
||||
if (component.TryGetProperty("purl", out var purl))
|
||||
{
|
||||
Assert.Equal(JsonValueKind.Null, purl.ValueKind);
|
||||
}
|
||||
|
||||
var metadata = component.GetProperty("metadata");
|
||||
Assert.Equal("demo-pomxml-unresolved", metadata.GetProperty("manifestTitle").GetString());
|
||||
Assert.Equal("9.9.9", metadata.GetProperty("manifestVersion").GetString());
|
||||
|
||||
var evidence = component.GetProperty("evidence").EnumerateArray().ToArray();
|
||||
Assert.Contains(evidence, e =>
|
||||
string.Equals(e.GetProperty("source").GetString(), "pom.xml", StringComparison.OrdinalIgnoreCase) &&
|
||||
string.Equals(e.GetProperty("locator").GetString(), "demo-pomxml-unresolved.jar!META-INF/maven/com.example/demo-pomxml-unresolved/pom.xml", StringComparison.OrdinalIgnoreCase) &&
|
||||
e.TryGetProperty("sha256", out var sha) &&
|
||||
!string.IsNullOrWhiteSpace(sha.GetString()));
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -436,14 +706,6 @@ public sealed class JavaLanguageAnalyzerTests
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateBinaryEntry(ZipArchive archive, string path, string content)
|
||||
{
|
||||
var entry = archive.CreateEntry(path);
|
||||
using var stream = entry.Open();
|
||||
var bytes = Encoding.UTF8.GetBytes(content);
|
||||
stream.Write(bytes, 0, bytes.Length);
|
||||
}
|
||||
|
||||
private static string CreateSampleJar(string root, string groupId, string artifactId, string version)
|
||||
{
|
||||
var jarPath = Path.Combine(root, $"{artifactId}-{version}.jar");
|
||||
|
||||
@@ -14,12 +14,10 @@
|
||||
<PackageReference Remove="xunit" />
|
||||
<PackageReference Remove="xunit.runner.visualstudio" />
|
||||
<PackageReference Remove="Microsoft.AspNetCore.Mvc.Testing" />
|
||||
<PackageReference Remove="Mongo2Go" />
|
||||
<PackageReference Remove="coverlet.collector" />
|
||||
<PackageReference Remove="Microsoft.Extensions.TimeProvider.Testing" />
|
||||
<ProjectReference Remove="..\StellaOps.Concelier.Testing\StellaOps.Concelier.Testing.csproj" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\StellaOps.Concelier.Tests.Shared\AssemblyInfo.cs" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\StellaOps.Concelier.Tests.Shared\MongoFixtureCollection.cs" />
|
||||
<!-- Exclude shared OpenSSL files - they come from referenced Lang.Tests project -->
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\..\..\..\tests\shared\OpenSslLegacyShim.cs" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\..\..\..\tests\shared\OpenSslAutoInit.cs" />
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "node-phase22",
|
||||
"componentKey": "/app/native/addon.node",
|
||||
"name": "addon.node",
|
||||
"type": "node:native",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"confidence": "0.82",
|
||||
"reason": "native-addon-file"
|
||||
},
|
||||
"evidence": []
|
||||
},
|
||||
{
|
||||
"analyzerId": "node-phase22",
|
||||
"componentKey": "/app/pkg/pkg.wasm",
|
||||
"name": "pkg.wasm",
|
||||
"type": "node:wasm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"confidence": "0.80",
|
||||
"reason": "wasm-file"
|
||||
},
|
||||
"evidence": []
|
||||
},
|
||||
{
|
||||
"analyzerId": "node-phase22",
|
||||
"componentKey": "/src/app.js",
|
||||
"name": "app.js",
|
||||
"type": "node:bundle",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"confidence": "0.87",
|
||||
"format": "esm",
|
||||
"reason": "source-map"
|
||||
},
|
||||
"evidence": []
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/cached-lib@1.0.0",
|
||||
"purl": "pkg:npm/cached-lib@1.0.0",
|
||||
"name": "cached-lib",
|
||||
"version": "1.0.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"path": ".yarn/cache",
|
||||
"yarnPnp": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": ".yarn/cache/cached-lib-1.0.0.zip!package/package.json",
|
||||
"sha256": "b13d2a5d313d5929280c14af2086e23ca8f0d60761085c0ad44982ec307c92e3"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/yarn-pnp-demo@1.0.0",
|
||||
"purl": "pkg:npm/yarn-pnp-demo@1.0.0",
|
||||
"name": "yarn-pnp-demo",
|
||||
"version": "1.0.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"path": ".",
|
||||
"yarnPnp": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "package.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -23,7 +23,8 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "package.json"
|
||||
"locator": "package.json",
|
||||
"sha256": "4cd71adf540fff675b46ecd4d88d0b186534e97f9ca57ee86588d1386deb9274"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -48,4 +49,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -1,4 +1,51 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/hidden-lib@0.2.0",
|
||||
"purl": "pkg:npm/hidden-lib@0.2.0",
|
||||
"name": "hidden-lib",
|
||||
"version": "0.2.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"entrypoint": ".layers/layer0/node_modules/hidden-lib/index.js",
|
||||
"path": ".layers/layer0/node_modules/hidden-lib"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": ".layers/layer0/node_modules/hidden-lib/package.json",
|
||||
"sha256": "d014f340282aa989e5887ddf10a1d2165ba556f89428d0f2812eb8ce8e63c1c8"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "package.json:entrypoint",
|
||||
"locator": ".layers/layer0/node_modules/hidden-lib/package.json#entrypoint",
|
||||
"value": ".layers/layer0/node_modules/hidden-lib/index.js;index.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/layer-app@0.1.0",
|
||||
"purl": "pkg:npm/layer-app@0.1.0",
|
||||
"name": "layer-app",
|
||||
"version": "0.1.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"path": "layers/layer1/app"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "layers/layer1/app/package.json",
|
||||
"sha256": "23abb943f062b3ccdc18966eb36dfc48dd7ec4b5a6105851484fe2911946ecdd"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/layer-lib@0.1.0",
|
||||
@@ -15,7 +62,8 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "layers/layer1/node_modules/layer-lib/package.json"
|
||||
"locator": "layers/layer1/node_modules/layer-lib/package.json",
|
||||
"sha256": "4d4ee909c5fa810d7e9a1bb74f4e6e2da59c3bb4182f62f8bb8f6074218f19d8"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
@@ -24,5 +72,32 @@
|
||||
"value": "layers/layer1/node_modules/layer-lib/index.js;index.js"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/top-layer-lib@0.3.0",
|
||||
"purl": "pkg:npm/top-layer-lib@0.3.0",
|
||||
"name": "top-layer-lib",
|
||||
"version": "0.3.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"entrypoint": "layer2/node_modules/top-layer-lib/index.js",
|
||||
"path": "layer2/node_modules/top-layer-lib"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "layer2/node_modules/top-layer-lib/package.json",
|
||||
"sha256": "9de01a780c07e3d34ef74dfdbd14c5173f419609e77f9cc1fb973c30400e30e9"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "package.json:entrypoint",
|
||||
"locator": "layer2/node_modules/top-layer-lib/package.json#entrypoint",
|
||||
"value": "layer2/node_modules/top-layer-lib/index.js;index.js"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "layer-app",
|
||||
"version": "0.1.0",
|
||||
"dependencies": {
|
||||
"layer-lib": "1.0.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "explicit::node::npm::dev-range::sha256:681581098c1c40eb1faebe65e1916e56011369708306debd2568bfaa8173a6fc",
|
||||
"name": "dev-range",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "package.json#devDependencies",
|
||||
"declared.scope": "development",
|
||||
"declared.source": "package.json",
|
||||
"declared.sourceType": "range",
|
||||
"declared.versionSpec": "~2.0.0",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "package.json#devDependencies"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "explicit::node::npm::file-lib::sha256:2222fa2f2ec7523cabd6c80a0ffd89c3b306fad0ff6b89856f8b896e0b2fe70e",
|
||||
"name": "file-lib",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "package.json#dependencies",
|
||||
"declared.scope": "production",
|
||||
"declared.source": "package.json",
|
||||
"declared.sourceType": "file",
|
||||
"declared.versionSpec": "file:../local/file-lib",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "package.json#dependencies"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "explicit::node::npm::git-lib::sha256:02362d8e5c76a43f5f657721c46db1370be1c5504c9b30be8f667d5d85f369c6",
|
||||
"name": "git-lib",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "package.json#dependencies",
|
||||
"declared.scope": "production",
|
||||
"declared.source": "package.json",
|
||||
"declared.sourceType": "git",
|
||||
"declared.versionSpec": "git\u002Bhttps://example.com/repo.git#v1.0.0",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "package.json#dependencies"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "explicit::node::npm::opt-lib::sha256:79ae0f26f0d9e4a55710b56ae3f216251cedb886ce9dd45891fd70a17d2c273b",
|
||||
"name": "opt-lib",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "package.json#optionalDependencies",
|
||||
"declared.scope": "optional",
|
||||
"declared.source": "package.json",
|
||||
"declared.sourceType": "workspace",
|
||||
"declared.versionSpec": "workspace:*",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "package.json#optionalDependencies"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "explicit::node::npm::path-lib::sha256:5dfa2181ae287045798e7f7d1b3d8f452f071f19be8366d0a218da64fe815589",
|
||||
"name": "path-lib",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "package.json#dependencies",
|
||||
"declared.scope": "production",
|
||||
"declared.source": "package.json",
|
||||
"declared.sourceType": "path",
|
||||
"declared.versionSpec": "./local/path-lib",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "package.json#dependencies"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "explicit::node::npm::peer-lib::sha256:518814536b4014ed1645c41ccf2de9349336f33be755dfe30d60b14f85f5b302",
|
||||
"name": "peer-lib",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "package.json#peerDependencies",
|
||||
"declared.scope": "peer",
|
||||
"declared.source": "package.json",
|
||||
"declared.sourceType": "range",
|
||||
"declared.versionSpec": "\u003E=3.0.0",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "package.json#peerDependencies"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "explicit::node::npm::range-lib::sha256:d90425e51e919a0e90bd2cae825d86919c79799ed49ce2ecdeb956de86344145",
|
||||
"name": "range-lib",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "package.json#dependencies",
|
||||
"declared.scope": "production",
|
||||
"declared.source": "package.json",
|
||||
"declared.sourceType": "range",
|
||||
"declared.versionSpec": "^1.2.3",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "package.json#dependencies"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "explicit::node::npm::tag-lib::sha256:8337331b8a282de0437b980185f47c0d4f592b79d1b114a67b5dad11b8815afd",
|
||||
"name": "tag-lib",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "package.json#dependencies",
|
||||
"declared.scope": "production",
|
||||
"declared.source": "package.json",
|
||||
"declared.sourceType": "tag",
|
||||
"declared.versionSpec": "latest",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "package.json#dependencies"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "explicit::node::npm::tarball-lib::sha256:4fcba99e507cd649bf51963a3ed4f16fbf6431a4170e08580495999ad1ea1fd6",
|
||||
"name": "tarball-lib",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "package.json#dependencies",
|
||||
"declared.scope": "production",
|
||||
"declared.source": "package.json",
|
||||
"declared.sourceType": "tarball",
|
||||
"declared.versionSpec": "https://example.com/pkg.tgz",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "package.json#dependencies"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"range-lib": "^1.2.3",
|
||||
"tag-lib": "latest",
|
||||
"git-lib": "git+https://example.com/repo.git#v1.0.0",
|
||||
"tarball-lib": "https://example.com/pkg.tgz",
|
||||
"file-lib": "file:../local/file-lib",
|
||||
"path-lib": "./local/path-lib"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dev-range": "~2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"peer-lib": ">=3.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"opt-lib": "workspace:*"
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,8 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "package.json"
|
||||
"locator": "package.json",
|
||||
"sha256": "e20b4c9ec9073b572c368b5ea40465eb59586487fa9469ae784cc23f618f3457"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
|
||||
@@ -30,13 +30,63 @@
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"entrypoint": "src/index.js",
|
||||
"imports": "4",
|
||||
"path": "."
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node.import",
|
||||
"locator": "src/index.js",
|
||||
"value": "./lib//entry.js${*} (conf:medium;template-dynamic)"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node.import",
|
||||
"locator": "src/index.js",
|
||||
"value": "./lib/concat.js (conf:high;literal;literal)"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node.import",
|
||||
"locator": "src/index.js",
|
||||
"value": "./lib/static.js (conf:high;literal)"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "node.import",
|
||||
"locator": "src/original.ts",
|
||||
"value": "./lib/sourcemap.js (conf:high;literal)"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "package.json"
|
||||
"locator": "package.json",
|
||||
"sha256": "07f1225926d9d07b0a024994036d10a689f3d98cc51324e2b21a06a7bddb8d0e"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.resolve",
|
||||
"locator": "package.json",
|
||||
"value": "src/index.js:./lib//entry.js${*}-\u003Eunresolved (unresolved;low)"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.resolve",
|
||||
"locator": "package.json",
|
||||
"value": "src/index.js:./lib/concat.js-\u003Eunresolved (unresolved;low)"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.resolve",
|
||||
"locator": "package.json",
|
||||
"value": "src/index.js:./lib/static.js-\u003Eunresolved (unresolved;low)"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.resolve",
|
||||
"locator": "package.json",
|
||||
"value": "src/original.ts:./lib/sourcemap.js-\u003Eunresolved (unresolved;low)"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/%40scope/scoped-child@4.0.0",
|
||||
"purl": "pkg:npm/%40scope/scoped-child@4.0.0",
|
||||
"name": "@scope/scoped-child",
|
||||
"version": "4.0.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "package-lock.json:node_modules/parent/node_modules/@scope/scoped-child",
|
||||
"declared.resolvedVersion": "4.0.0",
|
||||
"declared.source": "package-lock.json",
|
||||
"declared.sourceType": "range",
|
||||
"declared.versionSpec": "4.0.0",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "package-lock.json:node_modules/parent/node_modules/@scope/scoped-child"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/%40scope/scoped@3.0.0",
|
||||
"purl": "pkg:npm/%40scope/scoped@3.0.0",
|
||||
"name": "@scope/scoped",
|
||||
"version": "3.0.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "package-lock.json:node_modules/@scope/scoped",
|
||||
"declared.resolvedVersion": "3.0.0",
|
||||
"declared.source": "package-lock.json",
|
||||
"declared.sourceType": "range",
|
||||
"declared.versionSpec": "3.0.0",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "package-lock.json:node_modules/@scope/scoped"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/child@2.0.0",
|
||||
"purl": "pkg:npm/child@2.0.0",
|
||||
"name": "child",
|
||||
"version": "2.0.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "package-lock.json:node_modules/parent/node_modules/child",
|
||||
"declared.resolvedVersion": "2.0.0",
|
||||
"declared.source": "package-lock.json",
|
||||
"declared.sourceType": "range",
|
||||
"declared.versionSpec": "2.0.0",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "package-lock.json:node_modules/parent/node_modules/child"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/parent@1.0.0",
|
||||
"purl": "pkg:npm/parent@1.0.0",
|
||||
"name": "parent",
|
||||
"version": "1.0.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "package-lock.json:node_modules/parent",
|
||||
"declared.resolvedVersion": "1.0.0",
|
||||
"declared.source": "package-lock.json",
|
||||
"declared.sourceType": "range",
|
||||
"declared.versionSpec": "1.0.0",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "package-lock.json:node_modules/parent"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "lock-only-package-lock",
|
||||
"lockfileVersion": 3,
|
||||
"packages": {
|
||||
"node_modules/parent": {
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"node_modules/parent/node_modules/child": {
|
||||
"version": "2.0.0"
|
||||
},
|
||||
"node_modules/@scope/scoped": {
|
||||
"version": "3.0.0"
|
||||
},
|
||||
"node_modules/parent/node_modules/@scope/scoped-child": {
|
||||
"version": "4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "explicit::node::npm::local-link::sha256:ea69a4c271be378e84e910ddee0a83c3b6da4b4526146ce646e3ce411ae0aa07",
|
||||
"name": "local-link",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "pnpm-lock.yaml:local-link/0.0.0",
|
||||
"declared.source": "pnpm-lock.yaml",
|
||||
"declared.sourceType": "link",
|
||||
"declared.versionSpec": "link:../packages/local-link",
|
||||
"declaredOnly": "true",
|
||||
"lockIntegrityMissing": "true",
|
||||
"lockIntegrityMissingReason": "link"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "pnpm-lock.yaml:local-link/0.0.0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/%40scope/scoped@2.0.0",
|
||||
"purl": "pkg:npm/%40scope/scoped@2.0.0",
|
||||
"name": "@scope/scoped",
|
||||
"version": "2.0.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "pnpm-lock.yaml:@scope/scoped/2.0.0",
|
||||
"declared.resolvedVersion": "2.0.0",
|
||||
"declared.source": "pnpm-lock.yaml",
|
||||
"declared.sourceType": "range",
|
||||
"declared.versionSpec": "2.0.0",
|
||||
"declaredOnly": "true",
|
||||
"lockIntegrityMissing": "true",
|
||||
"lockIntegrityMissingReason": "missing"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "pnpm-lock.yaml:@scope/scoped/2.0.0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/left-pad@1.3.0",
|
||||
"purl": "pkg:npm/left-pad@1.3.0",
|
||||
"name": "left-pad",
|
||||
"version": "1.3.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "pnpm-lock.yaml:left-pad/1.3.0",
|
||||
"declared.resolvedVersion": "1.3.0",
|
||||
"declared.source": "pnpm-lock.yaml",
|
||||
"declared.sourceType": "range",
|
||||
"declared.versionSpec": "1.3.0",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "pnpm-lock.yaml:left-pad/1.3.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,10 @@
|
||||
lockfileVersion: 6.0
|
||||
|
||||
packages:
|
||||
/left-pad/1.3.0:
|
||||
resolution: {integrity: sha512-leftpad, tarball: https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz}
|
||||
/local-link/0.0.0:
|
||||
version: link:../packages/local-link
|
||||
resolution: {tarball: link:../packages/local-link}
|
||||
/@scope/scoped/2.0.0:
|
||||
resolution: {tarball: https://registry.npmjs.org/@scope/scoped/-/scoped-2.0.0.tgz}
|
||||
@@ -0,0 +1,98 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/%40scope/scoped@3.0.1",
|
||||
"purl": "pkg:npm/%40scope/scoped@3.0.1",
|
||||
"name": "@scope/scoped",
|
||||
"version": "3.0.1",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "yarn.lock:@scope/scoped@npm:^3.0.0",
|
||||
"declared.resolvedVersion": "3.0.1",
|
||||
"declared.source": "yarn.lock",
|
||||
"declared.sourceType": "range",
|
||||
"declared.versionSpec": "3.0.1",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "yarn.lock:@scope/scoped@npm:^3.0.0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/legacy@1.0.0",
|
||||
"purl": "pkg:npm/legacy@1.0.0",
|
||||
"name": "legacy",
|
||||
"version": "1.0.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "yarn.lock:legacy@^1.0.0",
|
||||
"declared.resolvedVersion": "1.0.0",
|
||||
"declared.source": "yarn.lock",
|
||||
"declared.sourceType": "range",
|
||||
"declared.versionSpec": "1.0.0",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "yarn.lock:legacy@^1.0.0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/multi@1.0.0",
|
||||
"purl": "pkg:npm/multi@1.0.0",
|
||||
"name": "multi",
|
||||
"version": "1.0.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "yarn.lock:multi@npm:^1.0.0",
|
||||
"declared.resolvedVersion": "1.0.0",
|
||||
"declared.source": "yarn.lock",
|
||||
"declared.sourceType": "range",
|
||||
"declared.versionSpec": "1.0.0",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "yarn.lock:multi@npm:^1.0.0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/multi@2.0.0",
|
||||
"purl": "pkg:npm/multi@2.0.0",
|
||||
"name": "multi",
|
||||
"version": "2.0.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "yarn.lock:multi@npm:^2.0.0",
|
||||
"declared.resolvedVersion": "2.0.0",
|
||||
"declared.source": "yarn.lock",
|
||||
"declared.sourceType": "range",
|
||||
"declared.versionSpec": "2.0.0",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "yarn.lock:multi@npm:^2.0.0"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,23 @@
|
||||
__metadata:
|
||||
version: 8
|
||||
cacheKey: 10
|
||||
|
||||
"multi@npm:^1.0.0":
|
||||
version: "1.0.0"
|
||||
resolution: "multi@npm:1.0.0"
|
||||
checksum: "abcd1234"
|
||||
|
||||
"multi@npm:^2.0.0":
|
||||
version: "2.0.0"
|
||||
resolution: "multi@npm:2.0.0"
|
||||
integrity: "sha512-xyz987"
|
||||
|
||||
"@scope/scoped@npm:^3.0.0":
|
||||
version: "3.0.1"
|
||||
resolution: "@scope/scoped@npm:3.0.1"
|
||||
checksum: "deadbeef"
|
||||
|
||||
legacy@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/legacy/-/legacy-1.0.0.tgz#abc123"
|
||||
integrity sha512-legacy
|
||||
@@ -17,7 +17,8 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "node_modules/.pnpm/pkg@1.2.3/node_modules/pkg/package.json"
|
||||
"locator": "node_modules/.pnpm/pkg@1.2.3/node_modules/pkg/package.json",
|
||||
"sha256": "23fc3dc23387b21780c9b0b3f8cf3e07e1619a0603325a2744e2a6d2873fceac"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
@@ -42,7 +43,8 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "package.json"
|
||||
"locator": "package.json",
|
||||
"sha256": "1ee30a64ac1806fececa1a00c36555930029c81c92de4b376c2610499c1cb435"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -34,7 +34,8 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "package.json"
|
||||
"locator": "package.json",
|
||||
"sha256": "e7bea1ac14004d809d1b649c1329c9e09ce69d458c3794ee98b4f37c6fa591b5"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "package.json"
|
||||
"locator": "package.json",
|
||||
"sha256": "452a5c537c19282754f6c32eebf8aea46e9604c76b8d3b16527cdab932701ff7"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
|
||||
@@ -31,8 +31,9 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "package.json"
|
||||
"locator": "package.json",
|
||||
"sha256": "3c16561eea74166e8add2e59d2bf93d55c035a7cdac640410332ee2b9e7a1a35"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -1,4 +1,53 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/declared-only@9.9.9",
|
||||
"purl": "pkg:npm/declared-only@9.9.9",
|
||||
"name": "declared-only",
|
||||
"version": "9.9.9",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "package-lock.json:packages/app/node_modules/declared-only",
|
||||
"declared.resolvedVersion": "9.9.9",
|
||||
"declared.source": "package-lock.json",
|
||||
"declared.sourceType": "range",
|
||||
"declared.versionSpec": "9.9.9",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "package-lock.json:packages/app/node_modules/declared-only"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/left-pad@1.3.0",
|
||||
"purl": "pkg:npm/left-pad@1.3.0",
|
||||
"name": "left-pad",
|
||||
"version": "1.3.0",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"declared.locator": "package-lock.json:packages/app/node_modules/left-pad",
|
||||
"declared.resolvedVersion": "1.3.0",
|
||||
"declared.scope": "production",
|
||||
"declared.source": "package-lock.json",
|
||||
"declared.sourceType": "range",
|
||||
"declared.versionSpec": "1.3.0",
|
||||
"declaredOnly": "true"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "node.declared",
|
||||
"locator": "package-lock.json:packages/app/node_modules/left-pad"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/lib@2.0.1",
|
||||
@@ -13,6 +62,8 @@
|
||||
"lockSource": "package-lock.json",
|
||||
"path": "packages/lib",
|
||||
"resolved": "https://registry.example/lib-2.0.1.tgz",
|
||||
"riskLevel": "production",
|
||||
"scope": "production",
|
||||
"workspaceMember": "true",
|
||||
"workspaceRoot": "packages/lib"
|
||||
},
|
||||
@@ -20,7 +71,30 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "packages/lib/package.json"
|
||||
"locator": "packages/lib/package.json",
|
||||
"sha256": "5198fbaf659fb4f8d9845a7ffa51067ac7e727631f2503615c962540fe8c2298"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/nested-tool@0.0.5",
|
||||
"purl": "pkg:npm/nested-tool@0.0.5",
|
||||
"name": "nested-tool",
|
||||
"version": "0.0.5",
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"path": "packages/nested/tool",
|
||||
"workspaceMember": "true",
|
||||
"workspaceRoot": "packages/nested/tool"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "packages/nested/tool/package.json",
|
||||
"sha256": "3011f57f07fab11b4ecb61788319bc9768d2577cafd9f53f37a7cac721fc77cf"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -42,7 +116,8 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "package.json"
|
||||
"locator": "package.json",
|
||||
"sha256": "aa060a0c2a8a6c41f68783d0f7366491e5560bb9af3ea043d6d2dc664de20a7f"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -60,6 +135,8 @@
|
||||
"lockSource": "package-lock.json",
|
||||
"path": "packages/shared",
|
||||
"resolved": "https://registry.example/shared-3.1.4.tgz",
|
||||
"riskLevel": "production",
|
||||
"scope": "production",
|
||||
"workspaceMember": "true",
|
||||
"workspaceRoot": "packages/shared",
|
||||
"workspaceTargets": "packages/lib"
|
||||
@@ -68,7 +145,8 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "packages/shared/package.json"
|
||||
"locator": "packages/shared/package.json",
|
||||
"sha256": "4440d351c91132499bedb21859b2a1813b25563b93a54eb1ad1ded79d18839d1"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -95,7 +173,8 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "packages/app/package.json"
|
||||
"locator": "packages/app/package.json",
|
||||
"sha256": "e734fc2024e5582200309bd190832f2f931a8b8af65dd11c49f0583c92195582"
|
||||
},
|
||||
{
|
||||
"kind": "metadata",
|
||||
@@ -106,4 +185,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -1,10 +1,9 @@
|
||||
{
|
||||
"name": "root-workspace",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"workspaces": [
|
||||
"packages/app",
|
||||
"packages/lib",
|
||||
"packages/shared"
|
||||
]
|
||||
}
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"workspaces": [
|
||||
"packages/*",
|
||||
"packages/**"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "nested-tool",
|
||||
"version": "0.0.5",
|
||||
"devDependencies": {
|
||||
"left-pad": "1.3.0"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,41 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "node-phase22",
|
||||
"componentKey": "/app/native/addon.node",
|
||||
"name": "addon.node",
|
||||
"type": "node:native",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"confidence": "0.82",
|
||||
"reason": "native-addon-file"
|
||||
},
|
||||
"evidence": []
|
||||
},
|
||||
{
|
||||
"analyzerId": "node-phase22",
|
||||
"componentKey": "/app/pkg/pkg.wasm",
|
||||
"name": "pkg.wasm",
|
||||
"type": "node:wasm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"confidence": "0.80",
|
||||
"reason": "wasm-file"
|
||||
},
|
||||
"evidence": []
|
||||
},
|
||||
{
|
||||
"analyzerId": "node-phase22",
|
||||
"componentKey": "/src/app.js",
|
||||
"name": "app.js",
|
||||
"type": "node:bundle",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"confidence": "0.87",
|
||||
"format": "esm",
|
||||
"reason": "source-map"
|
||||
},
|
||||
"evidence": []
|
||||
},
|
||||
{
|
||||
"analyzerId": "node",
|
||||
"componentKey": "purl::pkg:npm/cached-lib@1.0.0",
|
||||
@@ -8,9 +45,7 @@
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"lockLocator": "cached-lib@npm:1.0.0",
|
||||
"lockSource": "pnp.data",
|
||||
"path": ".yarn/cache/cached-lib-1.0.0.zip/node_modules/cached-lib",
|
||||
"path": ".yarn/cache",
|
||||
"yarnPnp": "true"
|
||||
},
|
||||
"evidence": [
|
||||
@@ -31,8 +66,6 @@
|
||||
"type": "npm",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"lockLocator": "yarn-pnp-demo@workspace:.",
|
||||
"lockSource": "pnp.data",
|
||||
"path": ".",
|
||||
"yarnPnp": "true"
|
||||
},
|
||||
@@ -40,9 +73,8 @@
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "package.json",
|
||||
"locator": "package.json",
|
||||
"sha256": "65e86ba14f0beebc4573039ac34a58f6dfa0133aa4a9e7f2dcdbb36a4e5c2814"
|
||||
"locator": "package.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -125,6 +125,107 @@ public sealed class NodeDeterminismTests : IDisposable
|
||||
|
||||
#endregion
|
||||
|
||||
[Fact]
|
||||
public async Task LockOnlyProject_EmitsDeclaredOnlyComponents_WithoutRangeAsPurl()
|
||||
{
|
||||
WriteFile("package.json", JsonSerializer.Serialize(new
|
||||
{
|
||||
name = "root",
|
||||
version = "1.0.0",
|
||||
dependencies = new Dictionary<string, string>
|
||||
{
|
||||
["express"] = "^4.18.2",
|
||||
["left-pad"] = "^1.3.0"
|
||||
}
|
||||
}));
|
||||
|
||||
WriteFile("package-lock.json", JsonSerializer.Serialize(new
|
||||
{
|
||||
name = "root",
|
||||
version = "1.0.0",
|
||||
lockfileVersion = 3,
|
||||
packages = new Dictionary<string, object>
|
||||
{
|
||||
[""] = new
|
||||
{
|
||||
name = "root",
|
||||
version = "1.0.0"
|
||||
},
|
||||
["node_modules/express"] = new
|
||||
{
|
||||
version = "4.18.2",
|
||||
resolved = "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
|
||||
integrity = "sha512-deadbeef"
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
var json = await RunAnalyzerAsync();
|
||||
using var document = JsonDocument.Parse(json);
|
||||
var components = document.RootElement.EnumerateArray().ToArray();
|
||||
|
||||
var express = components.Single(static element =>
|
||||
element.TryGetProperty("purl", out var purl)
|
||||
&& purl.ValueKind == JsonValueKind.String
|
||||
&& purl.GetString() == "pkg:npm/express@4.18.2");
|
||||
|
||||
var expressMeta = express.GetProperty("metadata");
|
||||
Assert.Equal("true", expressMeta.GetProperty("declaredOnly").GetString());
|
||||
Assert.Equal("package-lock.json", expressMeta.GetProperty("declared.source").GetString());
|
||||
Assert.Equal("package-lock.json:node_modules/express", expressMeta.GetProperty("declared.locator").GetString());
|
||||
Assert.Equal("^4.18.2", expressMeta.GetProperty("declared.versionSpec").GetString());
|
||||
Assert.Equal("4.18.2", expressMeta.GetProperty("declared.resolvedVersion").GetString());
|
||||
|
||||
var leftPad = components.Single(static element =>
|
||||
element.GetProperty("name").GetString() == "left-pad");
|
||||
|
||||
Assert.False(leftPad.TryGetProperty("purl", out _));
|
||||
Assert.StartsWith("explicit::node::npm::left-pad::sha256:", leftPad.GetProperty("componentKey").GetString(), StringComparison.Ordinal);
|
||||
|
||||
var leftPadMeta = leftPad.GetProperty("metadata");
|
||||
Assert.Equal("true", leftPadMeta.GetProperty("declaredOnly").GetString());
|
||||
Assert.Equal("package.json", leftPadMeta.GetProperty("declared.source").GetString());
|
||||
Assert.Equal("^1.3.0", leftPadMeta.GetProperty("declared.versionSpec").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PnpmLock_IntegrityMissing_EmitsDeclaredOnlyMetadata()
|
||||
{
|
||||
WriteFile("package.json", JsonSerializer.Serialize(new
|
||||
{
|
||||
name = "root",
|
||||
version = "1.0.0",
|
||||
dependencies = new Dictionary<string, string>
|
||||
{
|
||||
["local-file"] = "file:../local-file-1.0.0.tgz"
|
||||
}
|
||||
}));
|
||||
|
||||
var pnpmLock = "lockfileVersion: '6.0'\n" +
|
||||
"packages:\n" +
|
||||
" /local-file/1.0.0:\n" +
|
||||
" resolution: {tarball: file:../local-file-1.0.0.tgz}\n";
|
||||
WriteFile("pnpm-lock.yaml", pnpmLock);
|
||||
|
||||
var json = await RunAnalyzerAsync();
|
||||
using var document = JsonDocument.Parse(json);
|
||||
var components = document.RootElement.EnumerateArray().ToArray();
|
||||
|
||||
var localFile = components.Single(static element =>
|
||||
element.TryGetProperty("purl", out var purl)
|
||||
&& purl.ValueKind == JsonValueKind.String
|
||||
&& purl.GetString() == "pkg:npm/local-file@1.0.0");
|
||||
|
||||
var meta = localFile.GetProperty("metadata");
|
||||
Assert.Equal("true", meta.GetProperty("declaredOnly").GetString());
|
||||
Assert.Equal("pnpm-lock.yaml", meta.GetProperty("declared.source").GetString());
|
||||
Assert.Equal("pnpm-lock.yaml:local-file/1.0.0", meta.GetProperty("declared.locator").GetString());
|
||||
Assert.Equal("file:../local-file-1.0.0.tgz", meta.GetProperty("declared.versionSpec").GetString());
|
||||
Assert.Equal("1.0.0", meta.GetProperty("declared.resolvedVersion").GetString());
|
||||
Assert.Equal("true", meta.GetProperty("lockIntegrityMissing").GetString());
|
||||
Assert.Equal("file", meta.GetProperty("lockIntegrityMissingReason").GetString());
|
||||
}
|
||||
|
||||
#region Entrypoint Ordering
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
using StellaOps.Scanner.Analyzers.Lang.Node.Internal;
|
||||
|
||||
namespace StellaOps.Scanner.Analyzers.Lang.Node.Tests.Node;
|
||||
|
||||
public sealed class NodeImportWalkerTests
|
||||
{
|
||||
[Fact]
|
||||
public void AnalyzeImports_ParsesEsmImportsAndExports()
|
||||
{
|
||||
var content = """
|
||||
import foo from "foo";
|
||||
export { bar } from "bar";
|
||||
export * from "baz";
|
||||
""";
|
||||
|
||||
var edges = NodeImportWalker.AnalyzeImports("/repo", "src/index.mjs", content);
|
||||
|
||||
Assert.Contains(edges, e => e.TargetSpecifier == "foo" && e.Kind == "import");
|
||||
Assert.Contains(edges, e => e.TargetSpecifier == "bar" && e.Kind == "export-from");
|
||||
Assert.Contains(edges, e => e.TargetSpecifier == "baz" && e.Kind == "export-all");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AnalyzeImports_WhenParserFails_UsesTypeScriptRegexFallback()
|
||||
{
|
||||
var content = """
|
||||
import type { Foo } from "foo";
|
||||
export type { Bar } from "bar";
|
||||
|
||||
interface Thing { name: string }
|
||||
""";
|
||||
|
||||
var edges = NodeImportWalker.AnalyzeImports("/repo", "src/index.ts", content);
|
||||
|
||||
Assert.Contains(edges, e => e.TargetSpecifier == "foo" && e.Evidence == "ts-regex");
|
||||
Assert.Contains(edges, e => e.TargetSpecifier == "bar" && e.Kind == "export-from" && e.Evidence == "ts-regex");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,6 +190,54 @@ public sealed class NodeLanguageAnalyzerTests
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LockOnlyPackageLockEmitsDeclaredOnlyComponentsAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "node", "lock-only-package-lock");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[] { new NodeLanguageAnalyzer() };
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LockOnlyYarnBerryEmitsDeclaredOnlyComponentsAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "node", "lock-only-yarn-berry");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[] { new NodeLanguageAnalyzer() };
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LockOnlyPnpmEmitsDeclaredOnlyComponentsAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "node", "lock-only-pnpm");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[] { new NodeLanguageAnalyzer() };
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PnpmVirtualStoreIsParsedAsync()
|
||||
{
|
||||
@@ -237,4 +285,20 @@ public sealed class NodeLanguageAnalyzerTests
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PackageJsonDeclaredOnlyDependenciesUseExplicitKeyAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = TestPaths.ResolveFixture("lang", "node", "declared-only-package-json");
|
||||
var goldenPath = Path.Combine(fixturePath, "expected.json");
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[] { new NodeLanguageAnalyzer() };
|
||||
|
||||
await LanguageAnalyzerTestHarness.AssertDeterministicAsync(
|
||||
fixturePath,
|
||||
goldenPath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,34 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
Assert.Empty(result.DeclaredPackages);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LoadAsync_EmptyRootPath_DoesNotThrow_WhenCurrentDirectoryHasPackageJson()
|
||||
{
|
||||
var originalDirectory = Environment.CurrentDirectory;
|
||||
var tempDirectory = Path.Combine(Path.GetTempPath(), "node-lock-tests-cwd-" + Guid.NewGuid().ToString("N")[..8]);
|
||||
Directory.CreateDirectory(tempDirectory);
|
||||
|
||||
try
|
||||
{
|
||||
await File.WriteAllTextAsync(Path.Combine(tempDirectory, "package.json"), """
|
||||
{
|
||||
"name": "fixture",
|
||||
"version": "0.0.0"
|
||||
}
|
||||
""");
|
||||
|
||||
Environment.CurrentDirectory = tempDirectory;
|
||||
|
||||
var result = await NodeLockData.LoadAsync(string.Empty, CancellationToken.None);
|
||||
Assert.Empty(result.DeclaredPackages);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Environment.CurrentDirectory = originalDirectory;
|
||||
Directory.Delete(tempDirectory, recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LoadAsync_OnlyPackageJson_CreatesDeclaredOnlyEntries()
|
||||
{
|
||||
@@ -232,7 +260,6 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
[Fact]
|
||||
public async Task LoadPackageLockJson_V3Format_NestedNodeModules()
|
||||
{
|
||||
// Note: Nested node_modules require explicit name property for correct extraction
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "package-lock.json"), """
|
||||
{
|
||||
"lockfileVersion": 3,
|
||||
@@ -241,7 +268,6 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"node_modules/parent/node_modules/child": {
|
||||
"name": "child",
|
||||
"version": "2.0.0"
|
||||
}
|
||||
}
|
||||
@@ -253,6 +279,38 @@ public sealed class NodeLockDataTests : IDisposable
|
||||
Assert.Equal(2, result.DeclaredPackages.Count);
|
||||
Assert.Contains(result.DeclaredPackages, e => e.Name == "parent");
|
||||
Assert.Contains(result.DeclaredPackages, e => e.Name == "child");
|
||||
|
||||
Assert.True(result.TryGet("node_modules/parent/node_modules/child", "child", "2.0.0", out var entry));
|
||||
Assert.NotNull(entry);
|
||||
Assert.Equal("2.0.0", entry!.Version);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LoadPackageLockJson_V3Format_NestedNodeModules_ScopedChild()
|
||||
{
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "package-lock.json"), """
|
||||
{
|
||||
"lockfileVersion": 3,
|
||||
"packages": {
|
||||
"node_modules/parent": {
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"node_modules/parent/node_modules/@types/node": {
|
||||
"version": "20.10.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
|
||||
Assert.Equal(2, result.DeclaredPackages.Count);
|
||||
Assert.Contains(result.DeclaredPackages, e => e.Name == "parent");
|
||||
Assert.Contains(result.DeclaredPackages, e => e.Name == "@types/node");
|
||||
|
||||
Assert.True(result.TryGet("node_modules/parent/node_modules/@types/node", "@types/node", "20.10.0", out var entry));
|
||||
Assert.NotNull(entry);
|
||||
Assert.Equal("20.10.0", entry!.Version);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -495,6 +553,35 @@ valid@^2.0.0:
|
||||
Assert.Contains(result.DeclaredPackages, e => e.Name == "valid");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LoadYarnLock_BerryFormat_ParsesResolutionChecksum_AndSkipsMetadata()
|
||||
{
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "yarn.lock"), """
|
||||
__metadata:
|
||||
version: 6
|
||||
|
||||
"lodash@npm:^4.17.21":
|
||||
version: 4.17.21
|
||||
resolution: "lodash@npm:4.17.21"
|
||||
checksum: 10c0deadbeef
|
||||
""");
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
Assert.DoesNotContain(result.DeclaredPackages, e => e.Name == "__metadata");
|
||||
|
||||
var entry = result.DeclaredPackages.Single();
|
||||
Assert.Equal("lodash", entry.Name);
|
||||
Assert.Equal("4.17.21", entry.Version);
|
||||
Assert.Equal("lodash@npm:4.17.21", entry.Resolved);
|
||||
Assert.Equal("checksum:10c0deadbeef", entry.Integrity);
|
||||
|
||||
Assert.True(result.TryGet("", "lodash", "4.17.21", out var byVersion));
|
||||
Assert.NotNull(byVersion);
|
||||
Assert.Equal("lodash@npm:^4.17.21", byVersion!.Locator);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region pnpm-lock.yaml Parsing Tests
|
||||
@@ -557,6 +644,24 @@ valid@^2.0.0:
|
||||
Assert.Equal("4.18.2", result.DeclaredPackages.First().Version);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LoadPnpmLock_WhenVersionLineMissing_UsesVersionFromKey()
|
||||
{
|
||||
var content = "lockfileVersion: '6.0'\n" +
|
||||
"packages:\n" +
|
||||
" /express/4.18.2:\n" +
|
||||
" resolution: {integrity: sha512-xyz}\n";
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content);
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
var entry = result.DeclaredPackages.Single();
|
||||
Assert.Equal("express", entry.Name);
|
||||
Assert.Equal("4.18.2", entry.Version);
|
||||
Assert.Equal("sha512-xyz", entry.Integrity);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LoadPnpmLock_ExtractsTarball()
|
||||
{
|
||||
@@ -573,6 +678,43 @@ valid@^2.0.0:
|
||||
Assert.Contains("lodash-4.17.21.tgz", result.DeclaredPackages.First().Resolved);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LoadPnpmLock_IntegrityMissingReason_File()
|
||||
{
|
||||
var content = "lockfileVersion: '6.0'\n" +
|
||||
"packages:\n" +
|
||||
" /local-file/1.0.0:\n" +
|
||||
" resolution: {tarball: file:../local-file-1.0.0.tgz}\n";
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content);
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
var entry = result.DeclaredPackages.Single();
|
||||
Assert.Equal("local-file", entry.Name);
|
||||
Assert.True(entry.IntegrityMissing);
|
||||
Assert.Equal("file", entry.IntegrityMissingReason);
|
||||
Assert.StartsWith("file:", entry.Resolved, StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LoadPnpmLock_SnapshotsSection_IsParsed()
|
||||
{
|
||||
var content = "lockfileVersion: '9.0'\n" +
|
||||
"snapshots:\n" +
|
||||
" /snap-only/1.0.0:\n" +
|
||||
" resolution: {integrity: sha512-snap}\n";
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "pnpm-lock.yaml"), content);
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
var entry = result.DeclaredPackages.Single();
|
||||
Assert.Equal("snap-only", entry.Name);
|
||||
Assert.Equal("1.0.0", entry.Version);
|
||||
Assert.Equal("sha512-snap", entry.Integrity);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LoadPnpmLock_SeparateIntegrityLine()
|
||||
{
|
||||
@@ -590,7 +732,7 @@ valid@^2.0.0:
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task LoadPnpmLock_SkipsPackagesWithoutIntegrity()
|
||||
public async Task LoadPnpmLock_PackagesWithoutIntegrity_AreKeptAndMarked()
|
||||
{
|
||||
var content = "lockfileVersion: '6.0'\n" +
|
||||
"packages:\n" +
|
||||
@@ -603,8 +745,19 @@ valid@^2.0.0:
|
||||
|
||||
var result = await NodeLockData.LoadAsync(_tempDir, CancellationToken.None);
|
||||
|
||||
Assert.Single(result.DeclaredPackages);
|
||||
Assert.Equal("has-integrity", result.DeclaredPackages.First().Name);
|
||||
Assert.Equal(2, result.DeclaredPackages.Count);
|
||||
|
||||
var noIntegrity = result.DeclaredPackages.Single(e => e.Name == "no-integrity");
|
||||
Assert.Equal("1.0.0", noIntegrity.Version);
|
||||
Assert.Null(noIntegrity.Integrity);
|
||||
Assert.True(noIntegrity.IntegrityMissing);
|
||||
Assert.Equal("missing", noIntegrity.IntegrityMissingReason);
|
||||
|
||||
var hasIntegrity = result.DeclaredPackages.Single(e => e.Name == "has-integrity");
|
||||
Assert.Equal("2.0.0", hasIntegrity.Version);
|
||||
Assert.Equal("sha512-valid", hasIntegrity.Integrity);
|
||||
Assert.False(hasIntegrity.IntegrityMissing);
|
||||
Assert.Null(hasIntegrity.IntegrityMissingReason);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -863,6 +1016,12 @@ valid@^2.0.0:
|
||||
Assert.True(result.TryGet("", "lodash", out var byNameEntry));
|
||||
Assert.Equal("4.0.0", byNameEntry!.Version);
|
||||
|
||||
Assert.True(result.TryGet("", "lodash", "4.17.21", out var byVersionEntry));
|
||||
Assert.Equal("4.17.21", byVersionEntry!.Version);
|
||||
|
||||
Assert.True(result.TryGet("", "lodash", "4.0.0", out var byVersionEntry2));
|
||||
Assert.Equal("4.0.0", byVersionEntry2!.Version);
|
||||
|
||||
// For TryGet lookups by path, package-lock.json entry is found
|
||||
Assert.True(result.TryGet("node_modules/lodash", "", out var byPathEntry));
|
||||
Assert.Equal("4.17.21", byPathEntry!.Version);
|
||||
|
||||
@@ -611,6 +611,177 @@ public sealed class NodePackageCollectorTraversalTests : IDisposable
|
||||
|
||||
#endregion
|
||||
|
||||
#region Lock Metadata Attachment
|
||||
|
||||
[Fact]
|
||||
public async Task Traversal_NestedNodeModules_AttachesCorrectLockMetadata()
|
||||
{
|
||||
WritePackageJson(_tempDir, "root-app", "1.0.0", isPrivate: true);
|
||||
|
||||
var nodeModules = Path.Combine(_tempDir, "node_modules");
|
||||
WritePackageJson(Path.Combine(nodeModules, "parent"), "parent", "1.0.0");
|
||||
WritePackageJson(Path.Combine(nodeModules, "parent", "node_modules", "child"), "child", "2.0.0");
|
||||
|
||||
await File.WriteAllTextAsync(Path.Combine(_tempDir, "package-lock.json"), """
|
||||
{
|
||||
"lockfileVersion": 3,
|
||||
"packages": {
|
||||
"node_modules/parent": {
|
||||
"version": "1.0.0",
|
||||
"integrity": "sha512-parent"
|
||||
},
|
||||
"node_modules/parent/node_modules/child": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://example.com/child.tgz",
|
||||
"integrity": "sha512-child"
|
||||
}
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
var json = await RunAnalyzerAsync();
|
||||
using var document = JsonDocument.Parse(json);
|
||||
var components = document.RootElement.EnumerateArray().ToArray();
|
||||
|
||||
var child = components.Single(static element =>
|
||||
element.TryGetProperty("purl", out var purl)
|
||||
&& purl.ValueKind == JsonValueKind.String
|
||||
&& purl.GetString() == "pkg:npm/child@2.0.0");
|
||||
|
||||
var metadata = child.GetProperty("metadata");
|
||||
Assert.Equal("sha512-child", metadata.GetProperty("integrity").GetString());
|
||||
Assert.Equal("https://example.com/child.tgz", metadata.GetProperty("resolved").GetString());
|
||||
Assert.Equal("package-lock.json", metadata.GetProperty("lockSource").GetString());
|
||||
Assert.Equal("package-lock.json:node_modules/parent/node_modules/child", metadata.GetProperty("lockLocator").GetString());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Workspace Scope Attribution
|
||||
|
||||
[Fact]
|
||||
public async Task Traversal_WorkspaceDependencyScopes_AreDerivedFromWorkspaceManifest()
|
||||
{
|
||||
File.WriteAllText(Path.Combine(_tempDir, "package.json"), """
|
||||
{
|
||||
"name": "root-app",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"workspaces": ["packages/*"]
|
||||
}
|
||||
""");
|
||||
|
||||
var workspaceDir = Path.Combine(_tempDir, "packages", "app");
|
||||
Directory.CreateDirectory(workspaceDir);
|
||||
File.WriteAllText(Path.Combine(workspaceDir, "package.json"), """
|
||||
{
|
||||
"name": "app",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"prod-dep": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dev-dep": "^1.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"opt-dep": "^1.0.0"
|
||||
}
|
||||
}
|
||||
""");
|
||||
|
||||
var nodeModules = Path.Combine(workspaceDir, "node_modules");
|
||||
WritePackageJson(Path.Combine(nodeModules, "prod-dep"), "prod-dep", "1.0.0");
|
||||
WritePackageJson(Path.Combine(nodeModules, "dev-dep"), "dev-dep", "1.0.0");
|
||||
WritePackageJson(Path.Combine(nodeModules, "opt-dep"), "opt-dep", "1.0.0");
|
||||
|
||||
var json = await RunAnalyzerAsync();
|
||||
using var document = JsonDocument.Parse(json);
|
||||
var components = document.RootElement.EnumerateArray().ToArray();
|
||||
|
||||
var prod = components.Single(static element =>
|
||||
element.TryGetProperty("purl", out var purl)
|
||||
&& purl.ValueKind == JsonValueKind.String
|
||||
&& purl.GetString() == "pkg:npm/prod-dep@1.0.0");
|
||||
Assert.Equal("production", prod.GetProperty("metadata").GetProperty("scope").GetString());
|
||||
Assert.Equal("production", prod.GetProperty("metadata").GetProperty("riskLevel").GetString());
|
||||
|
||||
var dev = components.Single(static element =>
|
||||
element.TryGetProperty("purl", out var purl)
|
||||
&& purl.ValueKind == JsonValueKind.String
|
||||
&& purl.GetString() == "pkg:npm/dev-dep@1.0.0");
|
||||
Assert.Equal("development", dev.GetProperty("metadata").GetProperty("scope").GetString());
|
||||
Assert.Equal("development", dev.GetProperty("metadata").GetProperty("riskLevel").GetString());
|
||||
|
||||
var opt = components.Single(static element =>
|
||||
element.TryGetProperty("purl", out var purl)
|
||||
&& purl.ValueKind == JsonValueKind.String
|
||||
&& purl.GetString() == "pkg:npm/opt-dep@1.0.0");
|
||||
Assert.Equal("optional", opt.GetProperty("metadata").GetProperty("scope").GetString());
|
||||
Assert.Equal("optional", opt.GetProperty("metadata").GetProperty("riskLevel").GetString());
|
||||
Assert.Equal("true", opt.GetProperty("metadata").GetProperty("optional").GetString());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Import Scanning Bounds
|
||||
|
||||
[Fact]
|
||||
public async Task Traversal_ImportScan_SkipsNodeModulesPackagesByDefault()
|
||||
{
|
||||
WritePackageJson(_tempDir, "root-app", "1.0.0", isPrivate: true);
|
||||
Directory.CreateDirectory(Path.Combine(_tempDir, "src"));
|
||||
File.WriteAllText(Path.Combine(_tempDir, "src", "index.js"), "import foo from \"foo\";\n");
|
||||
|
||||
var fooDir = Path.Combine(_tempDir, "node_modules", "foo");
|
||||
WritePackageJson(fooDir, "foo", "1.0.0");
|
||||
File.WriteAllText(Path.Combine(fooDir, "index.js"), "import bar from \"bar\";\n");
|
||||
|
||||
var json = await RunAnalyzerAsync();
|
||||
using var document = JsonDocument.Parse(json);
|
||||
var components = document.RootElement.EnumerateArray().ToArray();
|
||||
|
||||
var root = components.Single(static element =>
|
||||
element.TryGetProperty("purl", out var purl)
|
||||
&& purl.ValueKind == JsonValueKind.String
|
||||
&& purl.GetString() == "pkg:npm/root-app@1.0.0");
|
||||
Assert.Contains(root.GetProperty("evidence").EnumerateArray(), e => e.GetProperty("source").GetString() == "node.import");
|
||||
|
||||
var foo = components.Single(static element =>
|
||||
element.TryGetProperty("purl", out var purl)
|
||||
&& purl.ValueKind == JsonValueKind.String
|
||||
&& purl.GetString() == "pkg:npm/foo@1.0.0");
|
||||
Assert.DoesNotContain(foo.GetProperty("evidence").EnumerateArray(), e => e.GetProperty("source").GetString() == "node.import");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Traversal_ImportScan_WhenCapped_EmitsImportScanSkippedMetadata()
|
||||
{
|
||||
WritePackageJson(_tempDir, "root-app", "1.0.0", isPrivate: true);
|
||||
var srcDir = Path.Combine(_tempDir, "src");
|
||||
Directory.CreateDirectory(srcDir);
|
||||
|
||||
for (var i = 0; i < 510; i++)
|
||||
{
|
||||
File.WriteAllText(Path.Combine(srcDir, $"file-{i:D4}.js"), ";\n");
|
||||
}
|
||||
|
||||
var json = await RunAnalyzerAsync();
|
||||
using var document = JsonDocument.Parse(json);
|
||||
var components = document.RootElement.EnumerateArray().ToArray();
|
||||
|
||||
var root = components.Single(static element =>
|
||||
element.TryGetProperty("purl", out var purl)
|
||||
&& purl.ValueKind == JsonValueKind.String
|
||||
&& purl.GetString() == "pkg:npm/root-app@1.0.0");
|
||||
|
||||
var metadata = root.GetProperty("metadata");
|
||||
Assert.Equal("true", metadata.GetProperty("importScanSkipped").GetString());
|
||||
Assert.Equal("500", metadata.GetProperty("importScan.filesScanned").GetString());
|
||||
Assert.True(metadata.TryGetProperty("importScan.bytesScanned", out _));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Deeply Nested Packages
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
using StellaOps.Scanner.Analyzers.Lang.Node.Internal;
|
||||
|
||||
namespace StellaOps.Scanner.Analyzers.Lang.Node.Tests.Node;
|
||||
|
||||
public sealed class NodeWorkspaceIndexTests : IDisposable
|
||||
{
|
||||
private readonly string _tempDir;
|
||||
|
||||
public NodeWorkspaceIndexTests()
|
||||
{
|
||||
_tempDir = Path.Combine(Path.GetTempPath(), "node-workspace-index-tests-" + Guid.NewGuid().ToString("N")[..8]);
|
||||
Directory.CreateDirectory(_tempDir);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (Directory.Exists(_tempDir))
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(_tempDir, recursive: true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore cleanup failures in tests
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteFile(string relativePath, string content)
|
||||
{
|
||||
var fullPath = Path.Combine(_tempDir, relativePath);
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(fullPath)!);
|
||||
File.WriteAllText(fullPath, content);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_NoPackageJson_ReturnsEmpty()
|
||||
{
|
||||
var index = NodeWorkspaceIndex.Create(_tempDir);
|
||||
|
||||
Assert.Empty(index.GetMembers());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_PackagesStar_ExpandsImmediateChildren_Deterministically()
|
||||
{
|
||||
WriteFile("package.json", """
|
||||
{
|
||||
"workspaces": ["packages/*", "./tools/*"]
|
||||
}
|
||||
""");
|
||||
|
||||
WriteFile("packages/a/package.json", """{ "name": "a", "version": "1.0.0" }""");
|
||||
WriteFile("packages/b/package.json", """{ "name": "b", "version": "1.0.0" }""");
|
||||
Directory.CreateDirectory(Path.Combine(_tempDir, "packages", "empty"));
|
||||
|
||||
WriteFile("tools/t1/package.json", """{ "name": "t1", "version": "1.0.0" }""");
|
||||
|
||||
var index = NodeWorkspaceIndex.Create(_tempDir);
|
||||
|
||||
Assert.Equal(new[] { "packages/a", "packages/b", "tools/t1" }, index.GetMembers().ToArray());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_DoubleStar_ExpandsNestedMembers_AndSkipsNodeModules()
|
||||
{
|
||||
WriteFile("package.json", """
|
||||
{
|
||||
"workspaces": ["apps/**"]
|
||||
}
|
||||
""");
|
||||
|
||||
WriteFile("apps/app2/package.json", """{ "name": "app2", "version": "1.0.0" }""");
|
||||
WriteFile("apps/team/app1/package.json", """{ "name": "app1", "version": "1.0.0" }""");
|
||||
WriteFile("apps/team/node_modules/evil/package.json", """{ "name": "evil", "version": "1.0.0" }""");
|
||||
|
||||
var index = NodeWorkspaceIndex.Create(_tempDir);
|
||||
|
||||
Assert.Equal(new[] { "apps/app2", "apps/team/app1" }, index.GetMembers().ToArray());
|
||||
Assert.False(index.TryGetMember("apps/team/node_modules/evil", out _));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_PackagesDoubleStar_DoesNotIncludeNodeModulesTree()
|
||||
{
|
||||
WriteFile("package.json", """
|
||||
{
|
||||
"workspaces": ["packages/**"]
|
||||
}
|
||||
""");
|
||||
|
||||
WriteFile("packages/ok/package.json", """{ "name": "ok", "version": "1.0.0" }""");
|
||||
WriteFile("packages/node_modules/evil/package.json", """{ "name": "evil", "version": "1.0.0" }""");
|
||||
|
||||
var index = NodeWorkspaceIndex.Create(_tempDir);
|
||||
|
||||
Assert.Single(index.GetMembers());
|
||||
Assert.Equal("packages/ok", index.GetMembers().Single());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,12 +17,10 @@
|
||||
<PackageReference Remove="xunit" />
|
||||
<PackageReference Remove="xunit.runner.visualstudio" />
|
||||
<PackageReference Remove="Microsoft.AspNetCore.Mvc.Testing" />
|
||||
<PackageReference Remove="Mongo2Go" />
|
||||
<PackageReference Remove="coverlet.collector" />
|
||||
<PackageReference Remove="Microsoft.Extensions.TimeProvider.Testing" />
|
||||
<ProjectReference Remove="..\StellaOps.Concelier.Testing\StellaOps.Concelier.Testing.csproj" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\StellaOps.Concelier.Tests.Shared\AssemblyInfo.cs" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\StellaOps.Concelier.Tests.Shared\MongoFixtureCollection.cs" />
|
||||
<Using Remove="StellaOps.Concelier.Testing" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -14,12 +14,10 @@
|
||||
<PackageReference Remove="xunit" />
|
||||
<PackageReference Remove="xunit.runner.visualstudio" />
|
||||
<PackageReference Remove="Microsoft.AspNetCore.Mvc.Testing" />
|
||||
<PackageReference Remove="Mongo2Go" />
|
||||
<PackageReference Remove="coverlet.collector" />
|
||||
<PackageReference Remove="Microsoft.Extensions.TimeProvider.Testing" />
|
||||
<ProjectReference Remove="..\StellaOps.Concelier.Testing\StellaOps.Concelier.Testing.csproj" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\StellaOps.Concelier.Tests.Shared\AssemblyInfo.cs" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\StellaOps.Concelier.Tests.Shared\MongoFixtureCollection.cs" />
|
||||
<Using Remove="StellaOps.Concelier.Testing" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using StellaOps.Scanner.Analyzers.Lang.Python.Internal.Entrypoints;
|
||||
using StellaOps.Scanner.Analyzers.Lang.Python.Internal.VirtualFileSystem;
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace StellaOps.Scanner.Analyzers.Lang.Python.Tests.Entrypoints;
|
||||
|
||||
@@ -86,6 +87,40 @@ mygui = mypackage.gui:start
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DiscoverAsync_FindsZipappMain()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var tempPath = CreateTemporaryWorkspace();
|
||||
try
|
||||
{
|
||||
var zipappPath = Path.Combine(tempPath, "app.pyz");
|
||||
using (var stream = File.Create(zipappPath))
|
||||
using (var archive = new ZipArchive(stream, ZipArchiveMode.Create, leaveOpen: false))
|
||||
{
|
||||
var entry = archive.CreateEntry("__main__.py");
|
||||
await using var entryStream = entry.Open();
|
||||
await using var writer = new StreamWriter(entryStream);
|
||||
await writer.WriteAsync("print('hello')".AsMemory(), cancellationToken);
|
||||
}
|
||||
|
||||
var vfs = PythonVirtualFileSystem.CreateBuilder()
|
||||
.AddZipapp(zipappPath)
|
||||
.Build();
|
||||
|
||||
var discovery = new PythonEntrypointDiscovery(vfs, tempPath);
|
||||
await discovery.DiscoverAsync(cancellationToken);
|
||||
|
||||
Assert.Contains(discovery.Entrypoints, e =>
|
||||
e.Kind == PythonEntrypointKind.ZipappMain &&
|
||||
e.Name == "__main__");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(tempPath, recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DiscoverAsync_FindsDjangoManage()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: hiddenpkg
|
||||
Version: 0.1.0
|
||||
Summary: Hidden layer package
|
||||
@@ -0,0 +1 @@
|
||||
__version__ = "0.1.0"
|
||||
@@ -1,4 +1,38 @@
|
||||
[
|
||||
{
|
||||
"analyzerId": "python",
|
||||
"componentKey": "purl::pkg:pypi/hiddenpkg@0.1.0",
|
||||
"purl": "pkg:pypi/hiddenpkg@0.1.0",
|
||||
"name": "hiddenpkg",
|
||||
"version": "0.1.0",
|
||||
"type": "pypi",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"distInfoPath": ".layers/layer0/usr/lib/python3.11/site-packages/hiddenpkg-0.1.0.dist-info",
|
||||
"name": "hiddenpkg",
|
||||
"normalizedName": "hiddenpkg",
|
||||
"pkg.confidence": "High",
|
||||
"pkg.kind": "Wheel",
|
||||
"pkg.location": ".layers/layer0/usr/lib/python3.11/site-packages/hiddenpkg-0.1.0.dist-info",
|
||||
"provenance": "dist-info",
|
||||
"record.hashMismatches": "0",
|
||||
"record.hashedEntries": "0",
|
||||
"record.ioErrors": "0",
|
||||
"record.missingFiles": "0",
|
||||
"record.totalEntries": "0",
|
||||
"runtime.libPaths.count": "2",
|
||||
"runtime.versions": "3.11",
|
||||
"summary": "Hidden layer package",
|
||||
"version": "0.1.0"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "METADATA",
|
||||
"locator": ".layers/layer0/usr/lib/python3.11/site-packages/hiddenpkg-0.1.0.dist-info/METADATA"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "python",
|
||||
"componentKey": "purl::pkg:pypi/layered@2.0",
|
||||
@@ -6,37 +40,38 @@
|
||||
"name": "layered",
|
||||
"version": "2.0",
|
||||
"type": "pypi",
|
||||
"usedByEntrypoint": true,
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"author": "Layered Maintainer",
|
||||
"authorEmail": "maintainer@example.com",
|
||||
"classifier[0]": "Programming Language :: Python :: 3",
|
||||
"classifiers": "Programming Language :: Python :: 3",
|
||||
"distInfoPath": "layer1/usr/lib/python3.11/site-packages/layered-2.0.dist-info",
|
||||
"classifier[0]": "License :: OSI Approved :: Apache Software License",
|
||||
"classifiers": "License :: OSI Approved :: Apache Software License",
|
||||
"distInfoPath": "layer2/usr/lib/python3.11/site-packages/layered-2.0.dist-info",
|
||||
"editable": "true",
|
||||
"entryPoints.console_scripts": "layered-cli=layered.cli:main",
|
||||
"entryPoints.layered.hooks": "register=layered.plugins:register",
|
||||
"installer": "pip",
|
||||
"license": "Apache-2.0",
|
||||
"license.classifier[0]": "License :: OSI Approved :: Apache Software License",
|
||||
"license.file[0]": "layer2/usr/lib/python3.11/site-packages/LICENSE",
|
||||
"licenseExpression": "Apache-2.0",
|
||||
"name": "layered",
|
||||
"normalizedName": "layered",
|
||||
"pkg.confidence": "Definitive",
|
||||
"pkg.kind": "Wheel",
|
||||
"pkg.location": "layer2/usr/lib/python3.11/site-packages/layered-2.0.dist-info",
|
||||
"projectUrl": "Documentation, https://example.com/layered/docs",
|
||||
"provenance": "dist-info",
|
||||
"record.hashMismatches": "0",
|
||||
"record.hashedEntries": "7",
|
||||
"record.hashedEntries": "8",
|
||||
"record.ioErrors": "0",
|
||||
"record.missingFiles": "1",
|
||||
"record.missingFiles": "0",
|
||||
"record.totalEntries": "9",
|
||||
"requiresDist": "requests",
|
||||
"requiresPython": "\u003E=3.9",
|
||||
"runtime.libPaths.count": "2",
|
||||
"runtime.versions": "3.11",
|
||||
"sourceCommit": "abc123",
|
||||
"sourceSubdirectory": "src/layered",
|
||||
"sourceUrl": "https://git.example.com/layered",
|
||||
"sourceVcs": "git",
|
||||
"summary": "Base layer metadata",
|
||||
"summary": "Overlay metadata adding direct URL information",
|
||||
"version": "2.0",
|
||||
"wheel.generator": "pip 24.0",
|
||||
"wheel.rootIsPurelib": "true",
|
||||
@@ -44,57 +79,26 @@
|
||||
"wheel.version": "1.0"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "derived",
|
||||
"source": "RECORD",
|
||||
"locator": "layer1/usr/bin/layered-cli",
|
||||
"value": "missing"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "INSTALLER",
|
||||
"locator": "layer1/usr/lib/python3.11/site-packages/layered-2.0.dist-info/INSTALLER"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "INSTALLER",
|
||||
"locator": "layer2/usr/lib/python3.11/site-packages/layered-2.0.dist-info/INSTALLER"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "METADATA",
|
||||
"locator": "layer1/usr/lib/python3.11/site-packages/layered-2.0.dist-info/METADATA"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "METADATA",
|
||||
"locator": "layer2/usr/lib/python3.11/site-packages/layered-2.0.dist-info/METADATA"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "RECORD",
|
||||
"locator": "layer1/usr/lib/python3.11/site-packages/layered-2.0.dist-info/RECORD"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "RECORD",
|
||||
"locator": "layer2/usr/lib/python3.11/site-packages/layered-2.0.dist-info/RECORD"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "WHEEL",
|
||||
"locator": "layer1/usr/lib/python3.11/site-packages/layered-2.0.dist-info/WHEEL"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "WHEEL",
|
||||
"locator": "layer2/usr/lib/python3.11/site-packages/layered-2.0.dist-info/WHEEL"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "entry_points.txt",
|
||||
"locator": "layer1/usr/lib/python3.11/site-packages/layered-2.0.dist-info/entry_points.txt"
|
||||
},
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "entry_points.txt",
|
||||
@@ -112,5 +116,39 @@
|
||||
"value": "https://git.example.com/layered"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"analyzerId": "python",
|
||||
"componentKey": "purl::pkg:pypi/layerspkg@0.2.0",
|
||||
"purl": "pkg:pypi/layerspkg@0.2.0",
|
||||
"name": "layerspkg",
|
||||
"version": "0.2.0",
|
||||
"type": "pypi",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"distInfoPath": "layers/layer3/usr/lib/python3.11/site-packages/layerspkg-0.2.0.dist-info",
|
||||
"name": "layerspkg",
|
||||
"normalizedName": "layerspkg",
|
||||
"pkg.confidence": "High",
|
||||
"pkg.kind": "Wheel",
|
||||
"pkg.location": "layers/layer3/usr/lib/python3.11/site-packages/layerspkg-0.2.0.dist-info",
|
||||
"provenance": "dist-info",
|
||||
"record.hashMismatches": "0",
|
||||
"record.hashedEntries": "0",
|
||||
"record.ioErrors": "0",
|
||||
"record.missingFiles": "0",
|
||||
"record.totalEntries": "0",
|
||||
"runtime.libPaths.count": "2",
|
||||
"runtime.versions": "3.11",
|
||||
"summary": "Layers/ root package",
|
||||
"version": "0.2.0"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "file",
|
||||
"source": "METADATA",
|
||||
"locator": "layers/layer3/usr/lib/python3.11/site-packages/layerspkg-0.2.0.dist-info/METADATA"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: layerspkg
|
||||
Version: 0.2.0
|
||||
Summary: Layers/ root package
|
||||
@@ -0,0 +1 @@
|
||||
__version__ = "0.2.0"
|
||||
@@ -20,6 +20,9 @@
|
||||
"license.file[0]": "LICENSE",
|
||||
"name": "Cache-Pkg",
|
||||
"normalizedName": "cache-pkg",
|
||||
"pkg.confidence": "Definitive",
|
||||
"pkg.kind": "Wheel",
|
||||
"pkg.location": "lib/python3.11/site-packages/cache_pkg-1.2.3.dist-info",
|
||||
"projectUrl": "Source, https://example.com/cache-pkg",
|
||||
"provenance": "dist-info",
|
||||
"record.hashMismatches": "1",
|
||||
@@ -86,4 +89,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -22,6 +22,9 @@
|
||||
"license.classifier[0]": "License :: OSI Approved :: Apache Software License",
|
||||
"name": "simple",
|
||||
"normalizedName": "simple",
|
||||
"pkg.confidence": "Definitive",
|
||||
"pkg.kind": "Wheel",
|
||||
"pkg.location": "lib/python3.11/site-packages/simple-1.0.0.dist-info",
|
||||
"projectUrl": "Source, https://example.com/simple/src",
|
||||
"provenance": "dist-info",
|
||||
"record.hashMismatches": "0",
|
||||
@@ -84,4 +87,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.IO.Compression;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
@@ -125,6 +126,137 @@ public sealed class PythonLanguageAnalyzerTests
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EditableRequirementsUseExplicitKeyWithoutHostPathLeakAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = CreateTemporaryWorkspace();
|
||||
|
||||
try
|
||||
{
|
||||
var editableDir = Path.Combine(fixturePath, "editable-src");
|
||||
Directory.CreateDirectory(editableDir);
|
||||
|
||||
var requirementsPath = Path.Combine(fixturePath, "requirements.txt");
|
||||
await File.WriteAllTextAsync(requirementsPath, $"--editable {editableDir}{Environment.NewLine}", cancellationToken);
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new PythonLanguageAnalyzer()
|
||||
};
|
||||
|
||||
var json = await LanguageAnalyzerTestHarness.RunToJsonAsync(
|
||||
fixturePath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
|
||||
using var document = JsonDocument.Parse(json);
|
||||
var root = document.RootElement;
|
||||
|
||||
foreach (var component in root.EnumerateArray())
|
||||
{
|
||||
if (component.TryGetProperty("purl", out var purlElement) && purlElement.ValueKind == JsonValueKind.String)
|
||||
{
|
||||
Assert.DoesNotContain("@editable", purlElement.GetString(), StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
var editableComponent = root.EnumerateArray().Single(static component =>
|
||||
component.TryGetProperty("name", out var nameElement)
|
||||
&& string.Equals("editable-src", nameElement.GetString(), StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
Assert.True(!editableComponent.TryGetProperty("purl", out var purlValue) || purlValue.ValueKind == JsonValueKind.Null);
|
||||
|
||||
var componentKey = editableComponent.GetProperty("componentKey").GetString();
|
||||
Assert.StartsWith("explicit::python::pypi::editable-src::sha256:", componentKey, StringComparison.Ordinal);
|
||||
|
||||
var metadata = editableComponent.GetProperty("metadata");
|
||||
Assert.Equal("true", metadata.GetProperty("declaredOnly").GetString());
|
||||
Assert.Equal("editable", metadata.GetProperty("declared.sourceType").GetString());
|
||||
Assert.Equal("requirements.txt", metadata.GetProperty("declared.source").GetString());
|
||||
Assert.Equal("requirements.txt", metadata.GetProperty("declared.locator").GetString());
|
||||
|
||||
var editableSpec = metadata.GetProperty("lockEditablePath").GetString();
|
||||
Assert.Equal("editable-src", editableSpec);
|
||||
Assert.DoesNotContain(fixturePath, editableSpec, StringComparison.OrdinalIgnoreCase);
|
||||
Assert.DoesNotContain(":", editableSpec, StringComparison.Ordinal);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(fixturePath, recursive: true);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WheelArchiveDistInfo_IsVerifiedFromRecordAsync()
|
||||
{
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
var fixturePath = CreateTemporaryWorkspace();
|
||||
try
|
||||
{
|
||||
var distDir = Path.Combine(fixturePath, "dist");
|
||||
Directory.CreateDirectory(distDir);
|
||||
|
||||
var wheelPath = Path.Combine(distDir, "archivepkg-1.0.0-py3-none-any.whl");
|
||||
|
||||
var initBytes = Encoding.UTF8.GetBytes("__version__ = \"1.0.0\"\n");
|
||||
var metadataBytes = Encoding.UTF8.GetBytes(
|
||||
$"Metadata-Version: 2.1\nName: archivepkg\nVersion: 1.0.0\n{Environment.NewLine}");
|
||||
var wheelBytes = Encoding.UTF8.GetBytes(
|
||||
"Wheel-Version: 1.0\nGenerator: test\nRoot-Is-Purelib: true\nTag: py3-none-any\n");
|
||||
|
||||
var recordContent = new StringBuilder()
|
||||
.AppendLine($"archivepkg/__init__.py,sha256={ComputeSha256Base64(initBytes)},{initBytes.Length}")
|
||||
.AppendLine($"archivepkg-1.0.0.dist-info/METADATA,sha256={ComputeSha256Base64(metadataBytes)},{metadataBytes.Length}")
|
||||
.AppendLine($"archivepkg-1.0.0.dist-info/WHEEL,sha256={ComputeSha256Base64(wheelBytes)},{wheelBytes.Length}")
|
||||
.AppendLine("archivepkg-1.0.0.dist-info/RECORD,,")
|
||||
.ToString();
|
||||
var recordBytes = Encoding.UTF8.GetBytes(recordContent);
|
||||
|
||||
using (var stream = File.Create(wheelPath))
|
||||
using (var archive = new ZipArchive(stream, ZipArchiveMode.Create, leaveOpen: false))
|
||||
{
|
||||
WriteEntry(archive, "archivepkg/__init__.py", initBytes);
|
||||
WriteEntry(archive, "archivepkg-1.0.0.dist-info/METADATA", metadataBytes);
|
||||
WriteEntry(archive, "archivepkg-1.0.0.dist-info/WHEEL", wheelBytes);
|
||||
WriteEntry(archive, "archivepkg-1.0.0.dist-info/RECORD", recordBytes);
|
||||
}
|
||||
|
||||
var analyzers = new ILanguageAnalyzer[]
|
||||
{
|
||||
new PythonLanguageAnalyzer()
|
||||
};
|
||||
|
||||
var json = await LanguageAnalyzerTestHarness.RunToJsonAsync(
|
||||
fixturePath,
|
||||
analyzers,
|
||||
cancellationToken);
|
||||
|
||||
using var document = JsonDocument.Parse(json);
|
||||
var root = document.RootElement;
|
||||
|
||||
Assert.True(ComponentHasMetadata(root, "archivepkg", "record.totalEntries", "4"));
|
||||
Assert.True(ComponentHasMetadata(root, "archivepkg", "record.hashedEntries", "3"));
|
||||
Assert.True(ComponentHasMetadata(root, "archivepkg", "record.missingFiles", "0"));
|
||||
Assert.True(ComponentHasMetadata(root, "archivepkg", "record.hashMismatches", "0"));
|
||||
Assert.True(ComponentHasMetadata(root, "archivepkg", "record.ioErrors", "0"));
|
||||
}
|
||||
finally
|
||||
{
|
||||
Directory.Delete(fixturePath, recursive: true);
|
||||
}
|
||||
|
||||
static void WriteEntry(ZipArchive archive, string entryName, byte[] content)
|
||||
{
|
||||
var entry = archive.CreateEntry(entryName);
|
||||
using var entryStream = entry.Open();
|
||||
entryStream.Write(content, 0, content.Length);
|
||||
}
|
||||
|
||||
static string ComputeSha256Base64(byte[] content)
|
||||
=> Convert.ToBase64String(SHA256.HashData(content));
|
||||
}
|
||||
|
||||
private static async Task CreatePythonPackageAsync(string root, string name, string version, CancellationToken cancellationToken)
|
||||
{
|
||||
var sitePackages = Path.Combine(root, "lib", "python3.11", "site-packages");
|
||||
|
||||
@@ -14,12 +14,10 @@
|
||||
<PackageReference Remove="xunit" />
|
||||
<PackageReference Remove="xunit.runner.visualstudio" />
|
||||
<PackageReference Remove="Microsoft.AspNetCore.Mvc.Testing" />
|
||||
<PackageReference Remove="Mongo2Go" />
|
||||
<PackageReference Remove="coverlet.collector" />
|
||||
<PackageReference Remove="Microsoft.Extensions.TimeProvider.Testing" />
|
||||
<ProjectReference Remove="..\StellaOps.Concelier.Testing\StellaOps.Concelier.Testing.csproj" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\StellaOps.Concelier.Tests.Shared\AssemblyInfo.cs" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\StellaOps.Concelier.Tests.Shared\MongoFixtureCollection.cs" />
|
||||
<!-- Exclude OpenSSL shim files - already provided by StellaOps.Scanner.Analyzers.Lang.Tests reference -->
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\..\..\..\tests\shared\OpenSslLegacyShim.cs" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\..\..\..\tests\shared\OpenSslAutoInit.cs" />
|
||||
|
||||
@@ -100,11 +100,12 @@ public sealed class PythonVirtualFileSystemTests
|
||||
.Build();
|
||||
|
||||
Assert.Equal(3, vfs.FileCount);
|
||||
Assert.True(vfs.FileExists("mypackage/__init__.py"));
|
||||
Assert.True(vfs.FileExists("mypackage/core.py"));
|
||||
Assert.True(vfs.FileExists("mypackage-1.0.0.dist-info/METADATA"));
|
||||
var wheelRoot = $"archives/wheel/{Path.GetFileName(wheelPath)}";
|
||||
Assert.True(vfs.FileExists($"{wheelRoot}/mypackage/__init__.py"));
|
||||
Assert.True(vfs.FileExists($"{wheelRoot}/mypackage/core.py"));
|
||||
Assert.True(vfs.FileExists($"{wheelRoot}/mypackage-1.0.0.dist-info/METADATA"));
|
||||
|
||||
Assert.True(vfs.TryGetFile("mypackage/__init__.py", out var file));
|
||||
Assert.True(vfs.TryGetFile($"{wheelRoot}/mypackage/__init__.py", out var file));
|
||||
Assert.Equal(PythonFileSource.Wheel, file!.Source);
|
||||
Assert.Equal(wheelPath, file.ArchivePath);
|
||||
}
|
||||
@@ -141,9 +142,10 @@ public sealed class PythonVirtualFileSystemTests
|
||||
.Build();
|
||||
|
||||
Assert.Equal(1, vfs.FileCount);
|
||||
Assert.True(vfs.FileExists("__main__.py"));
|
||||
var zipappRoot = $"archives/zipapp/{Path.GetFileName(zipappPath)}";
|
||||
Assert.True(vfs.FileExists($"{zipappRoot}/__main__.py"));
|
||||
|
||||
Assert.True(vfs.TryGetFile("__main__.py", out var file));
|
||||
Assert.True(vfs.TryGetFile($"{zipappRoot}/__main__.py", out var file));
|
||||
Assert.Equal(PythonFileSource.Zipapp, file!.Source);
|
||||
}
|
||||
finally
|
||||
@@ -252,7 +254,7 @@ public sealed class PythonVirtualFileSystemTests
|
||||
Assert.Single(sitePackagesFiles);
|
||||
Assert.Single(wheelFiles);
|
||||
Assert.Equal("installed/__init__.py", sitePackagesFiles[0].VirtualPath);
|
||||
Assert.Equal("wheel/__init__.py", wheelFiles[0].VirtualPath);
|
||||
Assert.Equal($"archives/wheel/{Path.GetFileName(wheelPath)}/wheel/__init__.py", wheelFiles[0].VirtualPath);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"ruby.observation.capability.schedulers": "0",
|
||||
"ruby.observation.capability.serialization": "false",
|
||||
"ruby.observation.dependency_edges": "6",
|
||||
"ruby.observation.entrypoints": "0",
|
||||
"ruby.observation.packages": "9",
|
||||
"ruby.observation.ruby_version": "3.2.0",
|
||||
"ruby.observation.runtime_edges": "0"
|
||||
|
||||
@@ -7,12 +7,13 @@
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"ruby.observation.bundler_version": "2.5.3",
|
||||
"ruby.observation.capability.exec": "false",
|
||||
"ruby.observation.capability.exec": "true",
|
||||
"ruby.observation.capability.net": "true",
|
||||
"ruby.observation.capability.scheduler_list": "clockwork;sidekiq",
|
||||
"ruby.observation.capability.schedulers": "2",
|
||||
"ruby.observation.capability.serialization": "false",
|
||||
"ruby.observation.dependency_edges": "4",
|
||||
"ruby.observation.entrypoints": "1",
|
||||
"ruby.observation.packages": "6",
|
||||
"ruby.observation.runtime_edges": "5"
|
||||
},
|
||||
@@ -21,8 +22,8 @@
|
||||
"kind": "derived",
|
||||
"source": "ruby.observation",
|
||||
"locator": "document",
|
||||
"value": "{\u0022$schema\u0022:\u0022stellaops.ruby.observation@1\u0022,\u0022packages\u0022:[{\u0022name\u0022:\u0022clockwork\u0022,\u0022version\u0022:\u00223.0.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022ops\u0022]},{\u0022name\u0022:\u0022pagy\u0022,\u0022version\u0022:\u00226.5.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022web\u0022]},{\u0022name\u0022:\u0022pry\u0022,\u0022version\u0022:\u00220.14.2\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022tools\u0022]},{\u0022name\u0022:\u0022rack\u0022,\u0022version\u0022:\u00223.1.2\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022sidekiq\u0022,\u0022version\u0022:\u00227.2.1\u0022,\u0022source\u0022:\u0022vendor\u0022,\u0022declaredOnly\u0022:false,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022artifact\u0022:\u0022vendor/custom-bundle/cache/sidekiq-7.2.1.gem\u0022,\u0022groups\u0022:[\u0022jobs\u0022]},{\u0022name\u0022:\u0022sinatra\u0022,\u0022version\u0022:\u00223.1.0\u0022,\u0022source\u0022:\u0022vendor-cache\u0022,\u0022declaredOnly\u0022:false,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022artifact\u0022:\u0022vendor/cache/sinatra-3.1.0.gem\u0022,\u0022groups\u0022:[\u0022web\u0022]}],\u0022entrypoints\u0022:[{\u0022path\u0022:\u0022config/environment.rb\u0022,\u0022type\u0022:\u0022script\u0022,\u0022requiredGems\u0022:[\u0022pagy\u0022]}],\u0022dependencyEdges\u0022:[{\u0022from\u0022:\u0022pkg:gem/pry@0.14.2\u0022,\u0022to\u0022:\u0022coderay\u0022,\u0022constraint\u0022:\u0022~\\u003E 1.1\u0022},{\u0022from\u0022:\u0022pkg:gem/pry@0.14.2\u0022,\u0022to\u0022:\u0022method_source\u0022,\u0022constraint\u0022:\u0022~\\u003E 1.0\u0022},{\u0022from\u0022:\u0022pkg:gem/sidekiq@7.2.1\u0022,\u0022to\u0022:\u0022rack\u0022,\u0022constraint\u0022:\u0022~\\u003E 2.0\u0022},{\u0022from\u0022:\u0022pkg:gem/sinatra@3.1.0\u0022,\u0022to\u0022:\u0022rack\u0022,\u0022constraint\u0022:\u0022~\\u003E 3.0\u0022}],\u0022runtimeEdges\u0022:[{\u0022package\u0022:\u0022clockwork\u0022,\u0022usedByEntrypoint\u0022:false,\u0022files\u0022:[\u0022scripts/worker.rb\u0022],\u0022entrypoints\u0022:[],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022pagy\u0022,\u0022usedByEntrypoint\u0022:true,\u0022files\u0022:[\u0022app/main.rb\u0022,\u0022config/environment.rb\u0022],\u0022entrypoints\u0022:[\u0022config/environment.rb\u0022],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022rack\u0022,\u0022usedByEntrypoint\u0022:false,\u0022files\u0022:[\u0022app/main.rb\u0022],\u0022entrypoints\u0022:[],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022sidekiq\u0022,\u0022usedByEntrypoint\u0022:false,\u0022files\u0022:[\u0022scripts/worker.rb\u0022],\u0022entrypoints\u0022:[],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022sinatra\u0022,\u0022usedByEntrypoint\u0022:false,\u0022files\u0022:[\u0022app/main.rb\u0022],\u0022entrypoints\u0022:[],\u0022reasons\u0022:[\u0022require-static\u0022]}],\u0022jobs\u0022:[{\u0022name\u0022:\u0022clockwork\u0022,\u0022type\u0022:\u0022scheduler\u0022,\u0022scheduler\u0022:\u0022clockwork\u0022},{\u0022name\u0022:\u0022sidekiq\u0022,\u0022type\u0022:\u0022scheduler\u0022,\u0022scheduler\u0022:\u0022sidekiq\u0022}],\u0022environment\u0022:{\u0022bundlerVersion\u0022:\u00222.5.3\u0022,\u0022bundlePaths\u0022:[\u0022/mnt/e/dev/git.stella-ops.org/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Ruby.Tests/bin/Debug/net10.0/Fixtures/lang/ruby/complex-app/vendor/custom-bundle\u0022],\u0022gemfiles\u0022:[\u0022/mnt/e/dev/git.stella-ops.org/src/Scanner/__Tests/StellaOps.Scanner.Analyzers.Lang.Ruby.Tests/bin/Debug/net10.0/Fixtures/lang/ruby/complex-app/Gemfile\u0022],\u0022lockfiles\u0022:[\u0022Gemfile.lock\u0022],\u0022frameworks\u0022:[\u0022clockwork\u0022,\u0022sidekiq\u0022]},\u0022capabilities\u0022:{\u0022usesExec\u0022:false,\u0022usesNetwork\u0022:true,\u0022usesSerialization\u0022:false,\u0022jobSchedulers\u0022:[\u0022clockwork\u0022,\u0022sidekiq\u0022]},\u0022bundledWith\u0022:\u00222.5.3\u0022}",
|
||||
"sha256": "sha256:bd15160e034ea5adf0a8384dc9ee18557f695b0952d4fb17214f1bd1381ad22a"
|
||||
"value": "{\u0022$schema\u0022:\u0022stellaops.ruby.observation@1\u0022,\u0022packages\u0022:[{\u0022name\u0022:\u0022clockwork\u0022,\u0022version\u0022:\u00223.0.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022ops\u0022]},{\u0022name\u0022:\u0022pagy\u0022,\u0022version\u0022:\u00226.5.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022web\u0022]},{\u0022name\u0022:\u0022pry\u0022,\u0022version\u0022:\u00220.14.2\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022tools\u0022]},{\u0022name\u0022:\u0022rack\u0022,\u0022version\u0022:\u00223.1.2\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022sidekiq\u0022,\u0022version\u0022:\u00227.2.1\u0022,\u0022source\u0022:\u0022vendor\u0022,\u0022declaredOnly\u0022:false,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022artifact\u0022:\u0022vendor/custom-bundle/cache/sidekiq-7.2.1.gem\u0022,\u0022groups\u0022:[\u0022jobs\u0022]},{\u0022name\u0022:\u0022sinatra\u0022,\u0022version\u0022:\u00223.1.0\u0022,\u0022source\u0022:\u0022vendor-cache\u0022,\u0022declaredOnly\u0022:false,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022artifact\u0022:\u0022vendor/cache/sinatra-3.1.0.gem\u0022,\u0022groups\u0022:[\u0022web\u0022]}],\u0022entrypoints\u0022:[{\u0022path\u0022:\u0022config/environment.rb\u0022,\u0022type\u0022:\u0022script\u0022,\u0022requiredGems\u0022:[\u0022pagy\u0022]}],\u0022dependencyEdges\u0022:[{\u0022from\u0022:\u0022pkg:gem/pry@0.14.2\u0022,\u0022to\u0022:\u0022coderay\u0022,\u0022constraint\u0022:\u0022~\\u003E 1.1\u0022},{\u0022from\u0022:\u0022pkg:gem/pry@0.14.2\u0022,\u0022to\u0022:\u0022method_source\u0022,\u0022constraint\u0022:\u0022~\\u003E 1.0\u0022},{\u0022from\u0022:\u0022pkg:gem/sidekiq@7.2.1\u0022,\u0022to\u0022:\u0022rack\u0022,\u0022constraint\u0022:\u0022~\\u003E 2.0\u0022},{\u0022from\u0022:\u0022pkg:gem/sinatra@3.1.0\u0022,\u0022to\u0022:\u0022rack\u0022,\u0022constraint\u0022:\u0022~\\u003E 3.0\u0022}],\u0022runtimeEdges\u0022:[{\u0022package\u0022:\u0022clockwork\u0022,\u0022usedByEntrypoint\u0022:false,\u0022files\u0022:[\u0022scripts/worker.rb\u0022],\u0022entrypoints\u0022:[],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022pagy\u0022,\u0022usedByEntrypoint\u0022:true,\u0022files\u0022:[\u0022app/main.rb\u0022,\u0022config/environment.rb\u0022],\u0022entrypoints\u0022:[\u0022config/environment.rb\u0022],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022rack\u0022,\u0022usedByEntrypoint\u0022:false,\u0022files\u0022:[\u0022app/main.rb\u0022],\u0022entrypoints\u0022:[],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022sidekiq\u0022,\u0022usedByEntrypoint\u0022:false,\u0022files\u0022:[\u0022scripts/worker.rb\u0022],\u0022entrypoints\u0022:[],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022sinatra\u0022,\u0022usedByEntrypoint\u0022:false,\u0022files\u0022:[\u0022app/main.rb\u0022],\u0022entrypoints\u0022:[],\u0022reasons\u0022:[\u0022require-static\u0022]}],\u0022jobs\u0022:[{\u0022name\u0022:\u0022clockwork\u0022,\u0022type\u0022:\u0022scheduler\u0022,\u0022scheduler\u0022:\u0022clockwork\u0022},{\u0022name\u0022:\u0022sidekiq\u0022,\u0022type\u0022:\u0022scheduler\u0022,\u0022scheduler\u0022:\u0022sidekiq\u0022}],\u0022environment\u0022:{\u0022bundlerVersion\u0022:\u00222.5.3\u0022,\u0022bundlePaths\u0022:[\u0022vendor/custom-bundle\u0022],\u0022gemfiles\u0022:[\u0022Gemfile\u0022],\u0022lockfiles\u0022:[\u0022Gemfile.lock\u0022],\u0022frameworks\u0022:[\u0022clockwork\u0022,\u0022sidekiq\u0022]},\u0022capabilities\u0022:{\u0022usesExec\u0022:true,\u0022usesNetwork\u0022:true,\u0022usesSerialization\u0022:false,\u0022jobSchedulers\u0022:[\u0022clockwork\u0022,\u0022sidekiq\u0022]},\u0022bundledWith\u0022:\u00222.5.3\u0022}",
|
||||
"sha256": "sha256:fd8d3da9563e77103a04ec6020d8ec87dd7d9fab2160a31e289035787895f15e"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -35,6 +36,7 @@
|
||||
"type": "gem",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"capability.exec": "true",
|
||||
"capability.net": "true",
|
||||
"capability.scheduler": "clockwork;sidekiq",
|
||||
"capability.scheduler.clockwork": "true",
|
||||
@@ -64,6 +66,7 @@
|
||||
"type": "gem",
|
||||
"usedByEntrypoint": true,
|
||||
"metadata": {
|
||||
"capability.exec": "true",
|
||||
"capability.net": "true",
|
||||
"capability.scheduler": "clockwork;sidekiq",
|
||||
"capability.scheduler.clockwork": "true",
|
||||
@@ -94,6 +97,7 @@
|
||||
"type": "gem",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"capability.exec": "true",
|
||||
"capability.net": "true",
|
||||
"capability.scheduler": "clockwork;sidekiq",
|
||||
"capability.scheduler.clockwork": "true",
|
||||
@@ -120,6 +124,7 @@
|
||||
"type": "gem",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"capability.exec": "true",
|
||||
"capability.net": "true",
|
||||
"capability.scheduler": "clockwork;sidekiq",
|
||||
"capability.scheduler.clockwork": "true",
|
||||
@@ -150,6 +155,7 @@
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"artifact": "vendor/custom-bundle/cache/sidekiq-7.2.1.gem",
|
||||
"capability.exec": "true",
|
||||
"capability.net": "true",
|
||||
"capability.scheduler": "clockwork;sidekiq",
|
||||
"capability.scheduler.clockwork": "true",
|
||||
@@ -180,6 +186,7 @@
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"artifact": "vendor/cache/sinatra-3.1.0.gem",
|
||||
"capability.exec": "true",
|
||||
"capability.net": "true",
|
||||
"capability.scheduler": "clockwork;sidekiq",
|
||||
"capability.scheduler.clockwork": "true",
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
"ruby.observation.capability.schedulers": "0",
|
||||
"ruby.observation.capability.serialization": "false",
|
||||
"ruby.observation.dependency_edges": "3",
|
||||
"ruby.observation.entrypoints": "2",
|
||||
"ruby.observation.native_extensions": "2",
|
||||
"ruby.observation.packages": "7",
|
||||
"ruby.observation.ruby_version": "3.2.0",
|
||||
"ruby.observation.runtime_edges": "3",
|
||||
@@ -23,8 +25,8 @@
|
||||
"kind": "derived",
|
||||
"source": "ruby.observation",
|
||||
"locator": "document",
|
||||
"value": "{\u0022$schema\u0022:\u0022stellaops.ruby.observation@1\u0022,\u0022packages\u0022:[{\u0022name\u0022:\u0022mini_portile2\u0022,\u0022version\u0022:\u00222.8.4\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022nio4r\u0022,\u0022version\u0022:\u00222.5.9\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022nokogiri\u0022,\u0022version\u0022:\u00221.15.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022pg\u0022,\u0022version\u0022:\u00221.5.4\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022puma\u0022,\u0022version\u0022:\u00226.4.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022racc\u0022,\u0022version\u0022:\u00221.7.1\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022rack\u0022,\u0022version\u0022:\u00223.0.8\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]}],\u0022entrypoints\u0022:[{\u0022path\u0022:\u0022app.rb\u0022,\u0022type\u0022:\u0022script\u0022,\u0022requiredGems\u0022:[\u0022nokogiri\u0022,\u0022pg\u0022,\u0022rack\u0022]},{\u0022path\u0022:\u0022config.ru\u0022,\u0022type\u0022:\u0022rack\u0022,\u0022requiredGems\u0022:[\u0022rack\u0022]}],\u0022dependencyEdges\u0022:[{\u0022from\u0022:\u0022pkg:gem/nokogiri@1.15.0\u0022,\u0022to\u0022:\u0022mini_portile2\u0022,\u0022constraint\u0022:\u0022~\\u003E 2.8.2\u0022},{\u0022from\u0022:\u0022pkg:gem/nokogiri@1.15.0\u0022,\u0022to\u0022:\u0022racc\u0022,\u0022constraint\u0022:\u0022~\\u003E 1.4\u0022},{\u0022from\u0022:\u0022pkg:gem/puma@6.4.0\u0022,\u0022to\u0022:\u0022nio4r\u0022,\u0022constraint\u0022:\u0022~\\u003E 2.0\u0022}],\u0022runtimeEdges\u0022:[{\u0022package\u0022:\u0022nokogiri\u0022,\u0022usedByEntrypoint\u0022:true,\u0022files\u0022:[\u0022app.rb\u0022],\u0022entrypoints\u0022:[\u0022app.rb\u0022],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022pg\u0022,\u0022usedByEntrypoint\u0022:true,\u0022files\u0022:[\u0022app.rb\u0022],\u0022entrypoints\u0022:[\u0022app.rb\u0022],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022rack\u0022,\u0022usedByEntrypoint\u0022:true,\u0022files\u0022:[\u0022app.rb\u0022,\u0022config.ru\u0022],\u0022entrypoints\u0022:[\u0022app.rb\u0022,\u0022config.ru\u0022],\u0022reasons\u0022:[\u0022require-static\u0022]}],\u0022configs\u0022:[{\u0022name\u0022:\u0022puma\u0022,\u0022type\u0022:\u0022web-server\u0022,\u0022filePath\u0022:\u0022config/puma.rb\u0022,\u0022settings\u0022:{\u0022preload_app\u0022:\u0022true\u0022}}],\u0022environment\u0022:{\u0022rubyVersion\u0022:\u00223.2.0\u0022,\u0022bundlerVersion\u0022:\u00222.4.22\u0022,\u0022lockfiles\u0022:[\u0022Gemfile.lock\u0022],\u0022rubyVersionSources\u0022:[{\u0022version\u0022:\u00223.2.0\u0022,\u0022source\u0022:\u0022.ruby-version\u0022,\u0022sourceType\u0022:\u0022ruby-version\u0022},{\u0022version\u0022:\u00223.2.0\u0022,\u0022source\u0022:\u0022.tool-versions\u0022,\u0022sourceType\u0022:\u0022tool-versions\u0022},{\u0022version\u0022:\u00223.2.0\u0022,\u0022source\u0022:\u0022Gemfile\u0022,\u0022sourceType\u0022:\u0022gemfile\u0022}],\u0022webServers\u0022:[{\u0022serverType\u0022:\u0022puma\u0022,\u0022configPath\u0022:\u0022config/puma.rb\u0022,\u0022settings\u0022:{\u0022preload_app\u0022:\u0022true\u0022}}]},\u0022capabilities\u0022:{\u0022usesExec\u0022:false,\u0022usesNetwork\u0022:false,\u0022usesSerialization\u0022:false,\u0022jobSchedulers\u0022:[]},\u0022bundledWith\u0022:\u00222.4.22\u0022}",
|
||||
"sha256": "sha256:d5c7da885e1d05805981e2080c9023cd653ed464e993d5e48de6b9f55334eca7"
|
||||
"value": "{\u0022$schema\u0022:\u0022stellaops.ruby.observation@1\u0022,\u0022packages\u0022:[{\u0022name\u0022:\u0022mini_portile2\u0022,\u0022version\u0022:\u00222.8.4\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022nio4r\u0022,\u0022version\u0022:\u00222.5.9\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022nokogiri\u0022,\u0022version\u0022:\u00221.15.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022pg\u0022,\u0022version\u0022:\u00221.5.4\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022puma\u0022,\u0022version\u0022:\u00226.4.0\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022racc\u0022,\u0022version\u0022:\u00221.7.1\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]},{\u0022name\u0022:\u0022rack\u0022,\u0022version\u0022:\u00223.0.8\u0022,\u0022source\u0022:\u0022https://rubygems.org/\u0022,\u0022declaredOnly\u0022:true,\u0022lockfile\u0022:\u0022Gemfile.lock\u0022,\u0022groups\u0022:[\u0022default\u0022]}],\u0022entrypoints\u0022:[{\u0022path\u0022:\u0022app.rb\u0022,\u0022type\u0022:\u0022script\u0022,\u0022requiredGems\u0022:[\u0022nokogiri\u0022,\u0022pg\u0022,\u0022rack\u0022]},{\u0022path\u0022:\u0022config.ru\u0022,\u0022type\u0022:\u0022rack\u0022,\u0022requiredGems\u0022:[\u0022rack\u0022]}],\u0022dependencyEdges\u0022:[{\u0022from\u0022:\u0022pkg:gem/nokogiri@1.15.0\u0022,\u0022to\u0022:\u0022mini_portile2\u0022,\u0022constraint\u0022:\u0022~\\u003E 2.8.2\u0022},{\u0022from\u0022:\u0022pkg:gem/nokogiri@1.15.0\u0022,\u0022to\u0022:\u0022racc\u0022,\u0022constraint\u0022:\u0022~\\u003E 1.4\u0022},{\u0022from\u0022:\u0022pkg:gem/puma@6.4.0\u0022,\u0022to\u0022:\u0022nio4r\u0022,\u0022constraint\u0022:\u0022~\\u003E 2.0\u0022}],\u0022runtimeEdges\u0022:[{\u0022package\u0022:\u0022nokogiri\u0022,\u0022usedByEntrypoint\u0022:true,\u0022files\u0022:[\u0022app.rb\u0022],\u0022entrypoints\u0022:[\u0022app.rb\u0022],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022pg\u0022,\u0022usedByEntrypoint\u0022:true,\u0022files\u0022:[\u0022app.rb\u0022],\u0022entrypoints\u0022:[\u0022app.rb\u0022],\u0022reasons\u0022:[\u0022require-static\u0022]},{\u0022package\u0022:\u0022rack\u0022,\u0022usedByEntrypoint\u0022:true,\u0022files\u0022:[\u0022app.rb\u0022,\u0022config.ru\u0022],\u0022entrypoints\u0022:[\u0022app.rb\u0022,\u0022config.ru\u0022],\u0022reasons\u0022:[\u0022require-static\u0022]}],\u0022configs\u0022:[{\u0022name\u0022:\u0022puma\u0022,\u0022type\u0022:\u0022web-server\u0022,\u0022filePath\u0022:\u0022config/puma.rb\u0022,\u0022settings\u0022:{\u0022preload_app\u0022:\u0022true\u0022}}],\u0022environment\u0022:{\u0022rubyVersion\u0022:\u00223.2.0\u0022,\u0022bundlerVersion\u0022:\u00222.4.22\u0022,\u0022lockfiles\u0022:[\u0022Gemfile.lock\u0022],\u0022rubyVersionSources\u0022:[{\u0022version\u0022:\u00223.2.0\u0022,\u0022source\u0022:\u0022.ruby-version\u0022,\u0022sourceType\u0022:\u0022ruby-version\u0022},{\u0022version\u0022:\u00223.2.0\u0022,\u0022source\u0022:\u0022.tool-versions\u0022,\u0022sourceType\u0022:\u0022tool-versions\u0022},{\u0022version\u0022:\u00223.2.0\u0022,\u0022source\u0022:\u0022Gemfile\u0022,\u0022sourceType\u0022:\u0022gemfile\u0022}],\u0022webServers\u0022:[{\u0022serverType\u0022:\u0022puma\u0022,\u0022configPath\u0022:\u0022config/puma.rb\u0022,\u0022settings\u0022:{\u0022preload_app\u0022:\u0022true\u0022}}],\u0022nativeExtensions\u0022:[{\u0022gemName\u0022:\u0022nokogiri\u0022,\u0022gemVersion\u0022:\u00221.15.0\u0022,\u0022extensionPath\u0022:\u0022layers/ruby/usr/local/lib/ruby/gems/3.2.0/gems/nokogiri-1.15.0/lib/nokogiri/nokogiri.so\u0022,\u0022extensionType\u0022:\u0022so\u0022},{\u0022gemName\u0022:\u0022pg\u0022,\u0022gemVersion\u0022:\u00221.5.4\u0022,\u0022extensionPath\u0022:\u0022layers/ruby/usr/local/lib/ruby/gems/3.2.0/gems/pg-1.5.4/lib/pg_ext.so\u0022,\u0022extensionType\u0022:\u0022so\u0022}]},\u0022capabilities\u0022:{\u0022usesExec\u0022:false,\u0022usesNetwork\u0022:false,\u0022usesSerialization\u0022:false,\u0022jobSchedulers\u0022:[]},\u0022bundledWith\u0022:\u00222.4.22\u0022}",
|
||||
"sha256": "sha256:59ac6bb07675933964aae184f8f581dfd33a334126e96f16fd0b1943374897c2"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -1 +1,28 @@
|
||||
[]
|
||||
[
|
||||
{
|
||||
"analyzerId": "ruby",
|
||||
"componentKey": "observation::ruby",
|
||||
"name": "Ruby Observation Summary",
|
||||
"type": "ruby-observation",
|
||||
"usedByEntrypoint": false,
|
||||
"metadata": {
|
||||
"ruby.observation.capability.exec": "true",
|
||||
"ruby.observation.capability.net": "true",
|
||||
"ruby.observation.capability.schedulers": "0",
|
||||
"ruby.observation.capability.serialization": "false",
|
||||
"ruby.observation.dependency_edges": "0",
|
||||
"ruby.observation.entrypoints": "1",
|
||||
"ruby.observation.packages": "0",
|
||||
"ruby.observation.runtime_edges": "0"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "derived",
|
||||
"source": "ruby.observation",
|
||||
"locator": "document",
|
||||
"value": "{\u0022$schema\u0022:\u0022stellaops.ruby.observation@1\u0022,\u0022packages\u0022:[],\u0022entrypoints\u0022:[{\u0022path\u0022:\u0022app.rb\u0022,\u0022type\u0022:\u0022script\u0022}],\u0022dependencyEdges\u0022:[],\u0022runtimeEdges\u0022:[],\u0022environment\u0022:{},\u0022capabilities\u0022:{\u0022usesExec\u0022:true,\u0022usesNetwork\u0022:true,\u0022usesSerialization\u0022:false,\u0022jobSchedulers\u0022:[]}}",
|
||||
"sha256": "sha256:60173f2b841ca2b231eb293dd6ccc9d7ed39ea77a0e86ed887111f84861092ed"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -12,6 +12,7 @@
|
||||
"ruby.observation.capability.schedulers": "0",
|
||||
"ruby.observation.capability.serialization": "false",
|
||||
"ruby.observation.dependency_edges": "13",
|
||||
"ruby.observation.entrypoints": "3",
|
||||
"ruby.observation.packages": "18",
|
||||
"ruby.observation.ruby_version": "3.2.0",
|
||||
"ruby.observation.runtime_edges": "3"
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"ruby.observation.capability.schedulers": "1",
|
||||
"ruby.observation.capability.serialization": "true",
|
||||
"ruby.observation.dependency_edges": "4",
|
||||
"ruby.observation.entrypoints": "4",
|
||||
"ruby.observation.packages": "11",
|
||||
"ruby.observation.ruby_version": "3.1.2",
|
||||
"ruby.observation.runtime_edges": "3"
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"ruby.observation.capability.schedulers": "0",
|
||||
"ruby.observation.capability.serialization": "false",
|
||||
"ruby.observation.dependency_edges": "12",
|
||||
"ruby.observation.entrypoints": "2",
|
||||
"ruby.observation.packages": "11",
|
||||
"ruby.observation.runtime_edges": "2"
|
||||
},
|
||||
|
||||
@@ -14,12 +14,10 @@
|
||||
<PackageReference Remove="xunit" />
|
||||
<PackageReference Remove="xunit.runner.visualstudio" />
|
||||
<PackageReference Remove="Microsoft.AspNetCore.Mvc.Testing" />
|
||||
<PackageReference Remove="Mongo2Go" />
|
||||
<PackageReference Remove="coverlet.collector" />
|
||||
<PackageReference Remove="Microsoft.Extensions.TimeProvider.Testing" />
|
||||
<ProjectReference Remove="..\StellaOps.Concelier.Testing\StellaOps.Concelier.Testing.csproj" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\StellaOps.Concelier.Tests.Shared\AssemblyInfo.cs" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\StellaOps.Concelier.Tests.Shared\MongoFixtureCollection.cs" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\..\..\..\tests\shared\OpenSslLegacyShim.cs" />
|
||||
<Compile Remove="$(MSBuildThisFileDirectory)..\..\..\..\tests\shared\OpenSslAutoInit.cs" />
|
||||
<Using Remove="StellaOps.Concelier.Testing" />
|
||||
|
||||
@@ -138,15 +138,17 @@
|
||||
"metadata": {
|
||||
"deno.container.identifier": "vendor-<hash>",
|
||||
"deno.container.kind": "vendor",
|
||||
"deno.container.layerDigest": "deadbeef",
|
||||
"deno.container.meta.alias": "vendor-<hash>",
|
||||
"deno.container.meta.path": "<workspace>/vendor"
|
||||
"deno.container.meta.path": "<workspace>/layers/sha256-deadbeef/fs/vendor"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "deno.container",
|
||||
"locator": "Vendor",
|
||||
"value": "vendor-<hash>"
|
||||
"value": "vendor-<hash>",
|
||||
"sha256": "deadbeef"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -159,17 +161,15 @@
|
||||
"metadata": {
|
||||
"deno.container.identifier": "vendor-<hash>",
|
||||
"deno.container.kind": "vendor",
|
||||
"deno.container.layerDigest": "deadbeef",
|
||||
"deno.container.meta.alias": "vendor-<hash>",
|
||||
"deno.container.meta.path": "<workspace>/layers/sha256-deadbeef/fs/vendor"
|
||||
"deno.container.meta.path": "<workspace>/vendor"
|
||||
},
|
||||
"evidence": [
|
||||
{
|
||||
"kind": "metadata",
|
||||
"source": "deno.container",
|
||||
"locator": "Vendor",
|
||||
"value": "vendor-<hash>",
|
||||
"sha256": "deadbeef"
|
||||
"value": "vendor-<hash>"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user