@@ -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
@@ -78,9 +79,6 @@ async function buildResponse(
7879 }
7980
8081 if ( dockerfileAnalysis !== undefined ) {
81- // Use legacy expansion function to maintain downstream compatibility.
82- getUserInstructionDeps ( dockerfileAnalysis . dockerfilePackages , deps ) ;
83-
8482 const dockerfileAnalysisFact : facts . DockerfileAnalysisFact = {
8583 type : "dockerfileAnalysis" ,
8684 data : dockerfileAnalysis ,
@@ -218,17 +216,12 @@ async function buildResponse(
218216 autoDetectedLayers &&
219217 Object . keys ( autoDetectedLayers ) . length > 0
220218 ) {
221- const autoDetectedPackagesWithChildren = getUserInstructionDeps (
222- autoDetectedPackages ,
223- deps ,
224- ) ;
225-
226219 const autoDetectedUserInstructionsFact : facts . AutoDetectedUserInstructionsFact =
227220 {
228221 type : "autoDetectedUserInstructions" ,
229222 data : {
230223 dockerfileLayers : autoDetectedLayers ,
231- dockerfilePackages : autoDetectedPackagesWithChildren ! ,
224+ dockerfilePackages : autoDetectedPackages ,
232225 } ,
233226 } ;
234227 additionalFacts . push ( autoDetectedUserInstructionsFact ) ;
@@ -361,7 +354,6 @@ async function buildResponse(
361354}
362355
363356/**
364- * @deprecated This function is deprecated and will be removed in a future version.
365357 * Expands the provided dockerfile packages to include transitive dependencies.
366358 * Transitive dependencies are keyed by their source segments.
367359 *
@@ -390,7 +382,6 @@ function getUserInstructionDeps(
390382
391383 if ( dockerfilePackage ) {
392384 for ( const dep of collectDeps ( dependencies [ dependencyName ] ) ) {
393- // Transitive dependencies are keyed by their source segments.
394385 dockerfilePackages [ dep . split ( "/" ) [ 0 ] ] = { ...dockerfilePackage } ;
395386 }
396387 }
@@ -411,59 +402,6 @@ function collectDeps(pkg) {
411402 : [ ] ;
412403}
413404
414- /**
415- * Returns the package source name from a full dependency name.
416- *
417- * A package source refers to the top-level package name, such as "foo" in "foo/foo-dev".
418- *
419- * @param depName - The full dependency name.
420- * @returns The package source name.
421- */
422- function packageSource ( depName : string ) : string {
423- return depName . split ( "/" ) [ 0 ] ;
424- }
425-
426- /**
427- * Expands the list of packages explicitly requested in the Dockerfile to include all transitive dependencies.
428- * The returned package map is keyed by the full dependency names.
429- *
430- * @param dockerfilePackages - The packages explicitly requested in a Dockerfile.
431- * @param deps - The dependencies of the image.
432- * @returns A map of packages attributed to the Dockerfile.
433- */
434- function expandDockerfilePackages (
435- dockerfilePackages : DockerFilePackages ,
436- deps : { [ depName : string ] : types . DepTreeDep } ,
437- ) : DockerFilePackages {
438- const expandedPkgs = { } ;
439-
440- function collectChildPackages ( node : types . DepTreeDep , parentEntry : any ) {
441- if ( ! node . dependencies ) {
442- return ;
443- }
444- for ( const childKey of Object . keys ( node . dependencies ) ) {
445- if ( ! expandedPkgs [ childKey ] ) {
446- expandedPkgs [ childKey ] = parentEntry ;
447- collectChildPackages ( node . dependencies [ childKey ] , parentEntry ) ;
448- }
449- }
450- }
451-
452- for ( const rootKey of Object . keys ( deps ) ) {
453- const source = packageSource ( rootKey ) ;
454- const dockerfileEntry =
455- dockerfilePackages [ rootKey ] || dockerfilePackages [ source ] ;
456- if ( dockerfileEntry ) {
457- // All keys in the expanded packages are the full dependency names.
458- expandedPkgs [ rootKey ] = dockerfileEntry ;
459-
460- collectChildPackages ( deps [ rootKey ] , dockerfileEntry ) ;
461- }
462- }
463-
464- return expandedPkgs ;
465- }
466-
467405/**
468406 * Excludes base image dependencies from the dependency tree if excludeBaseImageVulns is true.
469407 *
@@ -484,50 +422,51 @@ function excludeBaseImageDeps(
484422 }
485423
486424 return Object . keys ( deps )
487- . filter ( ( depName ) => dockerfilePkgs [ depName ] )
425+ . filter ( ( depName ) => {
426+ if ( dockerfilePkgs [ depName ] !== undefined ) {
427+ return true ;
428+ }
429+ const source = depName . split ( "/" ) [ 0 ] ;
430+ return dockerfilePkgs [ source ] !== undefined ;
431+ } )
488432 . reduce ( ( extractedDeps , depName ) => {
489433 extractedDeps [ depName ] = deps [ depName ] ;
490434 return extractedDeps ;
491435 } , { } ) ;
492436}
493437
494438/**
495- * Annotates the dependency tree with layer IDs.
496- *
439+ * Annotates the dependencies with the layer ID of the Dockerfile
440+ * instruction that installed them.
441+ *
497442 * @important
498443 * mutates the provided `deps` object.
499- *
444+
500445 * @param deps - The dependencies of the image.
501446 * @param dockerfilePkgs - The expanded packages attributed to the Dockerfile.
502447 */
503- function annotateWithLayerIds (
504- deps : { [ depName : string ] : types . DepTreeDep } ,
448+ function annotateLayerIds (
449+ deps : {
450+ [ depName : string ] : types . DepTreeDep ;
451+ } ,
505452 dockerfilePkgs : DockerFilePackages | undefined ,
506- ) : void {
453+ ) {
507454 if ( ! dockerfilePkgs ) {
508455 return ;
509456 }
510457
511- function annotateRecursive ( currentDeps : {
512- [ depName : string ] : types . DepTreeDep ;
513- } ) {
514- for ( const depKey of Object . keys ( currentDeps ) ) {
515- const node = currentDeps [ depKey ] ;
516- const dockerfileEntry = dockerfilePkgs ! [ depKey ] ;
517-
518- if ( dockerfileEntry ) {
519- node . labels = {
520- ...( node . labels || { } ) ,
521- dockerLayerId : instructionDigest ( dockerfileEntry . instruction ) ,
522- } ;
523-
524- // Only progress down the dependency tree if the current node is a dockerfile package.
525- if ( node . dependencies ) {
526- annotateRecursive ( node . dependencies ) ;
527- }
528- }
458+ for ( const dep of Object . keys ( deps ) ) {
459+ const pkg = deps [ dep ] ;
460+ const pkgSource = dep . split ( "/" ) [ 0 ] ;
461+ const dockerfilePkg = dockerfilePkgs [ dep ] || dockerfilePkgs [ pkgSource ] ;
462+ if ( dockerfilePkg ) {
463+ pkg . labels = {
464+ ...( pkg . labels || { } ) ,
465+ dockerLayerId : instructionDigest ( dockerfilePkg . instruction ) ,
466+ } ;
467+ }
468+ if ( pkg . dependencies ) {
469+ annotateLayerIds ( pkg . dependencies , dockerfilePkgs ) ;
529470 }
530471 }
531-
532- annotateRecursive ( deps ) ;
533472}
0 commit comments