@@ -12,12 +12,7 @@ import * as types from "./types";
1212import { truncateAdditionalFacts } from "./utils" ;
1313import { PLUGIN_VERSION } from "./version" ;
1414
15- export {
16- buildResponse ,
17- annotateWithLayerIds ,
18- expandDockerfilePackages ,
19- excludeBaseImageDeps ,
20- } ;
15+ export { buildResponse } ;
2116
2217async function buildResponse (
2318 depsAnalysis : StaticAnalysis & {
@@ -32,24 +27,30 @@ async function buildResponse(
3227) : Promise < types . PluginResponse > {
3328 const deps = depsAnalysis . depTree . dependencies ;
3429
35- const inputDockerfilePkgs =
36- dockerfileAnalysis ?. dockerfilePackages ??
37- depsAnalysis . autoDetectedUserInstructions ?. dockerfilePackages ;
38-
39- if ( inputDockerfilePkgs ) {
40- const expandedDockerfilePkgs = expandDockerfilePackages (
41- inputDockerfilePkgs ,
30+ // Expand dockerfile packages and auto detected user instructions if
31+ // they are provided. These objects are mutated in place, ensuring the
32+ // expanded packages are used in the subsequent steps and fact building.
33+ if ( dockerfileAnalysis ?. dockerfilePackages ) {
34+ getUserInstructionDeps ( dockerfileAnalysis . dockerfilePackages , deps ) ;
35+ }
36+ if ( depsAnalysis . autoDetectedUserInstructions ?. dockerfilePackages ) {
37+ getUserInstructionDeps (
38+ depsAnalysis . autoDetectedUserInstructions . dockerfilePackages ,
4239 deps ,
4340 ) ;
41+ }
42+
43+ const dockerfilePkgs =
44+ dockerfileAnalysis ?. dockerfilePackages ??
45+ depsAnalysis . autoDetectedUserInstructions ?. dockerfilePackages ;
4446
47+ if ( dockerfilePkgs ) {
4548 const finalDeps = excludeBaseImageDeps (
4649 deps ,
47- expandedDockerfilePkgs ,
50+ dockerfilePkgs ,
4851 excludeBaseImageVulns ,
4952 ) ;
50- annotateWithLayerIds ( finalDeps , expandedDockerfilePkgs ) ;
51-
52- // Assign the final dependencies to the dependency tree.
53+ annotateLayerIds ( finalDeps , dockerfilePkgs ) ;
5354 depsAnalysis . depTree . dependencies = finalDeps ;
5455 }
5556
@@ -71,9 +72,6 @@ async function buildResponse(
7172 }
7273
7374 if ( dockerfileAnalysis !== undefined ) {
74- // Use legacy expansion function to maintain downstream compatibility.
75- getUserInstructionDeps ( dockerfileAnalysis . dockerfilePackages , deps ) ;
76-
7775 const dockerfileAnalysisFact : facts . DockerfileAnalysisFact = {
7876 type : "dockerfileAnalysis" ,
7977 data : dockerfileAnalysis ,
@@ -211,17 +209,12 @@ async function buildResponse(
211209 autoDetectedLayers &&
212210 Object . keys ( autoDetectedLayers ) . length > 0
213211 ) {
214- const autoDetectedPackagesWithChildren = getUserInstructionDeps (
215- autoDetectedPackages ,
216- deps ,
217- ) ;
218-
219212 const autoDetectedUserInstructionsFact : facts . AutoDetectedUserInstructionsFact =
220213 {
221214 type : "autoDetectedUserInstructions" ,
222215 data : {
223216 dockerfileLayers : autoDetectedLayers ,
224- dockerfilePackages : autoDetectedPackagesWithChildren ! ,
217+ dockerfilePackages : autoDetectedPackages ,
225218 } ,
226219 } ;
227220 additionalFacts . push ( autoDetectedUserInstructionsFact ) ;
@@ -354,7 +347,6 @@ async function buildResponse(
354347}
355348
356349/**
357- * @deprecated This function is deprecated and will be removed in a future version.
358350 * Expands the provided dockerfile packages to include transitive dependencies.
359351 * Transitive dependencies are keyed by their source segments.
360352 *
@@ -383,7 +375,6 @@ function getUserInstructionDeps(
383375
384376 if ( dockerfilePackage ) {
385377 for ( const dep of collectDeps ( dependencies [ dependencyName ] ) ) {
386- // Transitive dependencies are keyed by their source segments.
387378 dockerfilePackages [ dep . split ( "/" ) [ 0 ] ] = { ...dockerfilePackage } ;
388379 }
389380 }
@@ -404,59 +395,6 @@ function collectDeps(pkg) {
404395 : [ ] ;
405396}
406397
407- /**
408- * Returns the package source name from a full dependency name.
409- *
410- * A package source refers to the top-level package name, such as "foo" in "foo/foo-dev".
411- *
412- * @param depName - The full dependency name.
413- * @returns The package source name.
414- */
415- function packageSource ( depName : string ) : string {
416- return depName . split ( "/" ) [ 0 ] ;
417- }
418-
419- /**
420- * Expands the list of packages explicitly requested in the Dockerfile to include all transitive dependencies.
421- * The returned package map is keyed by the full dependency names.
422- *
423- * @param dockerfilePackages - The packages explicitly requested in a Dockerfile.
424- * @param deps - The dependencies of the image.
425- * @returns A map of packages attributed to the Dockerfile.
426- */
427- function expandDockerfilePackages (
428- dockerfilePackages : DockerFilePackages ,
429- deps : { [ depName : string ] : types . DepTreeDep } ,
430- ) : DockerFilePackages {
431- const expandedPkgs = { } ;
432-
433- function collectChildPackages ( node : types . DepTreeDep , parentEntry : any ) {
434- if ( ! node . dependencies ) {
435- return ;
436- }
437- for ( const childKey of Object . keys ( node . dependencies ) ) {
438- if ( ! expandedPkgs [ childKey ] ) {
439- expandedPkgs [ childKey ] = parentEntry ;
440- collectChildPackages ( node . dependencies [ childKey ] , parentEntry ) ;
441- }
442- }
443- }
444-
445- for ( const rootKey of Object . keys ( deps ) ) {
446- const source = packageSource ( rootKey ) ;
447- const dockerfileEntry =
448- dockerfilePackages [ rootKey ] || dockerfilePackages [ source ] ;
449- if ( dockerfileEntry ) {
450- // All keys in the expanded packages are the full dependency names.
451- expandedPkgs [ rootKey ] = dockerfileEntry ;
452-
453- collectChildPackages ( deps [ rootKey ] , dockerfileEntry ) ;
454- }
455- }
456-
457- return expandedPkgs ;
458- }
459-
460398/**
461399 * Excludes base image dependencies from the dependency tree if excludeBaseImageVulns is true.
462400 *
@@ -477,50 +415,51 @@ function excludeBaseImageDeps(
477415 }
478416
479417 return Object . keys ( deps )
480- . filter ( ( depName ) => dockerfilePkgs [ depName ] )
418+ . filter ( ( depName ) => {
419+ if ( dockerfilePkgs [ depName ] !== undefined ) {
420+ return true ;
421+ }
422+ const source = depName . split ( "/" ) [ 0 ] ;
423+ return dockerfilePkgs [ source ] !== undefined ;
424+ } )
481425 . reduce ( ( extractedDeps , depName ) => {
482426 extractedDeps [ depName ] = deps [ depName ] ;
483427 return extractedDeps ;
484428 } , { } ) ;
485429}
486430
487431/**
488- * Annotates the dependency tree with layer IDs.
489- *
432+ * Annotates the dependencies with the layer ID of the Dockerfile
433+ * instruction that installed them.
434+ *
490435 * @important
491436 * mutates the provided `deps` object.
492- *
437+
493438 * @param deps - The dependencies of the image.
494439 * @param dockerfilePkgs - The expanded packages attributed to the Dockerfile.
495440 */
496- function annotateWithLayerIds (
497- deps : { [ depName : string ] : types . DepTreeDep } ,
441+ function annotateLayerIds (
442+ deps : {
443+ [ depName : string ] : types . DepTreeDep ;
444+ } ,
498445 dockerfilePkgs : DockerFilePackages | undefined ,
499- ) : void {
446+ ) {
500447 if ( ! dockerfilePkgs ) {
501448 return ;
502449 }
503450
504- function annotateRecursive ( currentDeps : {
505- [ depName : string ] : types . DepTreeDep ;
506- } ) {
507- for ( const depKey of Object . keys ( currentDeps ) ) {
508- const node = currentDeps [ depKey ] ;
509- const dockerfileEntry = dockerfilePkgs ! [ depKey ] ;
510-
511- if ( dockerfileEntry ) {
512- node . labels = {
513- ...( node . labels || { } ) ,
514- dockerLayerId : instructionDigest ( dockerfileEntry . instruction ) ,
515- } ;
516-
517- // Only progress down the dependency tree if the current node is a dockerfile package.
518- if ( node . dependencies ) {
519- annotateRecursive ( node . dependencies ) ;
520- }
521- }
451+ for ( const dep of Object . keys ( deps ) ) {
452+ const pkg = deps [ dep ] ;
453+ const pkgSource = dep . split ( "/" ) [ 0 ] ;
454+ const dockerfilePkg = dockerfilePkgs [ dep ] || dockerfilePkgs [ pkgSource ] ;
455+ if ( dockerfilePkg ) {
456+ pkg . labels = {
457+ ...( pkg . labels || { } ) ,
458+ dockerLayerId : instructionDigest ( dockerfilePkg . instruction ) ,
459+ } ;
460+ }
461+ if ( pkg . dependencies ) {
462+ annotateLayerIds ( pkg . dependencies , dockerfilePkgs ) ;
522463 }
523464 }
524-
525- annotateRecursive ( deps ) ;
526465}
0 commit comments