@@ -2929,6 +2929,56 @@ include = [ "*.jar", "media/mountain.jpg", "/media/person.png", ]
29292929 })
29302930 })
29312931 })
2932+
2933+ when ("builder create" , func () {
2934+ when ("--flatten=<buildpacks>" , func () {
2935+ it ("should flatten together all specified buildpacks" , func () {
2936+ h .SkipIf (t , ! createBuilderPack .SupportsFeature (invoke .FlattenBuilderCreationV2 ), "pack version <= 0.33.0 fails with this test" )
2937+ h .SkipIf (t , imageManager .HostOS () == "windows" , "These tests are not yet compatible with Windows-based containers" )
2938+
2939+ // create a task, handled by a 'task manager' which executes our pack commands during tests.
2940+ // looks like this is used to de-dup tasks
2941+ key := taskKey (
2942+ "create-complex-flattened-builder" ,
2943+ append (
2944+ []string {runImageMirror , createBuilderPackConfig .Path (), lifecycle .Identifier ()},
2945+ createBuilderPackConfig .FixturePaths ()... ,
2946+ )... ,
2947+ )
2948+
2949+ builderName , err := suiteManager .RunTaskOnceString (key , func () (string , error ) {
2950+ return createFlattenBuilder (t ,
2951+ assert ,
2952+ buildpackManager ,
2953+ lifecycle ,
2954+ createBuilderPack ,
2955+ runImageMirror )
2956+ })
2957+ assert .Nil (err )
2958+
2959+ // register task to be run to 'clean up' a task
2960+ suiteManager .RegisterCleanUp ("clean-" + key , func () error {
2961+ imageManager .CleanupImages (builderName )
2962+ return nil
2963+ })
2964+
2965+ assertImage .ExistsLocally (builderName )
2966+
2967+ // 3 layers for runtime OS
2968+ // 1 layer setting cnb, platform, layers folders
2969+ // 1 layer for lifecycle binaries
2970+ // 1 layer for order.toml
2971+ // 1 layer for run.toml
2972+ // 1 layer for stack.toml
2973+ // 1 layer status file changed
2974+ // Base Layers = 9
2975+
2976+ // 1 layer for 3 flattened builpacks
2977+ // 3 layers for single buildpacks not flattened
2978+ assertImage .HasLengthLayers (builderName , 13 )
2979+ })
2980+ })
2981+ })
29322982 })
29332983}
29342984
@@ -3315,6 +3365,157 @@ func createStackImage(dockerCli client.CommonAPIClient, repoName string, dir str
33153365 }))
33163366}
33173367
3368+ func createFlattenBuilder (
3369+ t * testing.T ,
3370+ assert h.AssertionManager ,
3371+ buildpackManager buildpacks.BuildModuleManager ,
3372+ lifecycle config.LifecycleAsset ,
3373+ pack * invoke.PackInvoker ,
3374+ runImageMirror string ,
3375+ ) (string , error ) {
3376+ t .Helper ()
3377+ t .Log ("creating flattened builder image..." )
3378+
3379+ // CREATE TEMP WORKING DIR
3380+ tmpDir , err := os .MkdirTemp ("" , "create-complex-test-flattened-builder" )
3381+ if err != nil {
3382+ return "" , err
3383+ }
3384+ defer os .RemoveAll (tmpDir )
3385+
3386+ // ARCHIVE BUILDPACKS
3387+ builderBuildpacks := []buildpacks.TestBuildModule {
3388+ buildpacks .BpNoop ,
3389+ buildpacks .BpNoop2 ,
3390+ buildpacks .BpOtherStack ,
3391+ buildpacks .BpReadEnv ,
3392+ }
3393+
3394+ templateMapping := map [string ]interface {}{
3395+ "run_image_mirror" : runImageMirror ,
3396+ }
3397+
3398+ packageImageName := registryConfig .RepoName ("nested-level-1-buildpack-" + h .RandString (8 ))
3399+ nestedLevelTwoBuildpackName := registryConfig .RepoName ("nested-level-2-buildpack-" + h .RandString (8 ))
3400+ simpleLayersBuildpackName := registryConfig .RepoName ("simple-layers-buildpack-" + h .RandString (8 ))
3401+ simpleLayersBuildpackDifferentShaName := registryConfig .RepoName ("simple-layers-buildpack-different-name-" + h .RandString (8 ))
3402+
3403+ templateMapping ["package_id" ] = "simple/nested-level-1"
3404+ templateMapping ["package_image_name" ] = packageImageName
3405+ templateMapping ["nested_level_1_buildpack" ] = packageImageName
3406+ templateMapping ["nested_level_2_buildpack" ] = nestedLevelTwoBuildpackName
3407+ templateMapping ["simple_layers_buildpack" ] = simpleLayersBuildpackName
3408+ templateMapping ["simple_layers_buildpack_different_sha" ] = simpleLayersBuildpackDifferentShaName
3409+
3410+ fixtureManager := pack .FixtureManager ()
3411+
3412+ nestedLevelOneConfigFile , err := os .CreateTemp (tmpDir , "nested-level-1-package.toml" )
3413+ assert .Nil (err )
3414+ fixtureManager .TemplateFixtureToFile (
3415+ "nested-level-1-buildpack_package.toml" ,
3416+ nestedLevelOneConfigFile ,
3417+ templateMapping ,
3418+ )
3419+ err = nestedLevelOneConfigFile .Close ()
3420+ assert .Nil (err )
3421+
3422+ nestedLevelTwoConfigFile , err := os .CreateTemp (tmpDir , "nested-level-2-package.toml" )
3423+ assert .Nil (err )
3424+ fixtureManager .TemplateFixtureToFile (
3425+ "nested-level-2-buildpack_package.toml" ,
3426+ nestedLevelTwoConfigFile ,
3427+ templateMapping ,
3428+ )
3429+
3430+ err = nestedLevelTwoConfigFile .Close ()
3431+ assert .Nil (err )
3432+
3433+ packageImageBuildpack := buildpacks .NewPackageImage (
3434+ t ,
3435+ pack ,
3436+ packageImageName ,
3437+ nestedLevelOneConfigFile .Name (),
3438+ buildpacks .WithRequiredBuildpacks (
3439+ buildpacks .BpNestedLevelOne ,
3440+ buildpacks .NewPackageImage (
3441+ t ,
3442+ pack ,
3443+ nestedLevelTwoBuildpackName ,
3444+ nestedLevelTwoConfigFile .Name (),
3445+ buildpacks .WithRequiredBuildpacks (
3446+ buildpacks .BpNestedLevelTwo ,
3447+ buildpacks .NewPackageImage (
3448+ t ,
3449+ pack ,
3450+ simpleLayersBuildpackName ,
3451+ fixtureManager .FixtureLocation ("simple-layers-buildpack_package.toml" ),
3452+ buildpacks .WithRequiredBuildpacks (buildpacks .BpSimpleLayers ),
3453+ ),
3454+ ),
3455+ ),
3456+ ),
3457+ )
3458+
3459+ simpleLayersDifferentShaBuildpack := buildpacks .NewPackageImage (
3460+ t ,
3461+ pack ,
3462+ simpleLayersBuildpackDifferentShaName ,
3463+ fixtureManager .FixtureLocation ("simple-layers-buildpack-different-sha_package.toml" ),
3464+ buildpacks .WithRequiredBuildpacks (buildpacks .BpSimpleLayersDifferentSha ),
3465+ )
3466+
3467+ defer imageManager .CleanupImages (packageImageName , nestedLevelTwoBuildpackName , simpleLayersBuildpackName , simpleLayersBuildpackDifferentShaName )
3468+
3469+ builderBuildpacks = append (
3470+ builderBuildpacks ,
3471+ packageImageBuildpack ,
3472+ simpleLayersDifferentShaBuildpack ,
3473+ )
3474+
3475+ buildpackManager .PrepareBuildModules (tmpDir , builderBuildpacks ... )
3476+
3477+ // ADD lifecycle
3478+ if lifecycle .HasLocation () {
3479+ lifecycleURI := lifecycle .EscapedPath ()
3480+ t .Logf ("adding lifecycle path '%s' to builder config" , lifecycleURI )
3481+ templateMapping ["lifecycle_uri" ] = lifecycleURI
3482+ } else {
3483+ lifecycleVersion := lifecycle .Version ()
3484+ t .Logf ("adding lifecycle version '%s' to builder config" , lifecycleVersion )
3485+ templateMapping ["lifecycle_version" ] = lifecycleVersion
3486+ }
3487+
3488+ // RENDER builder.toml
3489+ builderConfigFile , err := os .CreateTemp (tmpDir , "nested_builder.toml" )
3490+ if err != nil {
3491+ return "" , err
3492+ }
3493+
3494+ pack .FixtureManager ().TemplateFixtureToFile ("nested_builder.toml" , builderConfigFile , templateMapping )
3495+
3496+ err = builderConfigFile .Close ()
3497+ if err != nil {
3498+ return "" , err
3499+ }
3500+
3501+ // NAME BUILDER
3502+ bldr := registryConfig .RepoName ("test/flatten-builder-" + h .RandString (10 ))
3503+
3504+ // CREATE BUILDER
3505+ output := pack .RunSuccessfully (
3506+ "builder" , "create" , bldr ,
3507+ "-c" , builderConfigFile .Name (),
3508+ "--no-color" ,
3509+ "--verbose" ,
3510+ "--flatten" ,
"read/env@read-env-version,[email protected] ,[email protected] " ,
3511+ )
3512+
3513+ assert .Contains (output , fmt .Sprintf ("Successfully created builder image '%s'" , bldr ))
3514+ assert .Succeeds (h .PushImage (dockerCli , bldr , registryConfig ))
3515+
3516+ return bldr , nil
3517+ }
3518+
33183519// taskKey creates a key from the prefix and all arguments to be unique
33193520func taskKey (prefix string , args ... string ) string {
33203521 hash := sha256 .New ()
0 commit comments