@@ -2,12 +2,14 @@ package leeway
22
33import (
44 "archive/tar"
5+ "compress/gzip"
56 "context"
67 "crypto/rand"
78 "crypto/sha256"
89 "encoding/base64"
910 "encoding/hex"
1011 "encoding/json"
12+ "errors"
1113 "fmt"
1214 "io"
1315 "os"
@@ -1239,7 +1241,10 @@ func (p *Package) buildDocker(buildctx *buildContext, wd, result string) (res *p
12391241 return nil , err
12401242 }
12411243
1242- var buildCommands [][]string
1244+ var (
1245+ buildCommands [][]string
1246+ imageDependencies = make (map [string ]string )
1247+ )
12431248 buildCommands = append (buildCommands , []string {"cp" , dockerfile , "Dockerfile" })
12441249 for _ , dep := range p .GetDependencies () {
12451250 fn , exists := buildctx .LocalCache .Location (dep )
@@ -1252,6 +1257,15 @@ func (p *Package) buildDocker(buildctx *buildContext, wd, result string) (res *p
12521257 {"mkdir" , tgt },
12531258 {"tar" , "xfz" , fn , "--no-same-owner" , "-C" , tgt },
12541259 }... )
1260+
1261+ if dep .Type != DockerPackage {
1262+ continue
1263+ }
1264+ depimg , err := extractImageNameFromCache (dep .Name , fn )
1265+ if err != nil {
1266+ return nil , err
1267+ }
1268+ imageDependencies [strings .ToUpper (strings .ReplaceAll (dep .FilesystemSafeName (), "-" , "_" ))] = depimg
12551269 }
12561270
12571271 buildCommands = append (buildCommands , p .PreparationCommands ... )
@@ -1265,6 +1279,9 @@ func (p *Package) buildDocker(buildctx *buildContext, wd, result string) (res *p
12651279 for arg , val := range cfg .BuildArgs {
12661280 buildcmd = append (buildcmd , "--build-arg" , fmt .Sprintf ("%s=%s" , arg , val ))
12671281 }
1282+ for arg , val := range imageDependencies {
1283+ buildcmd = append (buildcmd , "--build-arg" , fmt .Sprintf ("DEP_%s=%s" , arg , val ))
1284+ }
12681285 buildcmd = append (buildcmd , "--build-arg" , fmt .Sprintf ("__GIT_COMMIT=%s" , p .C .Git ().Commit ))
12691286 if cfg .Squash {
12701287 buildcmd = append (buildcmd , "--squash" )
@@ -1415,6 +1432,60 @@ func dockerExportPostBuild(builddir, result string) func(sources fileset) (subj
14151432 }
14161433}
14171434
1435+ // extractImageNameFromCache extracts the Docker image name of a previously built package
1436+ // from the cache tar.gz file of that package.
1437+ func extractImageNameFromCache (pkgName , cacheBundleFN string ) (imgname string , err error ) {
1438+ defer func () {
1439+ if err != nil {
1440+ err = fmt .Errorf ("cannot extract image ref from cache for %s: %w" , pkgName , err )
1441+ }
1442+ }()
1443+
1444+ f , err := os .Open (cacheBundleFN )
1445+ if err != nil {
1446+ return "" , err
1447+ }
1448+ defer f .Close ()
1449+
1450+ gzin , err := gzip .NewReader (f )
1451+ if err != nil {
1452+ return "" , err
1453+ }
1454+ defer gzin .Close ()
1455+
1456+ tarin := tar .NewReader (gzin )
1457+ for {
1458+ hdr , err := tarin .Next ()
1459+ if errors .Is (err , io .EOF ) {
1460+ break
1461+ }
1462+ if err != nil {
1463+ return "" , err
1464+ }
1465+
1466+ if hdr .Typeflag != tar .TypeReg {
1467+ continue
1468+ }
1469+ if filepath .Base (hdr .Name ) != dockerImageNamesFiles {
1470+ continue
1471+ }
1472+
1473+ imgnames := make ([]byte , hdr .Size )
1474+ n , err := io .ReadFull (tarin , imgnames )
1475+ if err != nil {
1476+ return "" , err
1477+ }
1478+ if int64 (n ) != hdr .Size {
1479+ return "" , fmt .Errorf ("cannot read %s from cache: %w" , dockerImageNamesFiles , io .ErrShortBuffer )
1480+ }
1481+
1482+ lines := strings .Split (string (imgnames ), "\n " )
1483+ return lines [0 ], nil
1484+ }
1485+
1486+ return "" , nil
1487+ }
1488+
14181489// buildGeneric implements the build process for generic packages.
14191490// If you change anything in this process that's not backwards compatible, make sure you increment BuildGenericProccessVersion.
14201491func (p * Package ) buildGeneric (buildctx * buildContext , wd , result string ) (res * packageBuild , err error ) {
0 commit comments