From a68ed1dae7b127aa59458c61d050423588be5d10 Mon Sep 17 00:00:00 2001 From: Kritka Sahni <122665407+kritkasahni-google@users.noreply.github.com> Date: Tue, 17 Oct 2023 16:03:56 -0700 Subject: [PATCH 01/34] Create 0000-creator-skip-sbom.md Signed-off-by: Kritka Sahni <122665407+kritkasahni-google@users.noreply.github.com> --- text/0000-creator-skip-sbom.md | 131 +++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 text/0000-creator-skip-sbom.md diff --git a/text/0000-creator-skip-sbom.md b/text/0000-creator-skip-sbom.md new file mode 100644 index 000000000..6e01fcf56 --- /dev/null +++ b/text/0000-creator-skip-sbom.md @@ -0,0 +1,131 @@ +# Meta +[meta]: #meta +- Name: Enable CNB_SKIP_SBOM IN /cnb/lifecycle/creator +- Start Date: (fill in today's date: 2023-10-17) +- Author(s): kritkasahni-google +- Status: Draft +- RFC Pull Request: +- CNB Pull Request: +- CNB Issue: +- Supersedes: N/A + +# Summary +[summary]: #summary + +Enable CNB_SKIP_SBOM IN /cnb/lifecycle/creator to skip restoring SBOM layer from previous app image. We support CNB_SKIP_LAYERS in analyzer which does the same thing and we should support the same in creator also. + +# Definitions +[definitions]: #definitions +* lifecycle: software that orchestrates a CNB build. +* creator: executes all the lifecycle phases one by one in order. +* analyzer: lifecycle phase that restores SBOM layer from previous app image. +* restorer: lifecycle phase that restores layers from cache. +* SBOM: a software bill of materials (SBOM) is a list of all the components that make up the app image. + +# Motivation +[motivation]: #motivation + +To skip restoring SBOM layer from previous image when platform executes lifecycle by calling /cnb/lifecycle/creator. Restoring SBOM layer from previous app image can cause degraded build latency but if buildpack logic does not rely on SBOM from previous app image then should be able to skip restoring it. + +# What it is +[what-it-is]: #what-it-is + +CNB_SKIP_LAYERS is used by /cnb/lifecycle/analyzer to skip restoring SBOM layer from previous app image. +Need a similar mechanism for /cnb/lifecyle/creator specifically to skip restoring only the SBOM layer. + +The target personas affected by this change are: + + - **buildpack user**: if buildpacks don't rely on reusing SBOM layer then buildpack user should ideally see improved build latency by skipping SBOM restoration but reusing other layers from previous app image. + - **Platform implementors**: they will choose to skip restoring SBOM by providing CNB_SKIP_SBOM to trigger /cnb/lifecycle/creator. + + +# How it Works +[how-it-works]: #how-it-works + +Similar to how CNB_SKIP_LAYERS is handled in analyzer whether SBOM needs to be [restored](https://github.com/buildpacks/lifecycle/blob/292aa492a72f4e180bb92d109a73ebf7c8a0451d/phase/analyzer.go#L38) or [not](https://github.com/buildpacks/lifecycle/blob/292aa492a72f4e180bb92d109a73ebf7c8a0451d/phase/analyzer.go#L30) today, CNB_SKIP_SBOM will be be handled in same way in analyzer. +At the platform level, it would be input same way as CNB_SKIP_LAYERS [here](https://github.com/buildpacks/lifecycle/blob/292aa492a72f4e180bb92d109a73ebf7c8a0451d/platform/defaults.go#L184) and [handled](https://github.com/buildpacks/lifecycle/blob/main/platform/lifecycle_inputs.go#L82) like:- + + +``` + var skipSBOM bool + if boolEnv(EnvSkipSBOM){ + skipSBOM = true + } +``` + +In the analyzer, + +``` +analyzer := &Analyzer{ + Logger: logger, + SBOMRestorer: &layer.NopSBOMRestorer{}, + PlatformAPI: f.platformAPI, + } + + ... + if f.platformAPI.AtLeast("0.8") && !inputs.SkipLayers && !inputs.SkipSBOM { + analyzer.SBOMRestorer = &layer.DefaultSBOMRestorer{ + LayersDir: inputs.LayersDir, + Logger: logger, + } + } +``` + +# Migration +[migration]: #migration + +CNB_SKIP_SBOM/<skip-sbom> will be an optional input to /cnb/lifecycle/creator, and will be false by default. We maybe need to add a new API option for buildpack users, to choose whether this should be enabled. + +# Drawbacks +[drawbacks]: #drawbacks + +N/A + +# Alternatives +[alternatives]: #alternatives + +Platforms that execute lifecycle today via /cnb/lifecycle/creator are unable to skip restoring SBOM layer from previous app image unless they skip reusing previous app image entirely. + +# Prior Art +[prior-art]: #prior-art + +We already support enabling CNB_SKIP_LAYERS in /cnb/lifecycle/analyzer and /cnb/lifecycle/restorer, and CNB_SKIP_RESTORE in /cnb/lifecycle/creator. +* CNB_SKIP_LAYERS in /cnb/lifecycle/analyzer to skip restoring SBOM from previous app image. +* CNB_SKIP_LAYERS in /cnb/lifecycle/restorer to skip reusing previous app image layers entirely. +* CNB_SKIP_RESTORE in /cnb/lifecycle/creator to skips restoring SBOM plus all other layers entirely from previous app image. + +# Unresolved Questions +[unresolved-questions]: #unresolved-questions + +N/A + +# Spec. Changes (OPTIONAL) +[spec-changes]: #spec-changes +This new feature will affect the API of [Create](https://buildpacks.io/docs/concepts/components/lifecycle/create/) phase by adding the following fields. + +Back to API changes, we will add a new flag to control this. + +| Input | Environment Variable | DefaultValue | Description | +|----------------|-----------------------|--------------|----------------------------------------------| +| `<skip-sbom>` | `CNB_SKIP_SBOM` | `false` | Skip SBOM restoration | + +# History +[history]: #history + +<!-- +## Amended +### Meta +[meta-1]: #meta-1 +- Name: (fill in the amendment name: Variable Rename) +- Start Date: (fill in today's date: YYYY-MM-DD) +- Author(s): (Github usernames) +- Amendment Pull Request: (leave blank) + +### Summary + +A brief description of the changes. + +### Motivation + +Why was this amendment necessary? +---> From 91a8eaac4204a89c9301fe836785a17f80ba3336 Mon Sep 17 00:00:00 2001 From: Pavel Busko <pavel.busko@sap.com> Date: Mon, 9 Oct 2023 14:41:32 +0200 Subject: [PATCH 02/34] Add RFC for extension layers Co-authored-by: Ralf Pannemans <ralf.pannemans@sap.com> Signed-off-by: Ralf Pannemans <ralf.pannemans@sap.com> Co-authored-by: Pavel Busko <pavel.busko@sap.com> Signed-off-by: Pavel Busko <pavel.busko@sap.com> --- text/0000-extension-layer.md | 90 ++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 text/0000-extension-layer.md diff --git a/text/0000-extension-layer.md b/text/0000-extension-layer.md new file mode 100644 index 000000000..e337fb0b0 --- /dev/null +++ b/text/0000-extension-layer.md @@ -0,0 +1,90 @@ +# Meta +[meta]: #meta +- Name: Add extension layer to exchange data +- Start Date: 2023-10-09 +- Author(s): [c0d1ngm0nk3y](https://github.com/c0d1ngm0nk3y), [pbusko](https://github.com/pbusko) +- Status: Draft <!-- Acceptable values: Draft, Approved, On Hold, Superseded --> +- RFC Pull Request: +- CNB Pull Request: +- CNB Issue: +- Related: [RFC#0105 Support Dockerfiles](https://github.com/buildpacks/rfcs/blob/main/text/0105-dockerfiles.md) +- Supersedes: N/A + +# Summary +[summary]: #summary + +This RFC introduces support for Extension Layers to allow data transfer between the build environment and the Kaniko execution. + +# Motivation +[motivation]: #motivation + +This change allows extensions to possess their own layers to utilize during the generation/extend process. Additionally, it ensures that extension output does not inadvertently interfere with other extension or buildpack layers during the build, and it does not unintentionally become part of the final application image. + +This would allow distroless run images to be extended. + +# What it is +[what-it-is]: #what-it-is + +This follows up on RFC-0105 and proposes that during the execution of the extension's `bin/generate`, an extension is allowed to write arbitrary data to its exclusive layer. This data then becomes accessible during the execution of the `extend` phase via Kaniko context. The content of these extension-specific layers is ignored at build and launch time, it serves only the extension phase. + +# How it Works +[how-it-works]: #how-it-works + +Before execution of the `bin/generate`, the lifecycle will create a distinct writable layer for each extension which passed detection. The extensions can then write to these layers, and the Kaniko context is set to the corresponding layer during the `extend` phase instead of the `<app>` directory. The Extension Layers will not be included in the final image by the lifecycle. + +The location of the Extension Layer will be provided to the `bin/generate` via additional environment variable `CNB_EXT_LAYER_DIR`. + +# Migration +[migration]: #migration + +Since we would change the Kaniko context, this would be breaking for existing extensions. + +# Drawbacks +[drawbacks]: #drawbacks + +Why should we *not* do this? + +The workspace would no longer be the Kaniko context. But the benefit of having it in the first place seems quite limited anyway. + +# Alternatives +[alternatives]: #alternatives + +- Allow multi-stage Dockerfiles + +# Prior Art +[prior-art]: #prior-art + +Discuss prior art, both the good and bad. + +# Unresolved Questions +[unresolved-questions]: #unresolved-questions + +- Should the `bin/generate` be executed during the `extend` phase instead of the `detect` phase? +- The Kaniko context might consist of two folders: `<app>` and the Extension Layer for better compatibility. + +# Spec. Changes (OPTIONAL) +[spec-changes]: #spec-changes + +This RFC requires changes to the layers metadata and the `extend` phase: + +- layer metadata needs ti ubducate if a layer is a "extension layer" +- env variable with the layer location for the extension to write to +- kaniko context should be the extension layer and not the workspace + +<!-- +## Amended +### Meta +[meta-1]: #meta-1 +- Name: (fill in the amendment name: Variable Rename) +- Start Date: (fill in today's date: YYYY-MM-DD) +- Author(s): (Github usernames) +- Amendment Pull Request: (leave blank) + +### Summary + +A brief description of the changes. + +### Motivation + +Why was this amendment necessary? +---> \ No newline at end of file From 54fd7b04d74ab771cc5f158d4532beeb1add3063 Mon Sep 17 00:00:00 2001 From: Pavel Busko <pavel.busko@sap.com> Date: Wed, 25 Oct 2023 14:24:19 +0200 Subject: [PATCH 03/34] add examples Signed-off-by: Pavel Busko <pavel.busko@sap.com> --- text/0000-extension-layer.md | 48 ++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/text/0000-extension-layer.md b/text/0000-extension-layer.md index e337fb0b0..6fc860499 100644 --- a/text/0000-extension-layer.md +++ b/text/0000-extension-layer.md @@ -25,26 +25,56 @@ This would allow distroless run images to be extended. # What it is [what-it-is]: #what-it-is -This follows up on RFC-0105 and proposes that during the execution of the extension's `bin/generate`, an extension is allowed to write arbitrary data to its exclusive layer. This data then becomes accessible during the execution of the `extend` phase via Kaniko context. The content of these extension-specific layers is ignored at build and launch time, it serves only the extension phase. +This follows up on RFC-0105 and proposes that during the execution of the extension's `./bin/generate`, an extension is allowed to write arbitrary data to the `context` folder within its exclusive layer. This data then becomes accessible during the execution of the `extend` phase via Kaniko build context. The content of these extension-specific layers is ignored at build and launch time, it serves only the extension phase. # How it Works [how-it-works]: #how-it-works -Before execution of the `bin/generate`, the lifecycle will create a distinct writable layer for each extension which passed detection. The extensions can then write to these layers, and the Kaniko context is set to the corresponding layer during the `extend` phase instead of the `<app>` directory. The Extension Layers will not be included in the final image by the lifecycle. +- New root directory `/layers-ext` is introduced which contains extension layers. +- Before execution of the `./bin/generate`, the lifecycle will create a distinct writable layer `/layers-ext/<extension-id>` for each extension which passed detection. +- The `/layers-ext/<extension-id>` is provided to the `./bin/generate` as `<output>` directory. +- In addition to the files specified in [RFC#0105](https://github.com/buildpacks/rfcs/blob/main/text/0105-dockerfiles.md), the extension may create the `<output>/context` folder with an arbitrary content. +- If the folder `<output>/context` is present it will be set as Kaniko build context during the `extend` phase instead of the `<app>` directory. +- If the folder `<output>/context` is not present, Kaniko build context defaults to the `<app>` folder. + +The `/layers-ext` will not be included in the final image by the lifecycle. -The location of the Extension Layer will be provided to the `bin/generate` via additional environment variable `CNB_EXT_LAYER_DIR`. +### Example: Extend distroless run image with Debian packages. + +This example extension would allow to install `tar` package on the run image without package manager (distroless image). The extension contains `./bin/generate` and `./bin/custom-installer` file, which installs `.deb` files. + +##### `./bin/generate` + +```bash +#!/bin/sh + +mkdir -p ${CNB_OUTPUT_DIR}/context + +cp ${CNB_EXTENSION_DIR}/bin/custom-installer ${CNB_OUTPUT_DIR}/context/ +curl -o ${CNB_OUTPUT_DIR}/context/tar.deb http://security.ubuntu.com/ubuntu/pool/main/t/tar/tar_1.34+dfsg-1ubuntu0.1.22.04.1_amd64.deb + +cat >> "${CNB_OUTPUT_DIR}/run.Dockerfile" <<EOL +ARG base_image +FROM \${base_image} +ARG build_id=0 + +ADD custom-installer . +ADD tar.deb . +RUN ./custom-installer -p ./tar.deb +EOL +``` # Migration [migration]: #migration -Since we would change the Kaniko context, this would be breaking for existing extensions. +- No breaking changes were identified # Drawbacks [drawbacks]: #drawbacks Why should we *not* do this? -The workspace would no longer be the Kaniko context. But the benefit of having it in the first place seems quite limited anyway. +N/A # Alternatives [alternatives]: #alternatives @@ -59,17 +89,15 @@ Discuss prior art, both the good and bad. # Unresolved Questions [unresolved-questions]: #unresolved-questions -- Should the `bin/generate` be executed during the `extend` phase instead of the `detect` phase? -- The Kaniko context might consist of two folders: `<app>` and the Extension Layer for better compatibility. +- Should the `./bin/generate` be executed during the `extend` phase instead of the `detect` phase? # Spec. Changes (OPTIONAL) [spec-changes]: #spec-changes This RFC requires changes to the layers metadata and the `extend` phase: -- layer metadata needs ti ubducate if a layer is a "extension layer" -- env variable with the layer location for the extension to write to -- kaniko context should be the extension layer and not the workspace +- allow optional folder `<output>/context` with an arbitrary content to be provided by extension. +- if the `<output>/context` is present, kaniko context should be set to this folder instead of the `<app>`. <!-- ## Amended From 3b2372036d57f4cb9fcfb9647356c3a1de1eea4b Mon Sep 17 00:00:00 2001 From: Pavel Busko <busko.pavel@gmail.com> Date: Thu, 2 Nov 2023 16:24:02 +0100 Subject: [PATCH 04/34] Update text/0000-extension-layer.md Co-authored-by: Natalie Arellano <narellano@vmware.com> Signed-off-by: Pavel Busko <busko.pavel@gmail.com> --- text/0000-extension-layer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-extension-layer.md b/text/0000-extension-layer.md index 6fc860499..afdefe131 100644 --- a/text/0000-extension-layer.md +++ b/text/0000-extension-layer.md @@ -13,7 +13,7 @@ # Summary [summary]: #summary -This RFC introduces support for Extension Layers to allow data transfer between the build environment and the Kaniko execution. +This RFC introduces support for Extension configurable context to allow data transfer between the build environment and the Kaniko execution. # Motivation [motivation]: #motivation From 990d7155b15b021d37a445108300a3e03b6434c0 Mon Sep 17 00:00:00 2001 From: Pavel Busko <busko.pavel@gmail.com> Date: Thu, 2 Nov 2023 16:24:15 +0100 Subject: [PATCH 05/34] Update text/0000-extension-layer.md Co-authored-by: Natalie Arellano <narellano@vmware.com> Signed-off-by: Pavel Busko <busko.pavel@gmail.com> --- text/0000-extension-layer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-extension-layer.md b/text/0000-extension-layer.md index afdefe131..16314a960 100644 --- a/text/0000-extension-layer.md +++ b/text/0000-extension-layer.md @@ -18,7 +18,7 @@ This RFC introduces support for Extension configurable context to allow data tra # Motivation [motivation]: #motivation -This change allows extensions to possess their own layers to utilize during the generation/extend process. Additionally, it ensures that extension output does not inadvertently interfere with other extension or buildpack layers during the build, and it does not unintentionally become part of the final application image. +This change allows extensions to create their own context for the extend phase during the generation phase. Additionally, it ensures that extension output does not inadvertently interfere with other extension or buildpack layers during the build, and it does not unintentionally become part of the final application image. This would allow distroless run images to be extended. From 4130a0e5625e2212aaa6a3f24434bc697c5769cd Mon Sep 17 00:00:00 2001 From: Pavel Busko <busko.pavel@gmail.com> Date: Thu, 2 Nov 2023 16:24:36 +0100 Subject: [PATCH 06/34] Update text/0000-extension-layer.md Co-authored-by: Natalie Arellano <narellano@vmware.com> Signed-off-by: Pavel Busko <busko.pavel@gmail.com> --- text/0000-extension-layer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-extension-layer.md b/text/0000-extension-layer.md index 16314a960..f123ad5c6 100644 --- a/text/0000-extension-layer.md +++ b/text/0000-extension-layer.md @@ -25,7 +25,7 @@ This would allow distroless run images to be extended. # What it is [what-it-is]: #what-it-is -This follows up on RFC-0105 and proposes that during the execution of the extension's `./bin/generate`, an extension is allowed to write arbitrary data to the `context` folder within its exclusive layer. This data then becomes accessible during the execution of the `extend` phase via Kaniko build context. The content of these extension-specific layers is ignored at build and launch time, it serves only the extension phase. +This follows up on RFC-0105 and proposes that during the execution of the extension's `./bin/generate`, an extension is allowed to write arbitrary data to the `context` folder within its exclusive output directory. This data then becomes accessible during the execution of the `extend` phase via Kaniko build context. The content of these extension-specific context is ignored at build and launch time, it serves only the extension phase. # How it Works [how-it-works]: #how-it-works From 5aa99d6f651764bddd4d1eb8f1ab798b68791d12 Mon Sep 17 00:00:00 2001 From: Pavel Busko <busko.pavel@gmail.com> Date: Thu, 2 Nov 2023 16:24:48 +0100 Subject: [PATCH 07/34] Update text/0000-extension-layer.md Co-authored-by: Natalie Arellano <narellano@vmware.com> Signed-off-by: Pavel Busko <busko.pavel@gmail.com> --- text/0000-extension-layer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-extension-layer.md b/text/0000-extension-layer.md index f123ad5c6..3c6043fa0 100644 --- a/text/0000-extension-layer.md +++ b/text/0000-extension-layer.md @@ -31,7 +31,7 @@ This follows up on RFC-0105 and proposes that during the execution of the extens [how-it-works]: #how-it-works - New root directory `/layers-ext` is introduced which contains extension layers. -- Before execution of the `./bin/generate`, the lifecycle will create a distinct writable layer `/layers-ext/<extension-id>` for each extension which passed detection. +- Before execution of the `./bin/generate`, the lifecycle will create a distinct writable directory `/layers-ext/<extension-id>` for each extension which passed detection. - The `/layers-ext/<extension-id>` is provided to the `./bin/generate` as `<output>` directory. - In addition to the files specified in [RFC#0105](https://github.com/buildpacks/rfcs/blob/main/text/0105-dockerfiles.md), the extension may create the `<output>/context` folder with an arbitrary content. - If the folder `<output>/context` is present it will be set as Kaniko build context during the `extend` phase instead of the `<app>` directory. From d6276275e91b77e95063750621300021d25a2aa1 Mon Sep 17 00:00:00 2001 From: Pavel Busko <pavel.busko@sap.com> Date: Wed, 22 Nov 2023 10:55:38 +0100 Subject: [PATCH 08/34] Reuse CNB_GENERATED_DIR and allow image-specific folders Signed-off-by: Pavel Busko <pavel.busko@sap.com> Co-authored-by: Pavel Busko <pavel.busko@sap.com> --- text/0000-extension-layer.md | 37 ++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/text/0000-extension-layer.md b/text/0000-extension-layer.md index 3c6043fa0..200d43707 100644 --- a/text/0000-extension-layer.md +++ b/text/0000-extension-layer.md @@ -30,14 +30,26 @@ This follows up on RFC-0105 and proposes that during the execution of the extens # How it Works [how-it-works]: #how-it-works -- New root directory `/layers-ext` is introduced which contains extension layers. -- Before execution of the `./bin/generate`, the lifecycle will create a distinct writable directory `/layers-ext/<extension-id>` for each extension which passed detection. -- The `/layers-ext/<extension-id>` is provided to the `./bin/generate` as `<output>` directory. -- In addition to the files specified in [RFC#0105](https://github.com/buildpacks/rfcs/blob/main/text/0105-dockerfiles.md), the extension may create the `<output>/context` folder with an arbitrary content. -- If the folder `<output>/context` is present it will be set as Kaniko build context during the `extend` phase instead of the `<app>` directory. -- If the folder `<output>/context` is not present, Kaniko build context defaults to the `<app>` folder. +- Before execution of the `./bin/generate`, the lifecycle will create a distinct writable layer `$CNB_GENERATED_DIR/<extension-id>` for each extension which passed detection. +- The `$CNB_GENERATED_DIR/<extension-id>` is provided to the `./bin/generate` as `<output>` (`$CNB_OUTPUT_DIR`) directory. +- In addition to the files specified in [RFC#0105](https://github.com/buildpacks/rfcs/blob/main/text/0105-dockerfiles.md), the extension may create the following folders with an arbitrary content: + + either: + + - `<output>/context` + + or the image-specific folders: + + - `<output>/context.run` + - `<output>/context.build` + + If the `<output>/context` is provided together with any of the image-specific folders the detection phase must fail. +- If the folder `<output>/context` is present it will be set as Kaniko build context during the `extend` phase of the build and run images. +- If the folder `<output>/context.run` is present it will be set as Kaniko build context during the `extend` phase of the run image only. +- If the folder `<output>/context.build` is present it will be set as Kaniko build context during the `extend` phase of the build image only. +- If none of these folders is not present, Kaniko build context defaults to the `<app>` folder. -The `/layers-ext` will not be included in the final image by the lifecycle. +The `$CNB_GENERATED_DIR/<extension-id>` folders will not be included in the final image by the lifecycle. ### Example: Extend distroless run image with Debian packages. @@ -48,10 +60,10 @@ This example extension would allow to install `tar` package on the run image wit ```bash #!/bin/sh -mkdir -p ${CNB_OUTPUT_DIR}/context +mkdir -p ${CNB_OUTPUT_DIR}/context.run -cp ${CNB_EXTENSION_DIR}/bin/custom-installer ${CNB_OUTPUT_DIR}/context/ -curl -o ${CNB_OUTPUT_DIR}/context/tar.deb http://security.ubuntu.com/ubuntu/pool/main/t/tar/tar_1.34+dfsg-1ubuntu0.1.22.04.1_amd64.deb +cp ${CNB_EXTENSION_DIR}/bin/custom-installer ${CNB_OUTPUT_DIR}/context.run/ +curl -o ${CNB_OUTPUT_DIR}/context.run/tar.deb http://security.ubuntu.com/ubuntu/pool/main/t/tar/tar_1.34+dfsg-1ubuntu0.1.22.04.1_amd64.deb cat >> "${CNB_OUTPUT_DIR}/run.Dockerfile" <<EOL ARG base_image @@ -96,8 +108,9 @@ Discuss prior art, both the good and bad. This RFC requires changes to the layers metadata and the `extend` phase: -- allow optional folder `<output>/context` with an arbitrary content to be provided by extension. -- if the `<output>/context` is present, kaniko context should be set to this folder instead of the `<app>`. +- the `$CNB_OUTPUT_DIR` must point to the `$CNB_GENERATED_DIR/<extension-id>` folder instead of a temporary directory. +- allow optional folders `$CNB_GENERATED_DIR/<extension-id>/context`, `$CNB_GENERATED_DIR/<extension-id>/context.run` and `$CNB_GENERATED_DIR/<extension-id>/context.build` with an arbitrary content to be provided by extension. +- if the context folders are present, kaniko context should be set to the corresponding folder instead of the `<app>` (following the rules defined in [#how-it-works](#how-it-works)). <!-- ## Amended From b191b65e8978be1dcf8f89acc8c134ca3346d57b Mon Sep 17 00:00:00 2001 From: Natalie Arellano <narellano@vmware.com> Date: Tue, 6 Feb 2024 14:50:46 -0500 Subject: [PATCH 09/34] Fix manually merged RFCs Signed-off-by: Natalie Arellano <narellano@vmware.com> --- text/{0000-creator-skip-sbom.md => 0126-creator-skip-sbom.md} | 2 +- text/{0000-extension-layer.md => 0127-extension-layer.md} | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename text/{0000-creator-skip-sbom.md => 0126-creator-skip-sbom.md} (99%) rename text/{0000-extension-layer.md => 0127-extension-layer.md} (98%) diff --git a/text/0000-creator-skip-sbom.md b/text/0126-creator-skip-sbom.md similarity index 99% rename from text/0000-creator-skip-sbom.md rename to text/0126-creator-skip-sbom.md index 6e01fcf56..eebd2b1ad 100644 --- a/text/0000-creator-skip-sbom.md +++ b/text/0126-creator-skip-sbom.md @@ -3,7 +3,7 @@ - Name: Enable CNB_SKIP_SBOM IN /cnb/lifecycle/creator - Start Date: (fill in today's date: 2023-10-17) - Author(s): kritkasahni-google -- Status: Draft +- Status: Approved - RFC Pull Request: - CNB Pull Request: - CNB Issue: diff --git a/text/0000-extension-layer.md b/text/0127-extension-layer.md similarity index 98% rename from text/0000-extension-layer.md rename to text/0127-extension-layer.md index 200d43707..55f033e66 100644 --- a/text/0000-extension-layer.md +++ b/text/0127-extension-layer.md @@ -3,7 +3,7 @@ - Name: Add extension layer to exchange data - Start Date: 2023-10-09 - Author(s): [c0d1ngm0nk3y](https://github.com/c0d1ngm0nk3y), [pbusko](https://github.com/pbusko) -- Status: Draft <!-- Acceptable values: Draft, Approved, On Hold, Superseded --> +- Status: Approved - RFC Pull Request: - CNB Pull Request: - CNB Issue: From 88c024f529c56828e74c520e53b51d83e8e5211c Mon Sep 17 00:00:00 2001 From: Juan Bustamante <jbustamante@vmware.com> Date: Thu, 14 Sep 2023 17:04:31 -0500 Subject: [PATCH 10/34] Initial version Signed-off-by: Juan Bustamante <jbustamante@vmware.com> --- text/0000-multiarch-builders-and-package.md | 944 ++++++++++++++++++++ 1 file changed, 944 insertions(+) create mode 100644 text/0000-multiarch-builders-and-package.md diff --git a/text/0000-multiarch-builders-and-package.md b/text/0000-multiarch-builders-and-package.md new file mode 100644 index 000000000..aeaa88d5f --- /dev/null +++ b/text/0000-multiarch-builders-and-package.md @@ -0,0 +1,944 @@ +# Meta +[meta]: #meta +- Name: Multi-arch support for builders and buildpack packages +- Start Date: 2023-09-14 +- Author(s): @jjbustamante +- Status: Draft <!-- Acceptable values: Draft, Approved, On Hold, Superseded --> +- RFC Pull Request: (leave blank) +- CNB Pull Request: (leave blank) +- CNB Issue: (leave blank) +- Supersedes: (put "N/A" unless this replaces an existing RFC, then link to that RFC) + +# Summary +[summary]: #summary + +The problem for adding support for multi-arch buildpacks can be divided into three parts: +1. Support buildpack authors to **migrate their existing buildpacks** to support multi-arch. +2. Support buildpack authors to **create new buildpacks and builders** that handle multi-arch from the beginning. +3. Support application developers to **create application images** using multi-arch buildpacks and builders. + +The purpose of this RFC is to solve the statement 2, adding the capability to the commands: + +- `pack buildpack package` +- `pack builder create` + +to create individuals OCI images artifacts per each os and arch (builders and buildpack packages) and handle the creation for the [image index,](https://github.com/opencontainers/image-spec/blob/master/image-index.md) +that combines them into one single consumable tag for end-users. + +# Definitions +[definitions]: #definitions + +- Buildpack: A buildpack is a set of executables that inspects your app source code and creates a plan to build and run your application. +- Builder: A builder is an image that contains all the components necessary to execute a build. A builder image is created by taking a build image and adding a lifecycle, buildpacks, and files that configure aspects of the build including the buildpack detection order and the location(s) of the run image +- Image Manifest: The image manifest provides a configuration and set of layers for a single container image for a specific architecture and operating system. See [spec](https://github.com/opencontainers/image-spec/blob/main/manifest.md) +- Image Index: The image index is a higher-level manifest which points to specific image manifests, ideal for one or more platforms. See [spec](https://github.com/opencontainers/image-spec/blob/main/image-index.md) + +# Motivation +[motivation]: #motivation + +- Why should we do this? + +The uses of ARM architecture in the cloud and edge computing has been growing rapidly. The CNCF community has been also growing in the last years, and there is a need to support multi-arch for all the projects. The buildpacks community is not an exception, issues like: +- [It would be nice to support easily creating a manifest list packages and builders](https://github.com/buildpacks/pack/issues/1460) +- [Provide a way to specify desired platform when creating packages and builders](https://github.com/buildpacks/pack/issues/1459) +- [Multi arch image build support](https://github.com/buildpacks/pack/issues/1570) + +Or the conversations around this topic in our [slack channel](https://cloud-native.slack.com/archives/C032LNSMY0P), even the [talk at Kubecon NA 2022](https://www.youtube.com/watch?v=Sdr5axlOnDI&list=PLj6h78yzYM2O5aNpRM71NQyx3WUe1xpTn&index=76) demonstrate the interest from the community in this feature. + +- What use cases does it support? + +Currently, buildpack authors can build and package their buildpacks for different OS and Architectures, but when they distribute them the URI for a buildpack can’t disambiguate, +they need to use different tags to differentiate between them. Tools like `docker buildx imagetools create` helps to create an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) to combine them but increasing their build pipelines complexity. +For example, take a look at this recent blog [post](https://deploy-preview-53--elegant-borg-5bd068.netlify.app/blog/steps-we-took-for-a-basic-arm64-support-in-buildpacks) or the [instructions](https://github.com/dmikusa/paketo-arm64/) created from @dmikusa to build an ARM64 builder. + +For those buildpack authors that are using `cross-compile` languages like [go](https://go.dev/) or [rust](https://www.rust-lang.org/) or maybe bash scripts, adding the capability to `pack buildpack package` and `pack builder create` to create multi-arch images +and also handle the creation of an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will simplify their CI/CD pipelines and make the experience more suitable. + +- What is the expected outcome? + +`pack buildpack package` and `pack builder create` commands will be updated in a way that they will handle the creation of multi-arch OCI images + +# What it is +[what-it-is]: #what-it-is + +The end-users for this proposal are **Buildpack authors**, we expect to improve their user experience when creating multi-architecture buildpacks and builders as follows + +## Multi-arch example + +Let's suppose a **Buildpack author** has a `buildpack.toml` created with a content similar to this one: + +```toml +# Buildpack API version +api = "0.12" + +# Buildpack ID and metadata +[buildpack] + id = "examples/my-multiarch-buildpack" + version = "0.0.1" + +# List of targets operating systems, architectures and versions + +[[targets]] +os = "linux" +arch = "amd64" + +[[targets]] +os = "linux" +arch = "arm64" + +[[targets]] +os = "windows" +arch = "amd64" + +[[targets.distributions]] +name = "windows" +versions = ["10.0.20348.1970"] +``` + +And organizes the binaries according to their os/arch with a structure similar to this one: + +```bash +my-multiarch-buildpack +├── buildpack.toml +├── linux-amd64 +│ └── bin +│ ├── build +│ └── detect +├── linux-arm64 +│ └── bin +│ ├── build +│ └── detect +└── windows-amd64 + └── 10.0.20348.1970 + └── bin + ├── build.bat + └── detect.bat +``` + +Now `pack` will be able to package them separately for each os/arch family, following our [guide](https://buildpacks.io/docs/buildpack-author-guide/package-a-buildpack/) +we will need to create a `package.toml` file. + +The `package.toml` file will be similar to the one describe in our documentation: + +```toml +[buildpack] +uri = "examples/my-multiarch-buildpack" +# OR a .tgz with the previous folder structure +uri = "my-multiarch-buildpack.tgz" +``` + +But in this case, we actually **remove** the [platform](https://buildpacks.io/docs/reference/config/package-config/) section because it will be taken from the `buildpack.toml`. + +Packaging a multi-arch buildpack will require the output to be **publish** to a registry or **saved on disk** in OCI layout format. + +```bash +pack buildpack package my-buildpack --config ./package.toml --publish --multi-arch +# Or +pack buildpack package my-buildpack.cnb --config ./package.toml --format file --multi-arch +``` + +In these cases each `target` entry corresponds to a different buildpack image that is exported into an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) + +### Package a multi-arch Builder + +In case of packing a **Builder**, we assume the following premises: + +1. Buildpack authors migrated their `builder.toml` and [remove the stack](https://github.com/buildpacks/pack/issues/1303) concept. +2. Multi-architecture `build`, `run` images and `buildpacks` are available for baking into the **Builder**. + +A sample `builder.toml` file looks like: + +```toml +# Buildpacks to include in builder, these buildpacks MUST be multi-arch and point to Image Index +[[buildpacks]] +uri = "<some uri>" + +[run] +# Runtime images - in case of multi-arch images it must point to Image Index +[[run.images]] +image = "index.docker.io/paketobuildpacks/run-jammy-tiny:latest" + +[build] +# This image is used at build-time, in case of multi-arch images it must point to Image Index +image = "docker.io/paketobuildpacks/build-jammy-tiny:0.2.3" + +[[targets]] +os = "linux" +arch = "amd64" + +[[targets]] +os = "linux" +arch = "arm64" +``` + +As we can see, the proposal is based on the assumption that the `run-image`, `build-image` and `buildpacks` to include +in the builder are **multi-arch artifacts**, and we can reach them by reading an +[image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) + +```bash +pack builder create my-jammy-builder --config ./builder.toml \ + --multi-arch \ + --publish +``` + +In this case, because `targets` are specified and `--multi-arch` is being used `pack` will follow the builder creation process for **each provided platform**, +pulling the correct (based on os/arch) buildpacks, build and run images and creating different builders images that are +exported and combined into an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) + +# How it Works +[how-it-works]: #how-it-works + +## Buildpack Package + +As a quick summary, our current process to create a buildpack package involves: + +- The end-users defined `os` for the OCI image using the [package.toml](https://buildpacks.io/docs/reference/config/package-config/) when they want to export a buildpack package. +- The only values allowed are `linux` and `windows` and by default when is not present, `linux` is being used. +- When exporting to daemon, the `docker.OSType` must be equal to `platform.os` + +### To keep compatibility + +We propose: +- Deprecate the `platform.os` field from [package.toml](https://buildpacks.io/docs/reference/config/package-config/). It will be removed after two pack releases with the new feature +- When `platform.os` is present in [package.toml](https://buildpacks.io/docs/reference/config/package-config/), throw a warning messages indicating the field will be removed +and `--platform` flag must be used +- When `platform.os` is not present [package.toml](https://buildpacks.io/docs/reference/config/package-config/) and `--platform` flag is not used, throw a warning messages indicating +a new `--platform` flag is available +- Keep doing our current process to package a buildpack + +### To improve user experience + +We propose: +- Add a new `--platform` flag with format `[os][/arch][/variant]:[name@version]` to build for a particular target, once the `platform.os` field is removed, +this will be the way for end-users to specify the platform for which they want to create single OCI artifact. +> **Note** +> We want to avoid duplicated information, we expect to have `targets` with all the platform supported by a buildpack + +- Add a new boolean `--multi-arch` flag to indicate pack it must create multiples OCI artifacts and combine them with an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md), +this flag must be used in conjunction with `--publish` or `--format file` flags and error out when `daemon` is selected. +> **Note** +> I got feedback to avoid creating an Image Index if users are not expecting that, the flag is an acknowledgment for creating the index + +- A new folder structure to organize the buildpacks binaries for multi-arch images +```bash +. +├── buildpack.toml +└── {os}-{arch} // optional + └── {variant} // optional + ├── {version-1} // optional + │ └── bin + │ ├── build + │ └── detect + └── {version-2} // optional + └── bin + ├── build + └── detect +``` +> **Note** +> For cross-compile buildpacks like Paketo, it looks easy to add a step to their Makefile to compile and separate the binaries following this structure. + +Based on the [RFC-0096](https://github.com/buildpacks/rfcs/blob/main/text/0096-remove-stacks-mixins.md) we replaced the concept of `stacks` in `buildpack.toml` by a `target` which looks like: + +```toml +[[targets]] +os = "<operating system>" +arch = "<system architecture>" +variant = "<architecture variant>" +[[targets.distributions]] +name = "<distribution ID>" +versions = ["<distribution version>"] +``` +- When `--multi-arch` is enabled + - When `--publish` or `--format file` is specified + - `pack` will read `targets` from `buildpack.toml` + - For each `target` an OCI image will be created, following our current process + - `pack` will try to infer a folder structure similar to the one show above, and if it is found, those are the binaries to include in the OCI image + - If more than 1 OCI image was created, an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them + +### Examples + +Let's use some examples to explain the expected behavior in different use cases + +#### Buildpacks authors do not use targets + +##### `platform.os` is not present at `package.toml` + +This seems to be the case for [Paketo Buildpacks](https://github.com/paketo-buildpacks/java/blob/main/package.toml) +or [Heroku](https://github.com/heroku/buildpacks-jvm/blob/main/meta-buildpacks/java/package.toml). A simplified version of their folder structures is: + +```bash +├── bin +│ ├── build +│ └── detect +├── buildpack.toml +└── package.toml +``` + +In these cases, the expected output will be similar to: + +```bash +pack buildpack package <buildpack> --config ./package.toml --publish +Warning: A new '--platform' flag is available to set the target platform for the buildpack package, using 'linux' as default +Successfully published package <buildpack> and saved to registry + +# Or +pack buildpack package <buildpack> --config ./package.toml --format file +Warning: A new '--platform' flag is available to set the target platform for the buildpack package, using 'linux' as default +Successfully created package <buildpack> and saved to file +``` + +We will keep `linux` as the default platform, and we don't expect end-users to change anything else on their side. + +In case, Buildpack authors tries to use the new folder structure like: + +```bash +├── buildpack.toml +├── linux-amd64 +│ └── bin +│ ├── build +│ └── detect +├── linux-arm64 +│ └── bin +│ ├── build +│ └── detect +└── package.toml +``` + +The current `pack` version creates an OCI artifact copying all the files on it. + +![](https://hackmd.io/_uploads/BkGkZ_mla.png) + +But I think this buildpack can't be executed because `./bin/build` or `./bin/detect` can't be found. We could add some validations and throw an error, +but I do not see any value on doing that. + +> **Important** +> New folder structure is not useful if Buildpack Authors don't remove stacks and migrate to use targets +> + +Trying to use the new flags + +```bash +pack buildpack package <buildpack> --config ./package.toml --publish --multi-arch +Error: 'targets' or 'platforms' must be defined when creating a multi-architecture buildpack + +# Or +pack buildpack package <buildpack> --config ./package.toml --format file --multi-arch +Error: 'targets' or 'platforms' must be defined when creating a multi-architecture buildpack +``` + +In these cases, we don't have enough information to create a multi-arch buildpack, and pack must fail its execution. + +A valid way to re-write the command could be: + +```bash +pack buildpack package <buildpack> --config ./package.toml --publish --platform linux/arm64 --platform linux/amd64 --multi-arch +A multi-arch buildpack package will be created for platforms: 'linux/amd64', 'linux/arm64' +Successfully published package <buildpack> and saved to registry + +# Or +pack buildpack package <buildpack> --config ./package.toml --format file --platform linux/arm64 --platform linux/amd64 --multi-arch +A multi-arch buildpack package will be created for platforms: 'linux/amd64', 'linux/arm64' +Successfully created package <buildpack> and saved to file +``` + +In these cases, two OCI images, with the same binaries, will be created and pushed into the registry, for each image the configuration file will be +created with the correct `os` and `architecture` and an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them + +what about creating a single image for a new platform? + +```bash +pack buildpack package <buildpack> --config ./package.toml --publish --platform linux/arm64 +Successfully published package <buildpack> and saved to registry + +# Or +pack buildpack package <buildpack> --config ./package.toml --format file --platform linux/arm64 +Successfully created package <buildpack> and saved to file +``` + +In these cases, pack will create buildpack package image with the provided binaries and a [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) +with the following platform: + +```json +{ + "architecture": "arm64", + "os": "linux" +} +``` + +##### `platform.os` is present at `package.toml` + +These cases are similar to the previous one, but we can change the warning message. + +```bash +pack buildpack package <buildpack> --config ./package.toml --publish +Warning: 'platform.os' field in package.toml will be deprecated, use new '--platform' flag to set target platform +Successfully published package <buildpack> and saved to registry + +# Or +pack buildpack package <buildpack> --config ./package.toml --format file +Warning: 'platform.os' field in package.toml will be deprecated, use new '--platform' flag to set target platform +Successfully created package <buildpack> and saved to file +``` + +#### Buildpacks authors use targets + +We can divide the problem in two main scenarios: Buildpack authors use or not use the new folder structure. + +Let's start with the first one, which is the natural path for Buildpack Authors to migrate from `stacks` to `targets`. Let's suppose a buildpack folder structure like: + +```bash +├── bin +│ ├── build +│ └── detect +├── buildpack.toml +└── package.toml +``` + +And a `buildpack.toml` with `targets` defined as: + +```toml +[[targets]] +os = "linux" +arch = "amd64" + +[[targets]] +os = "linux" +arch = "arm64" +``` + +How could Buildpack Authors set which `os/arch` to use?, currently `pack` doesn't care about `targets` and +it sets `linux` as the `os` in the final OCI image. We can keep this behavior, and show warning messages to end-users, +this will avoid breaking the current behavior. + +```bash +pack buildpack package <buildpack> --config ./package.toml --publish +Warning: Multiple targets 'linux/amd64', 'linux/arm64' are present at 'buildpack.toml' +Warning: A new '--platform' flag is available to set the target platform for the buildpack package, using 'linux' as default +Successfully published package <buildpack> and saved to registry + +# Or +pack buildpack package <buildpack> --config ./package.toml --format file +Warning: Multiple targets 'linux/amd64', 'linux/arm64' are present at 'buildpack.toml' +Warning: A new '--platform' flag is available to set the target platform for the buildpack package, using 'linux' as default +Successfully created package <buildpack> and saved to file + +# Or +pack buildpack package <buildpack> --config ./package.toml +Warning: Multiple targets 'linux/amd64', 'linux/arm64' are present at 'buildpack.toml' +Warning: A new '--platform' flag is available to set the target platform for the buildpack package, using 'linux' as default +Successfully created package <buildpack> and saved to docker daemon +``` + +The OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) file will have: + +```json +{ + "architecture": "", + "os": "linux" +} +``` + +On the other hand, when end-users use the new `platform` flag + +```bash +pack buildpack package <buildpack> --config ./package.toml --publish --platform linux/arm64 +Successfully published package <buildpack> and saved to registry +``` + +The OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) file will have: + +```json +{ + "architecture": "amd64", + "os": "linux" +} +``` + +Trying to create a buildpack package for an unsupported platform should throw an error + +```bash +pack buildpack package <buildpack> --config ./package.toml --publish --platform windows/arm64 +Error: platform 'windows/arm64' is not supported in buildpack targets, check your 'buildpack.toml' +``` + +Let's go one more step further, and check what will happen if Buildpack Authors use the new `--multi-arch` flag + +```bash +pack buildpack package <buildpack> --config ./package.toml --publish --multi-arch +Info: A multi-arch buildpack package will be created for platforms: 'linux/amd64', 'linux/arm64' +Successfully published package <buildpack> and saved to registry +``` + +In this case, two OCI images will be created and pushed into the registry, for each image the configuration file will be +created with the correct `os` and `architecture` and +an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them, +with a content similar to: + +```json + +{ + "manifests": [ + { + "digest": "sha256:b492494d8e0113c4ad3fe4528a4b5ff89faa5331f7d52c5c138196f69ce176a6", + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "platform": { + "architecture": "amd64", + "os": "linux" + }, + "size": 424 + }, + { + "digest": "sha256:2589fe6bcf90466564741ae0d8309d1323f33b6ec8a5d401a62d0b256bcc3c37", + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "platform": { + "architecture": "arm", + "os": "linux" + }, + "size": 424 + } + ], + "mediaType": "application/vnd.oci.image.index.v1+json", + "schemaVersion": 2 +} +``` +> **Important** +> In this case, the layer blob for the OCI image will have the same bin/build and bin/detect binaries. This could be helpful +> for bash buildpacks for example. + +There is a downside for this case, how can we do it if we have windows and linux scripts? +One way to do it could be just copying the .bat scripts along with the linux scripts, something like: + +```bash +├── bin +│ ├── build +│ ├── build.bat +│ ├── detect +│ └── detect.bat +├── buildpack.toml +└── package.toml +``` + +But we will end up distributing windows and linux scripts together. + +Finally, let's check some examples for the second scenario, when Buildpack Authors migrated from `stacks` to `targets` and +they want to take advantage of the new multi-architecture capabilities, let's use our original folder structure: + +```bash +├── buildpack.toml +├── linux-amd64 +│ └── bin +│ ├── build +│ └── detect +├── linux-arm64 +│ └── bin +│ ├── build +│ └── detect +└── windows-amd64 + └── 10.0.20348.1970 + └── bin + ├── build.bat + └── detect.bat +``` + +And a `buildpack.toml` with the following `targets` defined: + +```toml +[[targets]] +os = "linux" +arch = "amd64" + +[[targets]] +os = "linux" +arch = "arm64" + +[[targets]] +os = "windows" +arch = "amd64" + +[[targets.distributions]] +name = "windows" +versions = ["10.0.20348.1970"] +``` + +If the Buildpack Author wants to create a single buildpack package they will use the `platform` flag + +```bash +pack buildpack package <buildpack> --config ./package.toml --publish --platform linux/arm64 +Successfully published package <buildpack> and saved to registry +``` + +In this case, `pack` will determine the folder `linux-arm64` exists, and that must be the root folder for the buildpack. +`pack` will copy `buildpack.toml` from the root and include it, something like: + +```bash +linux-arm64 +├── bin +│ ├── build +│ └── detect +└── buildpack.toml // Must be copy on the fly +``` + +Similar to previous cases, the OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) file will have: + +```json +{ + "architecture": "arm64", + "os": "linux" +} +``` + +A fully multi-arch buildpack could be created as follows: + +```bash +pack buildpack package <buildpack> --config ./package.toml --publish --multi-arch +Info: A multi-arch buildpack package will be created for platforms: 'linux/amd64', 'linux/arm64', 'windows/amd64' +Successfully published package <buildpack> and saved to registry +``` + +In this case, three OCI images will be created and pushed into the registry, for each image the configuration file will be +created with the correct platform: `os` and `architecture`, +an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them, +with a content similar to: + +```json + +{ + "manifests": [ + { + "digest": "sha256:b492494d8e0113c4ad3fe4528a4b5ff89faa5331f7d52c5c138196f69ce176a6", + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "platform": { + "architecture": "amd64", + "os": "linux" + }, + "size": 424 + }, + { + "digest": "sha256:2589fe6bcf90466564741ae0d8309d1323f33b6ec8a5d401a62d0b256bcc3c37", + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "platform": { + "architecture": "arm", + "os": "linux" + }, + "size": 424 + }, + { + "digest": "sha256:ed1a67bb47f3c35d782293229127ac1f8d64873a131186c49fe079dada0fa7e0", + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "platform": { + "architecture": "amd64", + "os": "windows", + "os.version": "10.0.20348.1970" + }, + "size": 424 + } + ], + "mediaType": "application/vnd.oci.image.index.v1+json", + "schemaVersion": 2 +} +``` + +> **Important** +> In this case, each image has different binaries according to the platform and the new folder structure + +## Builder + +Similar to how we did it for the `buildpack package`, lets summaries, our current process to create a **Builder**: + +- We read the `builder.toml` and fetch the `run.image`, currently we didn't specify the `platform`, **host** `os` is being used. +- We read the `builder.toml` and fetch the `build.image`, currently we didn't specify the `platform`, **host** `os` is being used. +- We create a **base builder** from the `build.image`. +- We read the `os` and `architecture` from the **base builder**, fetch a `lifecycle` image that matches the platform (Note: lifecycle is already publish behind an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md)) +- We add `Buildpacks` and `Extensions` to the **base builder**, because we don't define `architecture` for them, we fetch matching the **base builder** `os` +- More logic and finally the **Builder** image is created + +### To keep compatibility + +We propose: + +- When `stacks` is present in [builder.toml](https://buildpacks.io/docs/reference/config/builder-config/), throw a warning message indicating the field is deprecated and +it will be removed +- When `targets` is not present in [builder.toml](https://buildpacks.io/docs/reference/config/builder-config/), throw a warning messages indicating + a new `--platform` flag is available +- Keep doing our current process to create a builder + +### To improve user experience + +We propose: + +- Add `targets` section to the `builder.toml` schema, this will keep consistency for end-users to understand how to define multi-architecture. The new schema will be +similar to: +```toml +# Buildpacks to include in builder, +# MUST point to an Image Index that matches targets +[[buildpacks]] +uri = "<some uri>" + +[run] +# Runtime images +# MUST point to an Image Index that matches targets +[[run.images]] +image = "<run image reference>" + +[build] +# This image is used at build-time +# MUST point to an Image Index that matches targets +image = "<build image reference>" + +# Platforms to support with the Builder +[[targets]] +os = "<operating system>" +arch = "<system architecture>" +variant = "<architecture variant>" +[[targets.distributions]] +name = "<distribution ID>" +versions = ["<distribution version>"] +``` +- Add a new `--platform` optional flag with format `[os][/arch][/variant]:[name@version]` to create a builder for a particular target, this will help end-users to specify the platform for which they want to create single OCI artifact. +- Add a new boolean `--multi-arch` flag to indicate pack it must create multiples OCI artifacts and combine them with an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md), + this flag must be used in conjunction with `--publish` or `--format file` flags and error out when `daemon` is selected. + +### Examples + +Let's use some examples to explain the expected behavior in different use cases + +#### `Targets` are not present in `builder.toml` + +This is probably the case for most of the Buildpack Authors, for example [Paketo](https://github.com/paketo-buildpacks/builder-jammy-tiny/blob/main/builder.toml), lets suppose a +`buildpack.toml` like: + +```toml +# Buildpacks to include in builder +[[buildpacks]] +uri = "<some buildpacks>" + +# Order used for detection +[[order]] +[[order.group]] +id = "<some order>" +version = "<some version>" + +[stack] +id = "io.buildpacks.samples.stacks.jammy" +build-image = "cnbs/sample-base-build:jammy" +run-image = "cnbs/sample-base-run:jammy" +``` +Or we include `build` and `run` images + +```toml +# Base images used to create the builder +[build] +image = "cnbs/sample-base-build:jammy" +[run] +[[run.images]] +image = "cnbs/sample-base-run:jammy" +``` + +In these cases, the expected output will be similar to: + +```bash +pack builder create <builder> --config ./builder.toml +Warning: "stack" has been deprecated, prefer "targets" instead: https://github.com/buildpacks/rfcs/blob/main/text/0096-remove-stacks-mixins.md +Warning: A new '--platform' flag is available to set the target platform for the builder, using 'linux/amd64' as default +Successfully created builder image <builder> +Tip: Run pack build <image-name> --builder <builder> to use this builder +``` +We expect the command to keep working as today, the builder image will be created but some **warning** messages will be +printed to help end-users to check for new updates, maybe link to a migration guide? + +Trying to use the new flags: + +```bash +pack builder create <builder> --config ./builder.toml --platform linux/arm64 +Warning: "stack" has been deprecated, prefer "targets" instead: https://github.com/buildpacks/rfcs/blob/main/text/0096-remove-stacks-mixins.md +Warning: creating a builder for platform "linux/arm64" but "targets" is not defined, update your "builder.toml" to include "targets" +Successfully created builder image <builder> +Tip: Run pack build <image-name> --builder <builder> to use this builder +``` + +Pulling operations will be configured to use `linux/arm64` as platform, +the OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) file will have: + +```json +{ + "architecture": "arm64", + "os": "linux" +} +``` + +What about multi-architecture builders? + +```bash +pack builder create <builder> --config ./builder.toml --multi-arch --publish +Error: 'targets' or 'platforms' must be defined when creating a multi-architecture builder +``` + +In this case, pack doesn't have enough information to create a multi-arch builder and fail its execution. + +Using `platform` flag: + +```bash +pack builder create <builder> --config ./builder.toml \ + --multi-arch \ + --plaform linux/amd64 \ + --platform linux/arm64 \ + --publish +Successfully created builder image <builder> +Tip: Run pack build <image-name> --builder <builder> to use this builder +``` + +In this case, two OCI images will be created and pushed into the registry, for each image the configuration file will be +created with the correct platform: `os` and `architecture`, +an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them + +#### `Targets` are present in `builder.toml` + +Let's suppose a `builder.toml` similar to this one: + +```toml +[[buildpacks]] +id = "samples/java-maven" +version = "0.0.1" +uri = "<some uri>" + +[[order]] +[[order.group]] +id = "samples/java-maven" +version = "0.0.1" + +[build] +image = "cnbs/sample-base-build:jammy" +[run] +[[run.images]] +image = "cnbs/sample-base-run:jammy" + +[[targets]] +os = "linux" +arch = "amd64" + +[[targets]] +os = "linux" +arch = "arm64" +``` + +Let's suppose we execute the command in a host "linux/amd64" machine + +```bash +pack builder create <builder> --config ./builder.toml +Info: creating a builder for platform "linux/amd64" +Successfully created builder image <builder> +Tip: Run pack build <image-name> --builder <builder> to use this builder +``` + +`platform` flag is not defined, we keep our current behavior and detect the host `os` and `architecture`. Because a +`target` matches the host `platform` it is used to create the builder. + +Trying to use the new flags: + +```bash +pack builder create <builder> --config ./builder.toml --platform linux/arm64 +Info: creating a builder for platform "linux/arm64" +Successfully created builder image <builder> +Tip: Run pack build <image-name> --builder <builder> to use this builder +``` + +Pulling operations will be configured to use `linux/arm64` as platform, +the OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) file will have: + +```json +{ + "architecture": "arm64", + "os": "linux" +} +``` + +What about multi-architecture builders? + +```bash +pack builder create <builder> --config ./builder.toml --multi-arch --publish +Info: A multi-arch builder will be created for platforms: 'linux/amd64', 'linux/arm64' +Successfully created builder image <builder> +Tip: Run pack build <image-name> --builder <builder> to use this builder +``` + + +Using `platform` flag: + +```bash +pack builder create <builder> --config ./builder.toml \ + --multi-arch \ + --plaform linux/amd64 \ + --platform linux/arm64 \ + --publish +Info: A multi-arch builder will be created for platforms: 'linux/amd64', 'linux/arm64' +Successfully created builder image <builder> +Tip: Run pack build <image-name> --builder <builder> to use this builder +``` + +In this case, two OCI images will be created and pushed into the registry, for each image the configuration file will be +created with the correct platform: `os` and `architecture`, +an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them + + +# Migration +[migration]: #migration + +1. Align with the Stack removal [plan](https://docs.google.com/document/d/1bExpr31U5R5yQ6fncpl5YcdosWVwYcXgkt12vE-lpvU/edit) +2. Deprecate the `platform.os` field from [package.toml](https://buildpacks.io/docs/reference/config/package-config/) + - We don't want to break current behavior, but we do want community migrate to the new approach +3. Update docs to explain the new functionality, blog posts or any other useful media communicate the message +4. Remove `platform.os` support on `pack` + +# Drawbacks +[drawbacks]: #drawbacks + +- New complexity will be added into `pack` + +# Alternatives +[alternatives]: #alternatives + +- Do nothing, Buildpack Authors can keep using other tools like`docker buildx imagetools create` or `crane` to update the `architecture` in their Manifest files or +create [image indexes](https://github.com/opencontainers/image-spec/blob/master/image-index.md). +- Do not deprecate `platform.os` field from [package.toml](https://buildpacks.io/docs/reference/config/package-config/) and add more fields to get the same result, instead of flags + - I didn't explore this idea + +# Prior Art +[prior-art]: #prior-art + +- Stack Removal [RFC #096](https://github.com/buildpacks/rfcs/blob/jjbustamante/feature/multi-arch-phase-2/text/0096-remove-stacks-mixins.md) +- This RFC is a continuation of the work started with the proposal to add commands to handle manifest list in pack, see the [RFC](https://github.com/buildpacks/rfcs/pull/283) +- Paketo [RFC #288](https://github.com/paketo-buildpacks/rfcs/pull/288) to publish multi-arch buildpacks + +# Unresolved Questions +[unresolved-questions]: #unresolved-questions + +- If I already have an [image indexe](https://github.com/opencontainers/image-spec/blob/master/image-index.md) created and I want to add support for new plaform, how do I do it? +- What are the intermediate images for each platform named/called? +- What happen if I want to exclude some buildpack for a particular target? +- What happen if I want to include the same file or folder for every image, do I have to copy then inside the {os}-{arch} folder? + +# Spec. Changes (OPTIONAL) +[spec-changes]: #spec-changes + +NA + +# History +[history]: #history + +<!-- +## Amended +### Meta +[meta-1]: #meta-1 +- Name: (fill in the amendment name: Variable Rename) +- Start Date: (fill in today's date: YYYY-MM-DD) +- Author(s): (Github usernames) +- Amendment Pull Request: (leave blank) + +### Summary + +A brief description of the changes. + +### Motivation + +Why was this amendment necessary? +---> From af7811b6b0dc3e0b42be181b9f922b8c2e1ef706 Mon Sep 17 00:00:00 2001 From: Juan Bustamante <jbustamante@vmware.com> Date: Tue, 7 Nov 2023 15:58:00 -0500 Subject: [PATCH 11/34] Change flag --platform to use --target, and adding a field to override the path for binaries in buildpack.toml Signed-off-by: Juan Bustamante <jbustamante@vmware.com> --- text/0000-multiarch-builders-and-package.md | 236 +++++++++++--------- 1 file changed, 135 insertions(+), 101 deletions(-) diff --git a/text/0000-multiarch-builders-and-package.md b/text/0000-multiarch-builders-and-package.md index aeaa88d5f..eb5348395 100644 --- a/text/0000-multiarch-builders-and-package.md +++ b/text/0000-multiarch-builders-and-package.md @@ -65,7 +65,7 @@ The end-users for this proposal are **Buildpack authors**, we expect to improve ## Multi-arch example -Let's suppose a **Buildpack author** has a `buildpack.toml` created with a content similar to this one: +Let's suppose a **Buildpack author** has a `buildpack.toml` updated to include `targets` as follows: ```toml # Buildpack API version @@ -93,26 +93,33 @@ arch = "amd64" [[targets.distributions]] name = "windows" versions = ["10.0.20348.1970"] + +# Stacks (deprecated) the buildpack will work with +[[stacks]] +id = "*" ``` And organizes the binaries according to their os/arch with a structure similar to this one: ```bash my-multiarch-buildpack +. ├── buildpack.toml -├── linux-amd64 -│ └── bin -│ ├── build -│ └── detect -├── linux-arm64 -│ └── bin -│ ├── build -│ └── detect -└── windows-amd64 - └── 10.0.20348.1970 - └── bin - ├── build.bat - └── detect.bat +├── linux +│ ├── amd64 +│ │ └── bin +│ │ ├── build +│ │ └── detect +│ └── arm64 +│ └── bin +│ ├── build +│ └── detect +└── windows + └── amd64 + └── windows@10.0.20348.1970 + └── bin + ├── build.bat + └── detect.bat ``` Now `pack` will be able to package them separately for each os/arch family, following our [guide](https://buildpacks.io/docs/buildpack-author-guide/package-a-buildpack/) @@ -132,18 +139,21 @@ But in this case, we actually **remove** the [platform](https://buildpacks.io/do Packaging a multi-arch buildpack will require the output to be **publish** to a registry or **saved on disk** in OCI layout format. ```bash -pack buildpack package my-buildpack --config ./package.toml --publish --multi-arch +pack buildpack package my-buildpack --config ./package.toml --publish # Or -pack buildpack package my-buildpack.cnb --config ./package.toml --format file --multi-arch +pack buildpack package my-buildpack.cnb --config ./package.toml --format file ``` +> **Important** +> pack will determine a multi-arch buildpack package is being created because there are more than one target defined. + In these cases each `target` entry corresponds to a different buildpack image that is exported into an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) ### Package a multi-arch Builder In case of packing a **Builder**, we assume the following premises: -1. Buildpack authors migrated their `builder.toml` and [remove the stack](https://github.com/buildpacks/pack/issues/1303) concept. +1. Buildpack authors updated their `builder.toml` to include the new `targets` fields defined in this RFC. 2. Multi-architecture `build`, `run` images and `buildpacks` are available for baking into the **Builder**. A sample `builder.toml` file looks like: @@ -169,6 +179,14 @@ arch = "amd64" [[targets]] os = "linux" arch = "arm64" + +# Stack (deprecated) +[stack] +id = "io.buildpacks.stacks.jammy.tiny" +# This image is used at build-time +build-image = "docker.io/paketobuildpacks/build-jammy-tiny:0.2.3" +# This image is used at runtime +run-image = "index.docker.io/paketobuildpacks/run-jammy-tiny:latest" ``` As we can see, the proposal is based on the assumption that the `run-image`, `build-image` and `buildpacks` to include @@ -176,12 +194,12 @@ in the builder are **multi-arch artifacts**, and we can reach them by reading an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) ```bash -pack builder create my-jammy-builder --config ./builder.toml \ - --multi-arch \ - --publish +pack builder create my-jammy-builder --config ./builder.toml --publish ``` +> **Important** +> Similar to the `buildpack package`, pack will determine a multi-arch builder must be created based on the multiple targets defined. -In this case, because `targets` are specified and `--multi-arch` is being used `pack` will follow the builder creation process for **each provided platform**, +In this case `pack` will follow the builder creation process for **each provided target**, pulling the correct (based on os/arch) buildpacks, build and run images and creating different builders images that are exported and combined into an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) @@ -201,58 +219,74 @@ As a quick summary, our current process to create a buildpack package involves: We propose: - Deprecate the `platform.os` field from [package.toml](https://buildpacks.io/docs/reference/config/package-config/). It will be removed after two pack releases with the new feature - When `platform.os` is present in [package.toml](https://buildpacks.io/docs/reference/config/package-config/), throw a warning messages indicating the field will be removed -and `--platform` flag must be used -- When `platform.os` is not present [package.toml](https://buildpacks.io/docs/reference/config/package-config/) and `--platform` flag is not used, throw a warning messages indicating -a new `--platform` flag is available +and `--target` flag must be used +- When `platform.os` is not present [package.toml](https://buildpacks.io/docs/reference/config/package-config/) and `--target` flag is not used, throw a warning messages indicating +a new `--target` flag is available - Keep doing our current process to package a buildpack ### To improve user experience We propose: -- Add a new `--platform` flag with format `[os][/arch][/variant]:[name@version]` to build for a particular target, once the `platform.os` field is removed, +- Add a new `--target` flag with format `[os][/arch][/variant]:[name@version]` to build for a particular target, once the `platform.os` field is removed, this will be the way for end-users to specify the platform for which they want to create single OCI artifact. > **Note** > We want to avoid duplicated information, we expect to have `targets` with all the platform supported by a buildpack -- Add a new boolean `--multi-arch` flag to indicate pack it must create multiples OCI artifacts and combine them with an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md), -this flag must be used in conjunction with `--publish` or `--format file` flags and error out when `daemon` is selected. -> **Note** -> I got feedback to avoid creating an Image Index if users are not expecting that, the flag is an acknowledgment for creating the index - - A new folder structure to organize the buildpacks binaries for multi-arch images ```bash +# Option 1 - no variant is required . ├── buildpack.toml -└── {os}-{arch} // optional - └── {variant} // optional - ├── {version-1} // optional - │ └── bin - │ ├── build - │ └── detect - └── {version-2} // optional - └── bin - ├── build - └── detect +└── {os} // optional + └── {arch} // optional + └── bin + ├── build + └── detect + +# Option 2 - variant is required +. +├── buildpack.toml +└── {os} // optional + └── {arch} // optional + └── {variant} // optional + ├── {name@version-1} // optional + │ └── bin + │ ├── build + │ └── detect + └── {name@version-2} // optional + └── bin + ├── build + └── detect ``` > **Note** > For cross-compile buildpacks like Paketo, it looks easy to add a step to their Makefile to compile and separate the binaries following this structure. -Based on the [RFC-0096](https://github.com/buildpacks/rfcs/blob/main/text/0096-remove-stacks-mixins.md) we replaced the concept of `stacks` in `buildpack.toml` by a `target` which looks like: +In case, this folder structure is not suitable for Buildpack Authors: + +> **Proposal** +> a new `path` attribute is proposed to be included into the `target` section of the `buildpack.toml` to specify +where the binaries are located in the filesystem. + +Based on the [RFC-0096](https://github.com/buildpacks/rfcs/blob/main/text/0096-remove-stacks-mixins.md) the new `buildpack.toml` schema will look like this: ```toml [[targets]] os = "<operating system>" arch = "<system architecture>" variant = "<architecture variant>" + +# optional +path = "<path to look for the binaries if the folder structure convention is not followed>" + [[targets.distributions]] name = "<distribution ID>" versions = ["<distribution version>"] ``` -- When `--multi-arch` is enabled +- When `more than 1 target is defined` - When `--publish` or `--format file` is specified - - `pack` will read `targets` from `buildpack.toml` - For each `target` an OCI image will be created, following our current process - - `pack` will try to infer a folder structure similar to the one show above, and if it is found, those are the binaries to include in the OCI image + - `pack` will determine the binaries path (based on the `targets.path` in the buildpack.toml or infering a folder structure similar to the one show above) + - `pack` will include the binaries in the buildpack package OCI image - If more than 1 OCI image was created, an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them ### Examples @@ -278,16 +312,16 @@ In these cases, the expected output will be similar to: ```bash pack buildpack package <buildpack> --config ./package.toml --publish -Warning: A new '--platform' flag is available to set the target platform for the buildpack package, using 'linux' as default +Warning: A new '--target' flag is available to set the platform for the buildpack package, using 'linux' as default Successfully published package <buildpack> and saved to registry # Or pack buildpack package <buildpack> --config ./package.toml --format file -Warning: A new '--platform' flag is available to set the target platform for the buildpack package, using 'linux' as default +Warning: A new '--target' flag is available to set the platform for the buildpack package, using 'linux' as default Successfully created package <buildpack> and saved to file ``` -We will keep `linux` as the default platform, and we don't expect end-users to change anything else on their side. +We will keep `linux` as the default target platform, and we don't expect end-users to change anything else on their side. In case, Buildpack authors tries to use the new folder structure like: @@ -308,8 +342,7 @@ The current `pack` version creates an OCI artifact copying all the files on it. ![](https://hackmd.io/_uploads/BkGkZ_mla.png) -But I think this buildpack can't be executed because `./bin/build` or `./bin/detect` can't be found. We could add some validations and throw an error, -but I do not see any value on doing that. +But I think this buildpack can't be executed because `./bin/build` or `./bin/detect` can't be found. We could add some validations and throw an error, but I do not see any value on doing that. > **Important** > New folder structure is not useful if Buildpack Authors don't remove stacks and migrate to use targets @@ -319,11 +352,11 @@ Trying to use the new flags ```bash pack buildpack package <buildpack> --config ./package.toml --publish --multi-arch -Error: 'targets' or 'platforms' must be defined when creating a multi-architecture buildpack +Error: 'targets' must be defined when creating a multi-architecture buildpack # Or pack buildpack package <buildpack> --config ./package.toml --format file --multi-arch -Error: 'targets' or 'platforms' must be defined when creating a multi-architecture buildpack +Error: 'targets' must be defined when creating a multi-architecture buildpack ``` In these cases, we don't have enough information to create a multi-arch buildpack, and pack must fail its execution. @@ -331,32 +364,32 @@ In these cases, we don't have enough information to create a multi-arch buildpac A valid way to re-write the command could be: ```bash -pack buildpack package <buildpack> --config ./package.toml --publish --platform linux/arm64 --platform linux/amd64 --multi-arch -A multi-arch buildpack package will be created for platforms: 'linux/amd64', 'linux/arm64' +pack buildpack package <buildpack> --config ./package.toml --publish --target linux/arm64 --target linux/amd64 --multi-arch +A multi-arch buildpack package will be created for target platforms: 'linux/amd64', 'linux/arm64' Successfully published package <buildpack> and saved to registry # Or -pack buildpack package <buildpack> --config ./package.toml --format file --platform linux/arm64 --platform linux/amd64 --multi-arch -A multi-arch buildpack package will be created for platforms: 'linux/amd64', 'linux/arm64' +pack buildpack package <buildpack> --config ./package.toml --format file --target linux/arm64 --target linux/amd64 --multi-arch +A multi-arch buildpack package will be created for target platforms: 'linux/amd64', 'linux/arm64' Successfully created package <buildpack> and saved to file ``` In these cases, two OCI images, with the same binaries, will be created and pushed into the registry, for each image the configuration file will be created with the correct `os` and `architecture` and an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them -what about creating a single image for a new platform? +what about creating a single image for a new target platform? ```bash -pack buildpack package <buildpack> --config ./package.toml --publish --platform linux/arm64 +pack buildpack package <buildpack> --config ./package.toml --publish --target linux/arm64 Successfully published package <buildpack> and saved to registry # Or -pack buildpack package <buildpack> --config ./package.toml --format file --platform linux/arm64 +pack buildpack package <buildpack> --config ./package.toml --format file --target linux/arm64 Successfully created package <buildpack> and saved to file ``` In these cases, pack will create buildpack package image with the provided binaries and a [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) -with the following platform: +with the following target platform: ```json { @@ -371,12 +404,12 @@ These cases are similar to the previous one, but we can change the warning messa ```bash pack buildpack package <buildpack> --config ./package.toml --publish -Warning: 'platform.os' field in package.toml will be deprecated, use new '--platform' flag to set target platform +Warning: 'platform.os' field in package.toml will be deprecated, use new '--target' flag to set target platform Successfully published package <buildpack> and saved to registry # Or pack buildpack package <buildpack> --config ./package.toml --format file -Warning: 'platform.os' field in package.toml will be deprecated, use new '--platform' flag to set target platform +Warning: 'platform.os' field in package.toml will be deprecated, use new '--target' flag to set target platform Successfully created package <buildpack> and saved to file ``` @@ -413,19 +446,19 @@ this will avoid breaking the current behavior. ```bash pack buildpack package <buildpack> --config ./package.toml --publish Warning: Multiple targets 'linux/amd64', 'linux/arm64' are present at 'buildpack.toml' -Warning: A new '--platform' flag is available to set the target platform for the buildpack package, using 'linux' as default +Warning: A new '--target' flag is available to set the target platform for the buildpack package, using 'linux' as default Successfully published package <buildpack> and saved to registry # Or pack buildpack package <buildpack> --config ./package.toml --format file Warning: Multiple targets 'linux/amd64', 'linux/arm64' are present at 'buildpack.toml' -Warning: A new '--platform' flag is available to set the target platform for the buildpack package, using 'linux' as default +Warning: A new '--target' flag is available to set the target platform for the buildpack package, using 'linux' as default Successfully created package <buildpack> and saved to file # Or pack buildpack package <buildpack> --config ./package.toml Warning: Multiple targets 'linux/amd64', 'linux/arm64' are present at 'buildpack.toml' -Warning: A new '--platform' flag is available to set the target platform for the buildpack package, using 'linux' as default +Warning: A new '--target' flag is available to set the target platform for the buildpack package, using 'linux' as default Successfully created package <buildpack> and saved to docker daemon ``` @@ -438,10 +471,10 @@ The OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/ } ``` -On the other hand, when end-users use the new `platform` flag +On the other hand, when end-users use the new `target` flag ```bash -pack buildpack package <buildpack> --config ./package.toml --publish --platform linux/arm64 +pack buildpack package <buildpack> --config ./package.toml --publish --target linux/arm64 Successfully published package <buildpack> and saved to registry ``` @@ -457,15 +490,15 @@ The OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/ Trying to create a buildpack package for an unsupported platform should throw an error ```bash -pack buildpack package <buildpack> --config ./package.toml --publish --platform windows/arm64 -Error: platform 'windows/arm64' is not supported in buildpack targets, check your 'buildpack.toml' +pack buildpack package <buildpack> --config ./package.toml --publish --target windows/arm64 +Error: target platform 'windows/arm64' is not supported in buildpack targets, check your 'buildpack.toml' ``` Let's go one more step further, and check what will happen if Buildpack Authors use the new `--multi-arch` flag ```bash pack buildpack package <buildpack> --config ./package.toml --publish --multi-arch -Info: A multi-arch buildpack package will be created for platforms: 'linux/amd64', 'linux/arm64' +Info: A multi-arch buildpack package will be created for targets platforms: 'linux/amd64', 'linux/arm64' Successfully published package <buildpack> and saved to registry ``` @@ -560,10 +593,10 @@ name = "windows" versions = ["10.0.20348.1970"] ``` -If the Buildpack Author wants to create a single buildpack package they will use the `platform` flag +If the Buildpack Author wants to create a single buildpack package they will use the `target` flag ```bash -pack buildpack package <buildpack> --config ./package.toml --publish --platform linux/arm64 +pack buildpack package <buildpack> --config ./package.toml --publish --target linux/arm64 Successfully published package <buildpack> and saved to registry ``` @@ -591,12 +624,12 @@ A fully multi-arch buildpack could be created as follows: ```bash pack buildpack package <buildpack> --config ./package.toml --publish --multi-arch -Info: A multi-arch buildpack package will be created for platforms: 'linux/amd64', 'linux/arm64', 'windows/amd64' +Info: A multi-arch buildpack package will be created for target platforms: 'linux/amd64', 'linux/arm64', 'windows/amd64' Successfully published package <buildpack> and saved to registry ``` In this case, three OCI images will be created and pushed into the registry, for each image the configuration file will be -created with the correct platform: `os` and `architecture`, +created with the correct target: `os` and `architecture`, an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them, with a content similar to: @@ -639,17 +672,18 @@ with a content similar to: ``` > **Important** -> In this case, each image has different binaries according to the platform and the new folder structure +> In this case, each image has different binaries according to the target platform and the new folder structure ## Builder Similar to how we did it for the `buildpack package`, lets summaries, our current process to create a **Builder**: -- We read the `builder.toml` and fetch the `run.image`, currently we didn't specify the `platform`, **host** `os` is being used. -- We read the `builder.toml` and fetch the `build.image`, currently we didn't specify the `platform`, **host** `os` is being used. +- We read the `builder.toml` and fetch the `build.image`, currently we didn't specify the `platform`, **daemon** `os/arch` is being used. - We create a **base builder** from the `build.image`. -- We read the `os` and `architecture` from the **base builder**, fetch a `lifecycle` image that matches the platform (Note: lifecycle is already publish behind an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md)) -- We add `Buildpacks` and `Extensions` to the **base builder**, because we don't define `architecture` for them, we fetch matching the **base builder** `os` +- We read the `os` and `architecture` from the **base builder** + - Fetch the `run.image`, matching the `os/arch` with the values from the **base builder** + - Fetch the `lifecycle` image that matches the platform (Note: lifecycle is already publish behind an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md)) + - We add `Buildpacks` and `Extensions` to the **base builder** trying to match the **base builder** `os/arch`, in case the `architecture` doesn't match, we fall back to match the **base builder** `os` - More logic and finally the **Builder** image is created ### To keep compatibility @@ -659,7 +693,7 @@ We propose: - When `stacks` is present in [builder.toml](https://buildpacks.io/docs/reference/config/builder-config/), throw a warning message indicating the field is deprecated and it will be removed - When `targets` is not present in [builder.toml](https://buildpacks.io/docs/reference/config/builder-config/), throw a warning messages indicating - a new `--platform` flag is available + a new `--target` flag is available - Keep doing our current process to create a builder ### To improve user experience @@ -685,7 +719,7 @@ image = "<run image reference>" # MUST point to an Image Index that matches targets image = "<build image reference>" -# Platforms to support with the Builder +# Target platforms to support with the Builder [[targets]] os = "<operating system>" arch = "<system architecture>" @@ -694,7 +728,7 @@ variant = "<architecture variant>" name = "<distribution ID>" versions = ["<distribution version>"] ``` -- Add a new `--platform` optional flag with format `[os][/arch][/variant]:[name@version]` to create a builder for a particular target, this will help end-users to specify the platform for which they want to create single OCI artifact. +- Add a new `--target` optional flag with format `[os][/arch][/variant]:[name@version]` to create a builder for a particular target, this will help end-users to specify the platform for which they want to create single OCI artifact. - Add a new boolean `--multi-arch` flag to indicate pack it must create multiples OCI artifacts and combine them with an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md), this flag must be used in conjunction with `--publish` or `--format file` flags and error out when `daemon` is selected. @@ -739,7 +773,7 @@ In these cases, the expected output will be similar to: ```bash pack builder create <builder> --config ./builder.toml Warning: "stack" has been deprecated, prefer "targets" instead: https://github.com/buildpacks/rfcs/blob/main/text/0096-remove-stacks-mixins.md -Warning: A new '--platform' flag is available to set the target platform for the builder, using 'linux/amd64' as default +Warning: A new '--target' flag is available to set the target platform for the builder, using 'linux/amd64' as default Successfully created builder image <builder> Tip: Run pack build <image-name> --builder <builder> to use this builder ``` @@ -749,14 +783,14 @@ printed to help end-users to check for new updates, maybe link to a migration gu Trying to use the new flags: ```bash -pack builder create <builder> --config ./builder.toml --platform linux/arm64 +pack builder create <builder> --config ./builder.toml --target linux/arm64 Warning: "stack" has been deprecated, prefer "targets" instead: https://github.com/buildpacks/rfcs/blob/main/text/0096-remove-stacks-mixins.md Warning: creating a builder for platform "linux/arm64" but "targets" is not defined, update your "builder.toml" to include "targets" Successfully created builder image <builder> Tip: Run pack build <image-name> --builder <builder> to use this builder ``` -Pulling operations will be configured to use `linux/arm64` as platform, +Pulling operations will be configured to use `linux/arm64` as target platform, the OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) file will have: ```json @@ -770,25 +804,25 @@ What about multi-architecture builders? ```bash pack builder create <builder> --config ./builder.toml --multi-arch --publish -Error: 'targets' or 'platforms' must be defined when creating a multi-architecture builder +Error: 'targets' must be defined when creating a multi-architecture builder ``` In this case, pack doesn't have enough information to create a multi-arch builder and fail its execution. -Using `platform` flag: +Using `target` flag: ```bash pack builder create <builder> --config ./builder.toml \ --multi-arch \ - --plaform linux/amd64 \ - --platform linux/arm64 \ + --target linux/amd64 \ + --target linux/arm64 \ --publish Successfully created builder image <builder> Tip: Run pack build <image-name> --builder <builder> to use this builder ``` In this case, two OCI images will be created and pushed into the registry, for each image the configuration file will be -created with the correct platform: `os` and `architecture`, +created with the correct target: `os` and `architecture`, an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them #### `Targets` are present in `builder.toml` @@ -825,24 +859,24 @@ Let's suppose we execute the command in a host "linux/amd64" machine ```bash pack builder create <builder> --config ./builder.toml -Info: creating a builder for platform "linux/amd64" +Info: creating a builder for target "linux/amd64" Successfully created builder image <builder> Tip: Run pack build <image-name> --builder <builder> to use this builder ``` -`platform` flag is not defined, we keep our current behavior and detect the host `os` and `architecture`. Because a +`target` flag is not defined, we keep our current behavior and detect the host `os` and `architecture`. Because a `target` matches the host `platform` it is used to create the builder. Trying to use the new flags: ```bash -pack builder create <builder> --config ./builder.toml --platform linux/arm64 -Info: creating a builder for platform "linux/arm64" +pack builder create <builder> --config ./builder.toml --target linux/arm64 +Info: creating a builder for target "linux/arm64" Successfully created builder image <builder> Tip: Run pack build <image-name> --builder <builder> to use this builder ``` -Pulling operations will be configured to use `linux/arm64` as platform, +Pulling operations will be configured to use `linux/arm64` as target platform, the OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) file will have: ```json @@ -856,27 +890,27 @@ What about multi-architecture builders? ```bash pack builder create <builder> --config ./builder.toml --multi-arch --publish -Info: A multi-arch builder will be created for platforms: 'linux/amd64', 'linux/arm64' +Info: A multi-arch builder will be created for targets platform: 'linux/amd64', 'linux/arm64' Successfully created builder image <builder> Tip: Run pack build <image-name> --builder <builder> to use this builder ``` -Using `platform` flag: +Using `target` flag: ```bash pack builder create <builder> --config ./builder.toml \ --multi-arch \ - --plaform linux/amd64 \ - --platform linux/arm64 \ + --target linux/amd64 \ + --target linux/arm64 \ --publish -Info: A multi-arch builder will be created for platforms: 'linux/amd64', 'linux/arm64' +Info: A multi-arch builder will be created for targets platform: 'linux/amd64', 'linux/arm64' Successfully created builder image <builder> Tip: Run pack build <image-name> --builder <builder> to use this builder ``` In this case, two OCI images will be created and pushed into the registry, for each image the configuration file will be -created with the correct platform: `os` and `architecture`, +created with the correct target platform: `os` and `architecture`, an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them @@ -913,7 +947,7 @@ create [image indexes](https://github.com/opencontainers/image-spec/blob/master/ [unresolved-questions]: #unresolved-questions - If I already have an [image indexe](https://github.com/opencontainers/image-spec/blob/master/image-index.md) created and I want to add support for new plaform, how do I do it? -- What are the intermediate images for each platform named/called? +- What are the intermediate images for each target named/called? - What happen if I want to exclude some buildpack for a particular target? - What happen if I want to include the same file or folder for every image, do I have to copy then inside the {os}-{arch} folder? From d4ba0baf2dc9afaf2a39a924b2c3cb5351720d4e Mon Sep 17 00:00:00 2001 From: Juan Bustamante <jbustamante@vmware.com> Date: Fri, 10 Nov 2023 16:02:16 -0500 Subject: [PATCH 12/34] fixing some feedback from review, removing --multi-arch flag Signed-off-by: Juan Bustamante <jbustamante@vmware.com> --- text/0000-multiarch-builders-and-package.md | 316 ++++++++++---------- 1 file changed, 158 insertions(+), 158 deletions(-) diff --git a/text/0000-multiarch-builders-and-package.md b/text/0000-multiarch-builders-and-package.md index eb5348395..a56145423 100644 --- a/text/0000-multiarch-builders-and-package.md +++ b/text/0000-multiarch-builders-and-package.md @@ -122,10 +122,10 @@ my-multiarch-buildpack └── detect.bat ``` -Now `pack` will be able to package them separately for each os/arch family, following our [guide](https://buildpacks.io/docs/buildpack-author-guide/package-a-buildpack/) -we will need to create a `package.toml` file. +Now `pack` will be able to package them separately for each os/arch family. -The `package.toml` file will be similar to the one describe in our documentation: +Following our [guide](https://buildpacks.io/docs/buildpack-author-guide/package-a-buildpack/) we will need to create a +`package.toml` let's suppose it looks like this: ```toml [buildpack] @@ -134,7 +134,7 @@ uri = "examples/my-multiarch-buildpack" uri = "my-multiarch-buildpack.tgz" ``` -But in this case, we actually **remove** the [platform](https://buildpacks.io/docs/reference/config/package-config/) section because it will be taken from the `buildpack.toml`. +In this case we **remove** the [platform](https://buildpacks.io/docs/reference/config/package-config/) section because it will be taken from the `buildpack.toml`. Packaging a multi-arch buildpack will require the output to be **publish** to a registry or **saved on disk** in OCI layout format. @@ -147,13 +147,13 @@ pack buildpack package my-buildpack.cnb --config ./package.toml --format file > **Important** > pack will determine a multi-arch buildpack package is being created because there are more than one target defined. -In these cases each `target` entry corresponds to a different buildpack image that is exported into an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) +Each `target` entry corresponds to a different buildpack image that is exported into an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) ### Package a multi-arch Builder In case of packing a **Builder**, we assume the following premises: -1. Buildpack authors updated their `builder.toml` to include the new `targets` fields defined in this RFC. +1. Buildpack authors updated their `builder.toml` to include the new `targets` fields defined in this [RFC](https://github.com/buildpacks/rfcs/blob/main/text/0096-remove-stacks-mixins.md). 2. Multi-architecture `build`, `run` images and `buildpacks` are available for baking into the **Builder**. A sample `builder.toml` file looks like: @@ -193,11 +193,13 @@ As we can see, the proposal is based on the assumption that the `run-image`, `bu in the builder are **multi-arch artifacts**, and we can reach them by reading an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) +Packaging a multi-arch builder will require the output to be **publish** to a registry. + ```bash pack builder create my-jammy-builder --config ./builder.toml --publish ``` > **Important** -> Similar to the `buildpack package`, pack will determine a multi-arch builder must be created based on the multiple targets defined. +> Similar to the `buildpack package,` pack will determine a multi-arch builder must be created based on the multiple targets defined. In this case `pack` will follow the builder creation process for **each provided target**, pulling the correct (based on os/arch) buildpacks, build and run images and creating different builders images that are @@ -210,7 +212,7 @@ exported and combined into an [image index](https://github.com/opencontainers/im As a quick summary, our current process to create a buildpack package involves: -- The end-users defined `os` for the OCI image using the [package.toml](https://buildpacks.io/docs/reference/config/package-config/) when they want to export a buildpack package. +- The end-users defined `os` for the OCI image using the [package.toml](https://buildpacks.io/docs/reference/config/package-config/). - The only values allowed are `linux` and `windows` and by default when is not present, `linux` is being used. - When exporting to daemon, the `docker.OSType` must be equal to `platform.os` @@ -232,6 +234,8 @@ this will be the way for end-users to specify the platform for which they want t > **Note** > We want to avoid duplicated information, we expect to have `targets` with all the platform supported by a buildpack +- Add `targets` section to `buildpack.toml` to help Buildpack Authors to include support for new platforms without having to update their `pack buildpack package` command in their CI/CD pipelines + - A new folder structure to organize the buildpacks binaries for multi-arch images ```bash # Option 1 - no variant is required @@ -259,7 +263,8 @@ this will be the way for end-users to specify the platform for which they want t └── detect ``` > **Note** -> For cross-compile buildpacks like Paketo, it looks easy to add a step to their Makefile to compile and separate the binaries following this structure. +> For cross-compile buildpacks like Paketo, it looks easy to add a step to their Makefile to compile and separate the binaries following this structure. It is important to mention +> that the final buildpack image will not change, this will only change the buildpack structure from `pack` perspective In case, this folder structure is not suitable for Buildpack Authors: @@ -288,17 +293,20 @@ versions = ["<distribution version>"] - `pack` will determine the binaries path (based on the `targets.path` in the buildpack.toml or infering a folder structure similar to the one show above) - `pack` will include the binaries in the buildpack package OCI image - If more than 1 OCI image was created, an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them + - When `--daemon` is specified + - `pack` can keep using `docker.OSType` to determine the target `os` and probably can do some validations it the `os` is valid target ### Examples Let's use some examples to explain the expected behavior in different use cases -#### Buildpacks authors do not use targets - -##### `platform.os` is not present at `package.toml` +#### Buildpacks authors do not use targets AND `platform.os` is not present at `package.toml` This seems to be the case for [Paketo Buildpacks](https://github.com/paketo-buildpacks/java/blob/main/package.toml) -or [Heroku](https://github.com/heroku/buildpacks-jvm/blob/main/meta-buildpacks/java/package.toml). A simplified version of their folder structures is: +or [Heroku](https://github.com/heroku/buildpacks-jvm/blob/main/meta-buildpacks/java/package.toml), and it represents how `pack` +will work for most the users when new behavior is implemented + +A simplified version of Buildpack Authors folder structures is: ```bash ├── bin @@ -308,7 +316,8 @@ or [Heroku](https://github.com/heroku/buildpacks-jvm/blob/main/meta-buildpacks/j └── package.toml ``` -In these cases, the expected output will be similar to: +In these cases: We expect `pack` to keep doing what is doing today, but with the warning messages we mentioned above to +let end users know things are changing. ```bash pack buildpack package <buildpack> --config ./package.toml --publish @@ -319,104 +328,112 @@ Successfully published package <buildpack> and saved to registry pack buildpack package <buildpack> --config ./package.toml --format file Warning: A new '--target' flag is available to set the platform for the buildpack package, using 'linux' as default Successfully created package <buildpack> and saved to file -``` - -We will keep `linux` as the default target platform, and we don't expect end-users to change anything else on their side. - -In case, Buildpack authors tries to use the new folder structure like: + ``` +**Output**: pack will create a buildpack package image (as it is doing it today) with the provided binaries and a +[configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) with the following target +platform: -```bash -├── buildpack.toml -├── linux-amd64 -│ └── bin -│ ├── build -│ └── detect -├── linux-arm64 -│ └── bin -│ ├── build -│ └── detect -└── package.toml +```json +{ + "architecture": "", + "os": "linux" +} ``` -The current `pack` version creates an OCI artifact copying all the files on it. - -![](https://hackmd.io/_uploads/BkGkZ_mla.png) - -But I think this buildpack can't be executed because `./bin/build` or `./bin/detect` can't be found. We could add some validations and throw an error, but I do not see any value on doing that. - -> **Important** -> New folder structure is not useful if Buildpack Authors don't remove stacks and migrate to use targets -> - -Trying to use the new flags +After checking the **warning** messages, some end users must feel curious, and the try to use the new `--target` flag. ```bash -pack buildpack package <buildpack> --config ./package.toml --publish --multi-arch -Error: 'targets' must be defined when creating a multi-architecture buildpack +pack buildpack package <buildpack> --config ./package.toml --publish --target linux/arm64 +Successfully published package <buildpack> and saved to registry # Or -pack buildpack package <buildpack> --config ./package.toml --format file --multi-arch -Error: 'targets' must be defined when creating a multi-architecture buildpack +pack buildpack package <buildpack> --config ./package.toml --format file --target linux/arm64 +Successfully created package <buildpack> and saved to file ``` -In these cases, we don't have enough information to create a multi-arch buildpack, and pack must fail its execution. +**Output**: In these cases, pack will create buildpack a package image with the provided binaries and a +[configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) with the following target +platform: -A valid way to re-write the command could be: +```json +{ + "architecture": "arm64", + "os": "linux" +} +``` + +what about creating a multi-arch image for several target platforms? ```bash -pack buildpack package <buildpack> --config ./package.toml --publish --target linux/arm64 --target linux/amd64 --multi-arch +pack buildpack package <buildpack> --config ./package.toml --publish --target linux/arm64 --target linux/amd64 A multi-arch buildpack package will be created for target platforms: 'linux/amd64', 'linux/arm64' Successfully published package <buildpack> and saved to registry # Or -pack buildpack package <buildpack> --config ./package.toml --format file --target linux/arm64 --target linux/amd64 --multi-arch +pack buildpack package <buildpack> --config ./package.toml --format file --target linux/arm64 --target linux/amd64 A multi-arch buildpack package will be created for target platforms: 'linux/amd64', 'linux/arm64' Successfully created package <buildpack> and saved to file ``` -In these cases, two OCI images, with the same binaries, will be created and pushed into the registry, for each image the configuration file will be -created with the correct `os` and `architecture` and an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them +**Output**: two OCI images, with the same binaries, will be created and pushed into the registry, for each image the +configuration file will be created with the correct `os` and `architecture` and an +[image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them +using the `<buildpack>` name provided. + +#### Buildpacks authors do not use targets AND `platform.os` is present at `package.toml` + +Let's suppose the `package.toml` has the following: -what about creating a single image for a new target platform? +```toml +[buildpack] +uri = "<A URL or path to an archive, or a path to a directory>" + +[platform] +os = "linux" +``` +These cases are similar to the previous one, but we can change the warning message. ```bash -pack buildpack package <buildpack> --config ./package.toml --publish --target linux/arm64 +pack buildpack package <buildpack> --config ./package.toml --publish +Warning: 'platform.os' field in package.toml will be deprecated, use new '--target' flag or `targets` field in buildpack.toml to set the platform. Successfully published package <buildpack> and saved to registry # Or -pack buildpack package <buildpack> --config ./package.toml --format file --target linux/arm64 +pack buildpack package <buildpack> --config ./package.toml --format file +Warning: 'platform.os' field in package.toml will be deprecated, use new '--target' flag or `targets` field in buildpack.toml to set the platform. Successfully created package <buildpack> and saved to file ``` - -In these cases, pack will create buildpack package image with the provided binaries and a [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) -with the following target platform: +**Output**: The OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) file will have: ```json { - "architecture": "arm64", + "architecture": "", "os": "linux" } ``` -##### `platform.os` is present at `package.toml` - -These cases are similar to the previous one, but we can change the warning message. +Trying to use `--target` flag with `platform.os` field at the same time should throw an error, in this way, the end-user will need to update +their `package.toml` ```bash -pack buildpack package <buildpack> --config ./package.toml --publish -Warning: 'platform.os' field in package.toml will be deprecated, use new '--target' flag to set target platform -Successfully published package <buildpack> and saved to registry - +pack buildpack package <buildpack> --config ./package.toml --publish --target linux/arm64 # Or -pack buildpack package <buildpack> --config ./package.toml --format file -Warning: 'platform.os' field in package.toml will be deprecated, use new '--target' flag to set target platform -Successfully created package <buildpack> and saved to file +pack buildpack package <buildpack> --config ./package.toml --format file --target linux/arm64 + +Error: 'platform.os' and '--target' flag can not be used in conjunction, please remove 'platform.os' from package.toml, use new '--target' flag + or `targets` field in buildpack.toml to set the platform ``` #### Buildpacks authors use targets +> **Important** +> `pack` considers the use of `targets` as an acknowledgement of expecting a multi-arch images as output. Also, we expect +> `platform.os` do not be present in `buildpack.toml` + We can divide the problem in two main scenarios: Buildpack authors use or not use the new folder structure. +##### New folder structure is not use + Let's start with the first one, which is the natural path for Buildpack Authors to migrate from `stacks` to `targets`. Let's suppose a buildpack folder structure like: ```bash @@ -437,73 +454,25 @@ arch = "amd64" [[targets]] os = "linux" arch = "arm64" -``` -How could Buildpack Authors set which `os/arch` to use?, currently `pack` doesn't care about `targets` and -it sets `linux` as the `os` in the final OCI image. We can keep this behavior, and show warning messages to end-users, -this will avoid breaking the current behavior. +# Stacks (deprecated) the buildpack will work with +[[stacks]] +id = "*" +``` ```bash pack buildpack package <buildpack> --config ./package.toml --publish -Warning: Multiple targets 'linux/amd64', 'linux/arm64' are present at 'buildpack.toml' -Warning: A new '--target' flag is available to set the target platform for the buildpack package, using 'linux' as default +A multi-arch buildpack package will be created for target platforms: 'linux/amd64', 'linux/arm64' Successfully published package <buildpack> and saved to registry # Or pack buildpack package <buildpack> --config ./package.toml --format file -Warning: Multiple targets 'linux/amd64', 'linux/arm64' are present at 'buildpack.toml' -Warning: A new '--target' flag is available to set the target platform for the buildpack package, using 'linux' as default +A multi-arch buildpack package will be created for target platforms: 'linux/amd64', 'linux/arm64' Successfully created package <buildpack> and saved to file - -# Or -pack buildpack package <buildpack> --config ./package.toml -Warning: Multiple targets 'linux/amd64', 'linux/arm64' are present at 'buildpack.toml' -Warning: A new '--target' flag is available to set the target platform for the buildpack package, using 'linux' as default -Successfully created package <buildpack> and saved to docker daemon -``` - -The OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) file will have: - -```json -{ - "architecture": "", - "os": "linux" -} ``` -On the other hand, when end-users use the new `target` flag - -```bash -pack buildpack package <buildpack> --config ./package.toml --publish --target linux/arm64 -Successfully published package <buildpack> and saved to registry -``` - -The OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) file will have: - -```json -{ - "architecture": "amd64", - "os": "linux" -} -``` - -Trying to create a buildpack package for an unsupported platform should throw an error - -```bash -pack buildpack package <buildpack> --config ./package.toml --publish --target windows/arm64 -Error: target platform 'windows/arm64' is not supported in buildpack targets, check your 'buildpack.toml' -``` - -Let's go one more step further, and check what will happen if Buildpack Authors use the new `--multi-arch` flag - -```bash -pack buildpack package <buildpack> --config ./package.toml --publish --multi-arch -Info: A multi-arch buildpack package will be created for targets platforms: 'linux/amd64', 'linux/arm64' -Successfully published package <buildpack> and saved to registry -``` - -In this case, two OCI images will be created and pushed into the registry, for each image the configuration file will be -created with the correct `os` and `architecture` and +**Output**: In this case, two OCI images will be created and pushed into the registry, for each image the configuration file will be +created with the correct `os` and `architecture` and an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them, with a content similar to: @@ -534,43 +503,70 @@ with a content similar to: "schemaVersion": 2 } ``` -> **Important** -> In this case, the layer blob for the OCI image will have the same bin/build and bin/detect binaries. This could be helpful -> for bash buildpacks for example. -There is a downside for this case, how can we do it if we have windows and linux scripts? -One way to do it could be just copying the .bat scripts along with the linux scripts, something like: +In case of targeting the daemon, pack will match **daemon os/arch** with the **targets os/arch**, for example when running +on a `linux/arm64` machine. ```bash -├── bin -│ ├── build -│ ├── build.bat -│ ├── detect -│ └── detect.bat -├── buildpack.toml -└── package.toml +pack buildpack package <buildpack> --config ./package.toml +Successfully created package <buildpack> and saved to docker daemon ``` -But we will end up distributing windows and linux scripts together. +**Output**: In these cases, pack will create buildpack a package image with the provided binaries and a +[configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) with the following target +platform: -Finally, let's check some examples for the second scenario, when Buildpack Authors migrated from `stacks` to `targets` and -they want to take advantage of the new multi-architecture capabilities, let's use our original folder structure: +```json +{ + "architecture": "arm64", + "os": "linux" +} +``` +But, if we execute the same command on a **windows/amd64** machine, platform doesn't match and an error is thrown ```bash +pack buildpack package <buildpack> --config ./package.toml +Error: daemon platform 'windows/amd64' does not match target platforms: 'linux/amd64', 'linux/arm64' +``` +On the other hand, when end-users use the new `--target` flag + +```bash +pack buildpack package <buildpack> --config ./package.toml --publish --target linux/arm64 +Successfully published package <buildpack> and saved to registry +``` + +**Output**: The OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) file will have: + +```json +{ + "architecture": "amd64", + "os": "linux" +} +``` + +##### New folder structure is use + +Finally, let's check some examples for the second scenario, when Buildpack Authors want to take advantage of the new +multi-architecture capabilities, let's use our original folder structure: + +```bash +. ├── buildpack.toml -├── linux-amd64 -│ └── bin -│ ├── build -│ └── detect -├── linux-arm64 -│ └── bin -│ ├── build -│ └── detect -└── windows-amd64 - └── 10.0.20348.1970 - └── bin - ├── build.bat - └── detect.bat +├── linux +│ ├── amd64 +│ │ └── bin +│ │ ├── build +│ │ └── detect +│ └── arm64 +│ └── bin +│ ├── build +│ └── detect +└── windows + └── amd64 + └── windows@10.0.20348.1970 + └── bin + ├── build.bat + └── detect.bat ``` And a `buildpack.toml` with the following `targets` defined: @@ -591,6 +587,10 @@ arch = "amd64" [[targets.distributions]] name = "windows" versions = ["10.0.20348.1970"] + +# Stacks (deprecated) the buildpack will work with +[[stacks]] +id = "*" ``` If the Buildpack Author wants to create a single buildpack package they will use the `target` flag @@ -600,18 +600,18 @@ pack buildpack package <buildpack> --config ./package.toml --publish --target li Successfully published package <buildpack> and saved to registry ``` -In this case, `pack` will determine the folder `linux-arm64` exists, and that must be the root folder for the buildpack. +In this case, `pack` will find the folder `linux/arm64`, and it must be the root folder for the buildpack. `pack` will copy `buildpack.toml` from the root and include it, something like: ```bash -linux-arm64 +linux/arm64 ├── bin │ ├── build │ └── detect └── buildpack.toml // Must be copy on the fly ``` -Similar to previous cases, the OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) file will have: +**Output**: The OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) file will have: ```json { @@ -620,15 +620,15 @@ Similar to previous cases, the OCI Image [configuration](https://github.com/open } ``` -A fully multi-arch buildpack could be created as follows: +A fully multi-arch buildpack will be created automatically, because we have more than one target defined. ```bash -pack buildpack package <buildpack> --config ./package.toml --publish --multi-arch +pack buildpack package <buildpack> --config ./package.toml --publish Info: A multi-arch buildpack package will be created for target platforms: 'linux/amd64', 'linux/arm64', 'windows/amd64' Successfully published package <buildpack> and saved to registry ``` -In this case, three OCI images will be created and pushed into the registry, for each image the configuration file will be +**Output**: In this case, three OCI images will be created and pushed into the registry, for each image the configuration file will be created with the correct target: `os` and `architecture`, an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them, with a content similar to: From 614052bb9729e4726301d7e6e9c69f7ebe619249 Mon Sep 17 00:00:00 2001 From: Juan Bustamante <jbustamante@vmware.com> Date: Fri, 10 Nov 2023 16:32:08 -0500 Subject: [PATCH 13/34] removing multi-arch flag Signed-off-by: Juan Bustamante <jbustamante@vmware.com> --- text/0000-multiarch-builders-and-package.md | 256 ++++++++++++-------- 1 file changed, 157 insertions(+), 99 deletions(-) diff --git a/text/0000-multiarch-builders-and-package.md b/text/0000-multiarch-builders-and-package.md index a56145423..420c7f5d6 100644 --- a/text/0000-multiarch-builders-and-package.md +++ b/text/0000-multiarch-builders-and-package.md @@ -222,55 +222,50 @@ We propose: - Deprecate the `platform.os` field from [package.toml](https://buildpacks.io/docs/reference/config/package-config/). It will be removed after two pack releases with the new feature - When `platform.os` is present in [package.toml](https://buildpacks.io/docs/reference/config/package-config/), throw a warning messages indicating the field will be removed and `--target` flag must be used -- When `platform.os` is not present [package.toml](https://buildpacks.io/docs/reference/config/package-config/) and `--target` flag is not used, throw a warning messages indicating +- When `platform.os` is not present in [package.toml](https://buildpacks.io/docs/reference/config/package-config/) and `--target` flag is not used, throw a warning messages indicating a new `--target` flag is available - Keep doing our current process to package a buildpack ### To improve user experience We propose: -- Add a new `--target` flag with format `[os][/arch][/variant]:[name@version]` to build for a particular target, once the `platform.os` field is removed, +- Add a new `--target` flag with the follwing format `[os][/arch][/variant]:[name@version]` to build for a particular target, once the `platform.os` field is removed, this will be the way for end-users to specify the platform for which they want to create single OCI artifact. -> **Note** -> We want to avoid duplicated information, we expect to have `targets` with all the platform supported by a buildpack - Add `targets` section to `buildpack.toml` to help Buildpack Authors to include support for new platforms without having to update their `pack buildpack package` command in their CI/CD pipelines -- A new folder structure to organize the buildpacks binaries for multi-arch images +- A new folder structure to organize the buildpacks binaries for multi-arch images, similar to this one: ```bash # Option 1 - no variant is required . -├── buildpack.toml -└── {os} // optional - └── {arch} // optional +├── buildpack.toml // mandatory +└── {os} // optional + └── {arch} // optional └── bin - ├── build - └── detect + ├── build // platform dependant binary (mandatory) + └── detect // platform dependant binary (mandatory) # Option 2 - variant is required . -├── buildpack.toml +├── buildpack.toml // mandatory └── {os} // optional └── {arch} // optional └── {variant} // optional ├── {name@version-1} // optional │ └── bin - │ ├── build - │ └── detect + │ ├── build // platform dependant binary (mandatory) + │ └── detect // platform dependant binary (mandatory) └── {name@version-2} // optional └── bin - ├── build - └── detect + ├── build // platform dependant binary (mandatory) + └── detect // platform dependant binary (mandatory) ``` > **Note** > For cross-compile buildpacks like Paketo, it looks easy to add a step to their Makefile to compile and separate the binaries following this structure. It is important to mention > that the final buildpack image will not change, this will only change the buildpack structure from `pack` perspective -In case, this folder structure is not suitable for Buildpack Authors: - -> **Proposal** -> a new `path` attribute is proposed to be included into the `target` section of the `buildpack.toml` to specify -where the binaries are located in the filesystem. +In case, this folder structure is not suitable for Buildpack Authors, **we propose** a new `path` attribute to be included +into the `target` section of the `buildpack.toml` to specify where the binaries are located in the filesystem. Based on the [RFC-0096](https://github.com/buildpacks/rfcs/blob/main/text/0096-remove-stacks-mixins.md) the new `buildpack.toml` schema will look like this: @@ -362,6 +357,10 @@ platform: } ``` +> **Important** +> Pack will assume the binaries are appropriate for the given target platform, what the flag is doing is expose a mechanism +> to update the metadata present in the OCI config file + what about creating a multi-arch image for several target platforms? ```bash @@ -378,7 +377,36 @@ Successfully created package <buildpack> and saved to file **Output**: two OCI images, with the same binaries, will be created and pushed into the registry, for each image the configuration file will be created with the correct `os` and `architecture` and an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them -using the `<buildpack>` name provided. +using the `<buildpack>` name provided. The content of the [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) +will be similar to: + +```json + +{ + "manifests": [ + { + "digest": "sha256:b492494d8e0113c4ad3fe4528a4b5ff89faa5331f7d52c5c138196f69ce176a6", + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "platform": { + "architecture": "amd64", + "os": "linux" + }, + "size": 424 + }, + { + "digest": "sha256:2589fe6bcf90466564741ae0d8309d1323f33b6ec8a5d401a62d0b256bcc3c37", + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "platform": { + "architecture": "arm", + "os": "linux" + }, + "size": 424 + } + ], + "mediaType": "application/vnd.oci.image.index.v1+json", + "schemaVersion": 2 +} +``` #### Buildpacks authors do not use targets AND `platform.os` is present at `package.toml` @@ -391,7 +419,7 @@ uri = "<A URL or path to an archive, or a path to a directory>" [platform] os = "linux" ``` -These cases are similar to the previous one, but we can change the warning message. +These cases are similar to the previous one, but we the warning message will be changed. ```bash pack buildpack package <buildpack> --config ./package.toml --publish @@ -434,7 +462,8 @@ We can divide the problem in two main scenarios: Buildpack authors use or not us ##### New folder structure is not use -Let's start with the first one, which is the natural path for Buildpack Authors to migrate from `stacks` to `targets`. Let's suppose a buildpack folder structure like: +Let's start with the first one, which is the natural path for Buildpack Authors that are using `bash` buildpacks. +Let's suppose a buildpack folder structure like: ```bash ├── bin @@ -504,6 +533,22 @@ with a content similar to: } ``` +On the other hand, when end-users use the new `--target` flag, they can create a single OCI artifact + +```bash +pack buildpack package <buildpack> --config ./package.toml --publish --target linux/arm64 +Successfully published package <buildpack> and saved to registry +``` + +**Output**: The OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) file will have: + +```json +{ + "architecture": "amd64", + "os": "linux" +} +``` + In case of targeting the daemon, pack will match **daemon os/arch** with the **targets os/arch**, for example when running on a `linux/arm64` machine. @@ -512,7 +557,7 @@ pack buildpack package <buildpack> --config ./package.toml Successfully created package <buildpack> and saved to docker daemon ``` -**Output**: In these cases, pack will create buildpack a package image with the provided binaries and a +**Output**: pack will create a buildpack package image with the provided binaries and a [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) with the following target platform: @@ -523,26 +568,12 @@ platform: } ``` -But, if we execute the same command on a **windows/amd64** machine, platform doesn't match and an error is thrown +But, if we execute the same command on a **windows/amd64** machine, the `buildpack.toml` doesn't contain any `target` that +matches the **daemon os/arch**, an error must be thrown ```bash pack buildpack package <buildpack> --config ./package.toml Error: daemon platform 'windows/amd64' does not match target platforms: 'linux/amd64', 'linux/arm64' ``` -On the other hand, when end-users use the new `--target` flag - -```bash -pack buildpack package <buildpack> --config ./package.toml --publish --target linux/arm64 -Successfully published package <buildpack> and saved to registry -``` - -**Output**: The OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) file will have: - -```json -{ - "architecture": "amd64", - "os": "linux" -} -``` ##### New folder structure is use @@ -593,40 +624,14 @@ versions = ["10.0.20348.1970"] id = "*" ``` -If the Buildpack Author wants to create a single buildpack package they will use the `target` flag - -```bash -pack buildpack package <buildpack> --config ./package.toml --publish --target linux/arm64 -Successfully published package <buildpack> and saved to registry -``` - -In this case, `pack` will find the folder `linux/arm64`, and it must be the root folder for the buildpack. -`pack` will copy `buildpack.toml` from the root and include it, something like: - -```bash -linux/arm64 -├── bin -│ ├── build -│ └── detect -└── buildpack.toml // Must be copy on the fly -``` - -**Output**: The OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) file will have: - -```json -{ - "architecture": "arm64", - "os": "linux" -} -``` - -A fully multi-arch buildpack will be created automatically, because we have more than one target defined. - +When Buildpack Authors want to create a multi-arch images, they can execute the following command: ```bash pack buildpack package <buildpack> --config ./package.toml --publish Info: A multi-arch buildpack package will be created for target platforms: 'linux/amd64', 'linux/arm64', 'windows/amd64' Successfully published package <buildpack> and saved to registry ``` +A fully multi-arch buildpack will be created automatically, because we have more than one target defined +in the `buildpack.toml` **Output**: In this case, three OCI images will be created and pushed into the registry, for each image the configuration file will be created with the correct target: `os` and `architecture`, @@ -671,9 +676,63 @@ with a content similar to: } ``` -> **Important** -> In this case, each image has different binaries according to the target platform and the new folder structure - +If the Buildpack Author wants to create a single buildpack package they will use the `target` flag, similar to our previous +examples. + +### Important considerations for share files in the new folder structure + +Let's suppose we have a multi-arch buildpack **A** with local folder structure like this: + +```bash +. +├── LICENSE +├── NOTICE +├── README.md +├── buildpack.toml +├── resources +│ ├── config.properties +└── linux + ├── amd64 + │ └── bin + │ ├── build + │ ├── detect + │ └── foo + └── arm64 + └── bin + ├── build + ├── detect + └── bar +``` + +As we already discussed in this RFC, we are expecting to create two OCI images artifacts, combined with an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md). +But what happen with the layers on those OCI images and the files that are shared? + +If we update the buildpack package creation process as follows: + +- If `A` is a multi-arch buildpack +- If `Platform` is a target defined for the buildpack A that follows a folder structure like `{os}/{arch}[/{variant}/{name@version-1}]/bin` + +$$BuildpackPackageLayers(A, Platform) = ShareLayers(A) + PlatformLayers(A, Platform)$$ + +Where + +- **ShareLayers**: Will be a layer created with the content of the root folder filtering out any `{os}` folder +- **PlatformLayers**: Will be a layer created with the content of the `Platform` folder given + +With our previous example, it means + +$$ ShareLayers(A) = \{\text{LICENSE},\text{NOTICE},\text{README.md},\text{buildpack.toml},\text{resources/config.properties}\} $$ + +$$ PlatformLayers(A,\text{linux,amd64}) = \{\text{bin/build},\text{bin/detect},\text{bin/foo}\} $$ + +$$ PlatformLayers(A,\text{linux,arm64}) = \{\text{bin/build},\text{bin/detect},\text{bin/bar}\} $$ + +$$ BuildpackPackageLayers(A,\text{linux,amd64}) = ShareLayers(A) + PlatformLayers(A,\text{linux,amd64}) $$ + +$$ BuildpackPackageLayers(A,\text{linux,arm64}) = ShareLayers(A) + PlatformLayers(A,\text{linux,arm64}) $$ + +This means the shared layer can be reused in each intermediate image and improve the performance when it contains big files + ## Builder Similar to how we did it for the `buildpack package`, lets summaries, our current process to create a **Builder**: @@ -700,7 +759,11 @@ it will be removed We propose: -- Add `targets` section to the `builder.toml` schema, this will keep consistency for end-users to understand how to define multi-architecture. The new schema will be +- Add `targets` section to the `builder.toml` schema, this will keep consistency for end-users to understand how to +define multi-architecture. Adding more than one target to the `builder.toml` will be considered by `pack` as an +acknowledgement of the desired to generate multi-arch [Builders](https://buildpacks.io/docs/concepts/components/builder/). + +The new schema will be similar to: ```toml # Buildpacks to include in builder, @@ -728,9 +791,8 @@ variant = "<architecture variant>" name = "<distribution ID>" versions = ["<distribution version>"] ``` -- Add a new `--target` optional flag with format `[os][/arch][/variant]:[name@version]` to create a builder for a particular target, this will help end-users to specify the platform for which they want to create single OCI artifact. -- Add a new boolean `--multi-arch` flag to indicate pack it must create multiples OCI artifacts and combine them with an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md), - this flag must be used in conjunction with `--publish` or `--format file` flags and error out when `daemon` is selected. +- Add a new `--target` optional flag with format `[os][/arch][/variant]:[name@version]` to create a builder for a +particular target, this will help end-users to specify the platform for which they want to create single OCI artifact. ### Examples @@ -738,8 +800,9 @@ Let's use some examples to explain the expected behavior in different use cases #### `Targets` are not present in `builder.toml` -This is probably the case for most of the Buildpack Authors, for example [Paketo](https://github.com/paketo-buildpacks/builder-jammy-tiny/blob/main/builder.toml), lets suppose a -`buildpack.toml` like: +This is probably the case for most of the Buildpack Authors, for example +[Paketo](https://github.com/paketo-buildpacks/builder-jammy-tiny/blob/main/builder.toml), lets suppose a`buildpack.toml` +like: ```toml # Buildpacks to include in builder @@ -790,7 +853,7 @@ Successfully created builder image <builder> Tip: Run pack build <image-name> --builder <builder> to use this builder ``` -Pulling operations will be configured to use `linux/arm64` as target platform, +**Output**: Pulling operations will be configured to use `linux/arm64` as target platform, the OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) file will have: ```json @@ -802,18 +865,10 @@ the OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/ What about multi-architecture builders? -```bash -pack builder create <builder> --config ./builder.toml --multi-arch --publish -Error: 'targets' must be defined when creating a multi-architecture builder -``` - -In this case, pack doesn't have enough information to create a multi-arch builder and fail its execution. - Using `target` flag: ```bash pack builder create <builder> --config ./builder.toml \ - --multi-arch \ --target linux/amd64 \ --target linux/arm64 \ --publish @@ -821,9 +876,9 @@ Successfully created builder image <builder> Tip: Run pack build <image-name> --builder <builder> to use this builder ``` -In this case, two OCI images will be created and pushed into the registry, for each image the configuration file will be -created with the correct target: `os` and `architecture`, -an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them +**Output**: two OCI images will be created and pushed into the registry, for each image the configuration file will be +created with the correct target: `os` and `architecture`, an +[image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them #### `Targets` are present in `builder.toml` @@ -855,7 +910,7 @@ os = "linux" arch = "arm64" ``` -Let's suppose we execute the command in a host "linux/amd64" machine +Let's suppose we execute the command against a daemon running in a `linux/amd64` machine ```bash pack builder create <builder> --config ./builder.toml @@ -864,14 +919,18 @@ Successfully created builder image <builder> Tip: Run pack build <image-name> --builder <builder> to use this builder ``` -`target` flag is not defined, we keep our current behavior and detect the host `os` and `architecture`. Because a -`target` matches the host `platform` it is used to create the builder. +**Output**: We keep our current behavior and detect the `os` and `architecture` from the daemon. Because there is `target` +that matches the daemon `os/arch` the builder is being built. -Trying to use the new flags: +Using `--target` flag against the daemon with a different platform + +TODO check if this is possible! +<!-- ```bash pack builder create <builder> --config ./builder.toml --target linux/arm64 -Info: creating a builder for target "linux/arm64" +Info: creating a builder for target "linux/arm64" +Warning: Successfully created builder image <builder> Tip: Run pack build <image-name> --builder <builder> to use this builder ``` @@ -885,22 +944,21 @@ the OCI Image [configuration](https://github.com/opencontainers/image-spec/blob/ "os": "linux" } ``` +--> What about multi-architecture builders? ```bash -pack builder create <builder> --config ./builder.toml --multi-arch --publish +pack builder create <builder> --config ./builder.toml --publish Info: A multi-arch builder will be created for targets platform: 'linux/amd64', 'linux/arm64' Successfully created builder image <builder> Tip: Run pack build <image-name> --builder <builder> to use this builder ``` - Using `target` flag: ```bash pack builder create <builder> --config ./builder.toml \ - --multi-arch \ --target linux/amd64 \ --target linux/arm64 \ --publish @@ -909,7 +967,7 @@ Successfully created builder image <builder> Tip: Run pack build <image-name> --builder <builder> to use this builder ``` -In this case, two OCI images will be created and pushed into the registry, for each image the configuration file will be +**Output** In both cases, two OCI images will be created and pushed into the registry, for each image the configuration file will be created with the correct target platform: `os` and `architecture`, an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them From 7d017d8dd6b1d08eedbf4e35a5fffda682e18c15 Mon Sep 17 00:00:00 2001 From: Juan Bustamante <jbustamante@vmware.com> Date: Fri, 24 Nov 2023 17:55:54 -0500 Subject: [PATCH 14/34] fixing some format with the formulas Signed-off-by: Juan Bustamante <jbustamante@vmware.com> --- text/0000-multiarch-builders-and-package.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text/0000-multiarch-builders-and-package.md b/text/0000-multiarch-builders-and-package.md index 420c7f5d6..7e5eb6f0e 100644 --- a/text/0000-multiarch-builders-and-package.md +++ b/text/0000-multiarch-builders-and-package.md @@ -709,8 +709,8 @@ But what happen with the layers on those OCI images and the files that are share If we update the buildpack package creation process as follows: -- If `A` is a multi-arch buildpack -- If `Platform` is a target defined for the buildpack A that follows a folder structure like `{os}/{arch}[/{variant}/{name@version-1}]/bin` +- `A` is a multi-arch buildpack +- `Platform` is a target defined for the buildpack A that follows a folder structure like `{os}/{arch}[/{variant}/{name@version-1}]/bin` $$BuildpackPackageLayers(A, Platform) = ShareLayers(A) + PlatformLayers(A, Platform)$$ From cf6879e9cb6a65f2bcc723647fc9cf651f42bd34 Mon Sep 17 00:00:00 2001 From: Juan Bustamante <jbustamante@vmware.com> Date: Mon, 27 Nov 2023 16:08:16 -0500 Subject: [PATCH 15/34] updating shared folders definition Signed-off-by: Juan Bustamante <jbustamante@vmware.com> --- text/0000-multiarch-builders-and-package.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/text/0000-multiarch-builders-and-package.md b/text/0000-multiarch-builders-and-package.md index 7e5eb6f0e..15719dbff 100644 --- a/text/0000-multiarch-builders-and-package.md +++ b/text/0000-multiarch-builders-and-package.md @@ -679,7 +679,7 @@ with a content similar to: If the Buildpack Author wants to create a single buildpack package they will use the `target` flag, similar to our previous examples. -### Important considerations for share files in the new folder structure +### Important considerations for sharing files with the new folder structure Let's suppose we have a multi-arch buildpack **A** with local folder structure like this: @@ -704,22 +704,26 @@ Let's suppose we have a multi-arch buildpack **A** with local folder structure l └── bar ``` -As we already discussed in this RFC, we are expecting to create two OCI images artifacts, combined with an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md). +As we already discussed in this RFC, we are expecting to create two OCI images artifacts and combine with an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md). But what happen with the layers on those OCI images and the files that are shared? -If we update the buildpack package creation process as follows: +Let's suppose we have the following: + +Given - `A` is a multi-arch buildpack -- `Platform` is a target defined for the buildpack A that follows a folder structure like `{os}/{arch}[/{variant}/{name@version-1}]/bin` +- `Platform` is a target defined for `A` that follows a structure like `{os}/{arch}[/{variant}/{name@version-1}]/bin` + +We define the buildpack package layers as: $$BuildpackPackageLayers(A, Platform) = ShareLayers(A) + PlatformLayers(A, Platform)$$ Where -- **ShareLayers**: Will be a layer created with the content of the root folder filtering out any `{os}` folder -- **PlatformLayers**: Will be a layer created with the content of the `Platform` folder given +- **ShareLayers**: Will be a layer created with the content of the root folder filtering out all the `{os}` folders +- **PlatformLayers**: Will be a layer created with the `bin` folder content of the given `Platform` -With our previous example, it means +Using our previous example: $$ ShareLayers(A) = \{\text{LICENSE},\text{NOTICE},\text{README.md},\text{buildpack.toml},\text{resources/config.properties}\} $$ From 93a2d3a6969021b4ea5ce698b5ee6be6a0713640 Mon Sep 17 00:00:00 2001 From: Juan Bustamante <jbustamante@vmware.com> Date: Thu, 30 Nov 2023 11:01:39 -0500 Subject: [PATCH 16/34] fixing the shared layers concept, because we can't do it based on the distribution spec Signed-off-by: Juan Bustamante <jbustamante@vmware.com> --- text/0000-multiarch-builders-and-package.md | 53 ++++++++++----------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/text/0000-multiarch-builders-and-package.md b/text/0000-multiarch-builders-and-package.md index 15719dbff..54c6d9fc2 100644 --- a/text/0000-multiarch-builders-and-package.md +++ b/text/0000-multiarch-builders-and-package.md @@ -689,6 +689,8 @@ Let's suppose we have a multi-arch buildpack **A** with local folder structure l ├── NOTICE ├── README.md ├── buildpack.toml +├── package.toml +├── some-file // a file with a big size for example ├── resources │ ├── config.properties └── linux @@ -704,38 +706,35 @@ Let's suppose we have a multi-arch buildpack **A** with local folder structure l └── bar ``` -As we already discussed in this RFC, we are expecting to create two OCI images artifacts and combine with an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md). -But what happen with the layers on those OCI images and the files that are shared? +As we already discussed in this RFC, we are expecting to create two OCI images artifacts and combine with an +[image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md). The current [distribution spec](https://github.com/buildpacks/spec/blob/main/distribution.md#buildpackage) +defines: -Let's suppose we have the following: - -Given - -- `A` is a multi-arch buildpack -- `Platform` is a target defined for `A` that follows a structure like `{os}/{arch}[/{variant}/{name@version-1}]/bin` - -We define the buildpack package layers as: - -$$BuildpackPackageLayers(A, Platform) = ShareLayers(A) + PlatformLayers(A, Platform)$$ - -Where - -- **ShareLayers**: Will be a layer created with the content of the root folder filtering out all the `{os}` folders -- **PlatformLayers**: Will be a layer created with the `bin` folder content of the given `Platform` - -Using our previous example: - -$$ ShareLayers(A) = \{\text{LICENSE},\text{NOTICE},\text{README.md},\text{buildpack.toml},\text{resources/config.properties}\} $$ - -$$ PlatformLayers(A,\text{linux,amd64}) = \{\text{bin/build},\text{bin/detect},\text{bin/foo}\} $$ +``` +Each buildpack layer blob MUST contain a single buildpack at the following file path: -$$ PlatformLayers(A,\text{linux,arm64}) = \{\text{bin/build},\text{bin/detect},\text{bin/bar}\} $$ +/cnb/buildpacks/<buildpack ID>/<buildpack version>/ +``` -$$ BuildpackPackageLayers(A,\text{linux,amd64}) = ShareLayers(A) + PlatformLayers(A,\text{linux,amd64}) $$ +This means, we will end up duplicating the big file in each OCI images, for example our `linux/amd64` buildpack package +will have 1 layer with the following content under `/cnb/buildpacks/<buildpack ID>/<buildpack version>/` -$$ BuildpackPackageLayers(A,\text{linux,arm64}) = ShareLayers(A) + PlatformLayers(A,\text{linux,arm64}) $$ +```bash +├── LICENSE +├── NOTICE +├── README.md +├── buildpack.toml +├── some-file // a file with a big size for example +├── resources +│ └── config.properties +└── bin + ├── build + ├── detect + └── foo +``` -This means the shared layer can be reused in each intermediate image and improve the performance when it contains big files +And the `linux/arm64` version will be similar but with the `bar` file inside the `bin/` folder, as a consequence, the big file +will be duplicated on two different layers increasing the space requirements in the registry ## Builder From 515f41adaf49ab755a074d61c640b02cddc791b9 Mon Sep 17 00:00:00 2001 From: Juan Bustamante <jbustamante@vmware.com> Date: Thu, 25 Jan 2024 15:07:35 -0500 Subject: [PATCH 17/34] adding some overriding rules Signed-off-by: Juan Bustamante <jbustamante@vmware.com> --- text/0000-multiarch-builders-and-package.md | 86 ++++++++++++++++++++- 1 file changed, 83 insertions(+), 3 deletions(-) diff --git a/text/0000-multiarch-builders-and-package.md b/text/0000-multiarch-builders-and-package.md index 54c6d9fc2..995c97bc1 100644 --- a/text/0000-multiarch-builders-and-package.md +++ b/text/0000-multiarch-builders-and-package.md @@ -284,9 +284,10 @@ versions = ["<distribution version>"] ``` - When `more than 1 target is defined` - When `--publish` or `--format file` is specified - - For each `target` an OCI image will be created, following our current process - - `pack` will determine the binaries path (based on the `targets.path` in the buildpack.toml or infering a folder structure similar to the one show above) - - `pack` will include the binaries in the buildpack package OCI image + - For each `target` an OCI image will be created, following these rules + - `pack` will copy everything in the root folder excluding all `{os}/**` folder + - `pack` will determine the **target root binary folder**, this is the specific root folder for a given `target` (based on the `targets.path` in the buildpack.toml or inferring it from a folder structure similar to the one show above) + - `pack` will copy everything from the **target root binary folder** into the base buildpack package folder, in case a conflict file name is found, `pack` will **override** the existing file with the latest one - If more than 1 OCI image was created, an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them - When `--daemon` is specified - `pack` can keep using `docker.OSType` to determine the target `os` and probably can do some validations it the `os` is valid target @@ -295,6 +296,85 @@ versions = ["<distribution version>"] Let's use some examples to explain the expected behavior in different use cases +#### Overriding files rules + +Let's suppose the Buildpack Author creates a multi-arch folder structure and wants to create multiple buildpack packages + +```bash +. +├── buildpack.toml +├── package.toml +├── foo // some common file for all the platforms +└── linux + ├── amd64 + │ └── bin + │ ├── build + │ ├── detect + │ └── foo + └── arm64 + ├── foo // for some reason we need a different binary for arm64 + └── bin + ├── build + ├── detect + └── bar +``` + +In this case: + - The targets `os` provided are `["linux"]`, then + - For each `target` pack will exclude everything from `linux/**` to be copied into the initial buildpack package + +Resulting into a base structure like: + +```bash +. +└── cnb + └── buildpacks + └── {ID} + └── {version} + ├── buildpack.toml + ├── foo // this is our common file + └── package.toml +``` + +When target is `linux/amd64` + - `pack` will determined **target root binary folder** is `./linux/amd64` + - `pack` will copy everything from the `./linux/arm64` into the base buildpack package folder, because there are no conflicts the expected output will be: + +```bash + +. +└── cnb + └── buildpacks + └── {ID} + └── {version} + ├── bin + │ ├── build + │ ├── detect + │ └── foo // specific platform binary + ├── buildpack.toml + ├── foo // common file + └── package.toml +``` + +On the other hand, When target is `linux/arm64` +- `pack` will determined **target root binary folder** is `./linux/arm64` + - `pack` will copy everything from the `./linux/arm64` into the base buildpack package folder, because there is a conflict trying to copy `./linux/arm64/foo` into `cnb/buildpacks/{ID}/{version}/foo`, `pack` will override it and moves forward, resulting into: + +```bash +. +└── cnb + └── buildpacks + └── {ID} + └── {version} + ├── bin + │ ├── bar // specific platform binary + │ ├── build + │ └── detect + ├── buildpack.toml + ├── foo // override files with the content of the arm64 folder + └── package.toml +``` + #### Buildpacks authors do not use targets AND `platform.os` is not present at `package.toml` This seems to be the case for [Paketo Buildpacks](https://github.com/paketo-buildpacks/java/blob/main/package.toml) From 62847fdb313f022550b8348611421c56b2c0c7ca Mon Sep 17 00:00:00 2001 From: Juan Bustamante <jbustamante@vmware.com> Date: Fri, 2 Feb 2024 08:42:33 -0500 Subject: [PATCH 18/34] Update text/0000-multiarch-builders-and-package.md Co-authored-by: Natalie Arellano <narellano@vmware.com> Signed-off-by: Juan Bustamante <bustamantejj@gmail.com> Signed-off-by: Juan Bustamante <jbustamante@vmware.com> --- text/0000-multiarch-builders-and-package.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-multiarch-builders-and-package.md b/text/0000-multiarch-builders-and-package.md index 995c97bc1..c6423ddd8 100644 --- a/text/0000-multiarch-builders-and-package.md +++ b/text/0000-multiarch-builders-and-package.md @@ -396,7 +396,7 @@ let end users know things are changing. ```bash pack buildpack package <buildpack> --config ./package.toml --publish -Warning: A new '--target' flag is available to set the platform for the buildpack package, using 'linux' as default +Warning: A new '--target' flag is available to set the platform for the buildpack package, using 'linux/amd64' as default Successfully published package <buildpack> and saved to registry # Or From 075b11cc4bf44160efb212ac9d8886d2e13ba1af Mon Sep 17 00:00:00 2001 From: Juan Bustamante <jbustamante@vmware.com> Date: Fri, 2 Feb 2024 08:42:54 -0500 Subject: [PATCH 19/34] Update text/0000-multiarch-builders-and-package.md Co-authored-by: Natalie Arellano <narellano@vmware.com> Signed-off-by: Juan Bustamante <bustamantejj@gmail.com> Signed-off-by: Juan Bustamante <jbustamante@vmware.com> --- text/0000-multiarch-builders-and-package.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-multiarch-builders-and-package.md b/text/0000-multiarch-builders-and-package.md index c6423ddd8..55ad6a25d 100644 --- a/text/0000-multiarch-builders-and-package.md +++ b/text/0000-multiarch-builders-and-package.md @@ -401,7 +401,7 @@ Successfully published package <buildpack> and saved to registry # Or pack buildpack package <buildpack> --config ./package.toml --format file -Warning: A new '--target' flag is available to set the platform for the buildpack package, using 'linux' as default +Warning: A new '--target' flag is available to set the platform for the buildpack package, using 'linux/amd64' as default Successfully created package <buildpack> and saved to file ``` **Output**: pack will create a buildpack package image (as it is doing it today) with the provided binaries and a From fbdd18122b5eb74d66ac15b9653226509b50f512 Mon Sep 17 00:00:00 2001 From: Juan Bustamante <jbustamante@vmware.com> Date: Fri, 2 Feb 2024 09:49:13 -0500 Subject: [PATCH 20/34] adding some more feedback from review Signed-off-by: Juan Bustamante <jbustamante@vmware.com> --- text/0000-multiarch-builders-and-package.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text/0000-multiarch-builders-and-package.md b/text/0000-multiarch-builders-and-package.md index 55ad6a25d..aa5c8dcf4 100644 --- a/text/0000-multiarch-builders-and-package.md +++ b/text/0000-multiarch-builders-and-package.md @@ -223,7 +223,7 @@ We propose: - When `platform.os` is present in [package.toml](https://buildpacks.io/docs/reference/config/package-config/), throw a warning messages indicating the field will be removed and `--target` flag must be used - When `platform.os` is not present in [package.toml](https://buildpacks.io/docs/reference/config/package-config/) and `--target` flag is not used, throw a warning messages indicating -a new `--target` flag is available +a new `--target` flag is available and how to use it, or some helpful information on how to add `targets` to the `buildpack.toml` - Keep doing our current process to package a buildpack ### To improve user experience @@ -265,7 +265,7 @@ this will be the way for end-users to specify the platform for which they want t > that the final buildpack image will not change, this will only change the buildpack structure from `pack` perspective In case, this folder structure is not suitable for Buildpack Authors, **we propose** a new `path` attribute to be included -into the `target` section of the `buildpack.toml` to specify where the binaries are located in the filesystem. +into the `target` section of the `buildpack.toml` to specify where the **buildapck root directoy** is located in the filesystem. Based on the [RFC-0096](https://github.com/buildpacks/rfcs/blob/main/text/0096-remove-stacks-mixins.md) the new `buildpack.toml` schema will look like this: From 05a4383d97033a5313fe2a94557bfe33a242592c Mon Sep 17 00:00:00 2001 From: Juan Bustamante <jbustamante@vmware.com> Date: Thu, 8 Feb 2024 12:58:40 -0500 Subject: [PATCH 21/34] Removing the shared files complexity Signed-off-by: Juan Bustamante <jbustamante@vmware.com> --- text/0000-multiarch-builders-and-package.md | 131 +++++--------------- 1 file changed, 30 insertions(+), 101 deletions(-) diff --git a/text/0000-multiarch-builders-and-package.md b/text/0000-multiarch-builders-and-package.md index aa5c8dcf4..359537d40 100644 --- a/text/0000-multiarch-builders-and-package.md +++ b/text/0000-multiarch-builders-and-package.md @@ -32,6 +32,11 @@ that combines them into one single consumable tag for end-users. - Builder: A builder is an image that contains all the components necessary to execute a build. A builder image is created by taking a build image and adding a lifecycle, buildpacks, and files that configure aspects of the build including the buildpack detection order and the location(s) of the run image - Image Manifest: The image manifest provides a configuration and set of layers for a single container image for a specific architecture and operating system. See [spec](https://github.com/opencontainers/image-spec/blob/main/manifest.md) - Image Index: The image index is a higher-level manifest which points to specific image manifests, ideal for one or more platforms. See [spec](https://github.com/opencontainers/image-spec/blob/main/image-index.md) +- Buildpack root folder: is the top-most directory where a `buildpack.toml` can be found +- Platform root folder: Based on our new folder structure, the **platform root folder** is the top-most directory that identifies a target in **buildpack root folder** + For example: + - given a target `linux/amd64` the **platform root folder** will be `<buildpack root folder>/linux/amd64` + - given a target `windows/amd64:windows@10.0.20348.1970` the **platform root folder** will be `<buildpack root folder>/windows/amd64/windows@10.0.20348.1970` # Motivation [motivation]: #motivation @@ -239,8 +244,9 @@ this will be the way for end-users to specify the platform for which they want t # Option 1 - no variant is required . ├── buildpack.toml // mandatory +├── package.toml // mandatory └── {os} // optional - └── {arch} // optional + └── {arch} // optional (becomes the platform root folder) └── bin ├── build // platform dependant binary (mandatory) └── detect // platform dependant binary (mandatory) @@ -248,19 +254,24 @@ this will be the way for end-users to specify the platform for which they want t # Option 2 - variant is required . ├── buildpack.toml // mandatory +├── package.toml // mandatory └── {os} // optional └── {arch} // optional └── {variant} // optional - ├── {name@version-1} // optional - │ └── bin - │ ├── build // platform dependant binary (mandatory) - │ └── detect // platform dependant binary (mandatory) - └── {name@version-2} // optional + ├── {name@version-1} // optional (becomes the platform root folder) + │ └── bin + │ ├── build // platform dependant binary (mandatory) + │ └── detect // platform dependant binary (mandatory) + └── {name@version-2} // optional (becomes the platform root folder) └── bin ├── build // platform dependant binary (mandatory) └── detect // platform dependant binary (mandatory) ``` -> **Note** +- `buildpack.toml` file MUST be present at the **buildpack root folder** +- `package.toml` file MUST be present at the **buildpack root folder** +- For each platform, Buildpack Authors are responsible for copying or creating symlink or hard link for files into each **platform root folder** + +> **Note** > For cross-compile buildpacks like Paketo, it looks easy to add a step to their Makefile to compile and separate the binaries following this structure. It is important to mention > that the final buildpack image will not change, this will only change the buildpack structure from `pack` perspective @@ -285,9 +296,8 @@ versions = ["<distribution version>"] - When `more than 1 target is defined` - When `--publish` or `--format file` is specified - For each `target` an OCI image will be created, following these rules - - `pack` will copy everything in the root folder excluding all `{os}/**` folder - - `pack` will determine the **target root binary folder**, this is the specific root folder for a given `target` (based on the `targets.path` in the buildpack.toml or inferring it from a folder structure similar to the one show above) - - `pack` will copy everything from the **target root binary folder** into the base buildpack package folder, in case a conflict file name is found, `pack` will **override** the existing file with the latest one + - `pack` will determine the **platform root folder**, this is the specific root folder for a given `target` (based on the `targets.path` in the buildpack.toml or inferring it from a folder structure similar to the one show above) + - `pack` will execute the current process to create a buildpack package using the **platform root folder** and the `target` values - If more than 1 OCI image was created, an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them - When `--daemon` is specified - `pack` can keep using `docker.OSType` to determine the target `os` and probably can do some validations it the `os` is valid target @@ -296,15 +306,14 @@ versions = ["<distribution version>"] Let's use some examples to explain the expected behavior in different use cases -#### Overriding files rules +#### How to determine the platform root folder Let's suppose the Buildpack Author creates a multi-arch folder structure and wants to create multiple buildpack packages ```bash . ├── buildpack.toml -├── package.toml -├── foo // some common file for all the platforms +├── package.toml └── linux ├── amd64 │ └── bin @@ -312,33 +321,15 @@ Let's suppose the Buildpack Author creates a multi-arch folder structure and wan │ ├── detect │ └── foo └── arm64 - ├── foo // for some reason we need a different binary for arm64 + ├── foo └── bin ├── build ├── detect └── bar ``` -In this case: - - The targets `os` provided are `["linux"]`, then - - For each `target` pack will exclude everything from `linux/**` to be copied into the initial buildpack package - -Resulting into a base structure like: - -```bash -. -└── cnb - └── buildpacks - └── {ID} - └── {version} - ├── buildpack.toml - ├── foo // this is our common file - └── package.toml -``` - -When target is `linux/amd64` - - `pack` will determined **target root binary folder** is `./linux/amd64` - - `pack` will copy everything from the `./linux/arm64` into the base buildpack package folder, because there are no conflicts the expected output will be: +- When `linux/amd64` the **platform root folder** determined is `<buildpack root folder>/linux/amd64`, and the expected +folder structure in the OCI image for each buildpack package will be: ```bash @@ -352,14 +343,11 @@ When target is `linux/amd64` │ ├── detect │ └── foo // specific platform binary ├── buildpack.toml - ├── foo // common file └── package.toml ``` -On the other hand, When target is `linux/arm64` -- `pack` will determined **target root binary folder** is `./linux/arm64` - - `pack` will copy everything from the `./linux/arm64` into the base buildpack package folder, because there is a conflict trying to copy `./linux/arm64/foo` into `cnb/buildpacks/{ID}/{version}/foo`, `pack` will override it and moves forward, resulting into: - +On the other hand, When target is `linux/arm64, the **platform root folder** determined is `<buildpack root folder>/linux/arm64` +and the output OCI image folder structure looks like: ```bash . └── cnb @@ -371,7 +359,7 @@ On the other hand, When target is `linux/arm64` │ ├── build │ └── detect ├── buildpack.toml - ├── foo // override files with the content of the arm64 folder + ├── foo └── package.toml ``` @@ -759,63 +747,6 @@ with a content similar to: If the Buildpack Author wants to create a single buildpack package they will use the `target` flag, similar to our previous examples. -### Important considerations for sharing files with the new folder structure - -Let's suppose we have a multi-arch buildpack **A** with local folder structure like this: - -```bash -. -├── LICENSE -├── NOTICE -├── README.md -├── buildpack.toml -├── package.toml -├── some-file // a file with a big size for example -├── resources -│ ├── config.properties -└── linux - ├── amd64 - │ └── bin - │ ├── build - │ ├── detect - │ └── foo - └── arm64 - └── bin - ├── build - ├── detect - └── bar -``` - -As we already discussed in this RFC, we are expecting to create two OCI images artifacts and combine with an -[image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md). The current [distribution spec](https://github.com/buildpacks/spec/blob/main/distribution.md#buildpackage) -defines: - -``` -Each buildpack layer blob MUST contain a single buildpack at the following file path: - -/cnb/buildpacks/<buildpack ID>/<buildpack version>/ -``` - -This means, we will end up duplicating the big file in each OCI images, for example our `linux/amd64` buildpack package -will have 1 layer with the following content under `/cnb/buildpacks/<buildpack ID>/<buildpack version>/` - -```bash -├── LICENSE -├── NOTICE -├── README.md -├── buildpack.toml -├── some-file // a file with a big size for example -├── resources -│ └── config.properties -└── bin - ├── build - ├── detect - └── foo -``` - -And the `linux/arm64` version will be similar but with the `bar` file inside the `bin/` folder, as a consequence, the big file -will be duplicated on two different layers increasing the space requirements in the registry - ## Builder Similar to how we did it for the `buildpack package`, lets summaries, our current process to create a **Builder**: @@ -1005,10 +936,6 @@ Tip: Run pack build <image-name> --builder <builder> to use this builder **Output**: We keep our current behavior and detect the `os` and `architecture` from the daemon. Because there is `target` that matches the daemon `os/arch` the builder is being built. -Using `--target` flag against the daemon with a different platform - -TODO check if this is possible! - <!-- ```bash pack builder create <builder> --config ./builder.toml --target linux/arm64 @@ -1091,6 +1018,8 @@ create [image indexes](https://github.com/opencontainers/image-spec/blob/master/ - What are the intermediate images for each target named/called? - What happen if I want to exclude some buildpack for a particular target? - What happen if I want to include the same file or folder for every image, do I have to copy then inside the {os}-{arch} folder? +- Initially we proposed a shared file strategy but, we decided to leave that complexity out of the scope of this RFC and can be +revisited later if it required # Spec. Changes (OPTIONAL) [spec-changes]: #spec-changes From f064a78eb002b3e88f01b3690b8fda2f39ab2c58 Mon Sep 17 00:00:00 2001 From: Juan Bustamante <jbustamante@vmware.com> Date: Wed, 14 Feb 2024 10:45:01 -0500 Subject: [PATCH 22/34] Fixing some format issues Signed-off-by: Juan Bustamante <jbustamante@vmware.com> --- text/0000-multiarch-builders-and-package.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text/0000-multiarch-builders-and-package.md b/text/0000-multiarch-builders-and-package.md index 359537d40..1f903dbdc 100644 --- a/text/0000-multiarch-builders-and-package.md +++ b/text/0000-multiarch-builders-and-package.md @@ -346,7 +346,7 @@ folder structure in the OCI image for each buildpack package will be: └── package.toml ``` -On the other hand, When target is `linux/arm64, the **platform root folder** determined is `<buildpack root folder>/linux/arm64` +On the other hand, When target is `linux/arm64`, the **platform root folder** determined is `<buildpack root folder>/linux/arm64` and the output OCI image folder structure looks like: ```bash . @@ -384,12 +384,12 @@ let end users know things are changing. ```bash pack buildpack package <buildpack> --config ./package.toml --publish -Warning: A new '--target' flag is available to set the platform for the buildpack package, using 'linux/amd64' as default +Warning: A new '--target' flag is available to set the platform for the buildpack package, using 'linux' as default Successfully published package <buildpack> and saved to registry # Or pack buildpack package <buildpack> --config ./package.toml --format file -Warning: A new '--target' flag is available to set the platform for the buildpack package, using 'linux/amd64' as default +Warning: A new '--target' flag is available to set the platform for the buildpack package, using 'linux' as default Successfully created package <buildpack> and saved to file ``` **Output**: pack will create a buildpack package image (as it is doing it today) with the provided binaries and a From 335a57ddb6b0992f0db1c6cae62103c920b2e9a5 Mon Sep 17 00:00:00 2001 From: Juan Bustamante <jbustamante@vmware.com> Date: Wed, 21 Feb 2024 15:32:26 -0500 Subject: [PATCH 23/34] removing mandataroy comment from packaga.toml Signed-off-by: Juan Bustamante <jbustamante@vmware.com> --- text/0000-multiarch-builders-and-package.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text/0000-multiarch-builders-and-package.md b/text/0000-multiarch-builders-and-package.md index 1f903dbdc..f9521abeb 100644 --- a/text/0000-multiarch-builders-and-package.md +++ b/text/0000-multiarch-builders-and-package.md @@ -244,7 +244,7 @@ this will be the way for end-users to specify the platform for which they want t # Option 1 - no variant is required . ├── buildpack.toml // mandatory -├── package.toml // mandatory +├── package.toml └── {os} // optional └── {arch} // optional (becomes the platform root folder) └── bin @@ -254,7 +254,7 @@ this will be the way for end-users to specify the platform for which they want t # Option 2 - variant is required . ├── buildpack.toml // mandatory -├── package.toml // mandatory +├── package.toml └── {os} // optional └── {arch} // optional └── {variant} // optional From 14e3265c8274fa7ecb53ee06737c0b97e7c90264 Mon Sep 17 00:00:00 2001 From: Juan Bustamante <jbustamante@vmware.com> Date: Fri, 1 Mar 2024 12:10:05 -0500 Subject: [PATCH 24/34] removing package.toml to be mandatory, it is not! and adding some logic when exporting multi-arch buildpack packages as files Signed-off-by: Juan Bustamante <jbustamante@vmware.com> --- text/0000-multiarch-builders-and-package.md | 76 ++++++++++++++++----- 1 file changed, 59 insertions(+), 17 deletions(-) diff --git a/text/0000-multiarch-builders-and-package.md b/text/0000-multiarch-builders-and-package.md index f9521abeb..a44bf77a2 100644 --- a/text/0000-multiarch-builders-and-package.md +++ b/text/0000-multiarch-builders-and-package.md @@ -220,6 +220,7 @@ As a quick summary, our current process to create a buildpack package involves: - The end-users defined `os` for the OCI image using the [package.toml](https://buildpacks.io/docs/reference/config/package-config/). - The only values allowed are `linux` and `windows` and by default when is not present, `linux` is being used. - When exporting to daemon, the `docker.OSType` must be equal to `platform.os` +- When building a single buildpack package, `package.toml` is optional ### To keep compatibility @@ -244,7 +245,6 @@ this will be the way for end-users to specify the platform for which they want t # Option 1 - no variant is required . ├── buildpack.toml // mandatory -├── package.toml └── {os} // optional └── {arch} // optional (becomes the platform root folder) └── bin @@ -254,7 +254,6 @@ this will be the way for end-users to specify the platform for which they want t # Option 2 - variant is required . ├── buildpack.toml // mandatory -├── package.toml └── {os} // optional └── {arch} // optional └── {variant} // optional @@ -268,7 +267,6 @@ this will be the way for end-users to specify the platform for which they want t └── detect // platform dependant binary (mandatory) ``` - `buildpack.toml` file MUST be present at the **buildpack root folder** -- `package.toml` file MUST be present at the **buildpack root folder** - For each platform, Buildpack Authors are responsible for copying or creating symlink or hard link for files into each **platform root folder** > **Note** @@ -285,7 +283,6 @@ Based on the [RFC-0096](https://github.com/buildpacks/rfcs/blob/main/text/0096-r os = "<operating system>" arch = "<system architecture>" variant = "<architecture variant>" - # optional path = "<path to look for the binaries if the folder structure convention is not followed>" @@ -294,11 +291,16 @@ name = "<distribution ID>" versions = ["<distribution version>"] ``` - When `more than 1 target is defined` - - When `--publish` or `--format file` is specified + - When `--publish` is specified - For each `target` an OCI image will be created, following these rules - `pack` will determine the **platform root folder**, this is the specific root folder for a given `target` (based on the `targets.path` in the buildpack.toml or inferring it from a folder structure similar to the one show above) - `pack` will execute the current process to create a buildpack package using the **platform root folder** and the `target` values - If more than 1 OCI image was created, an [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) will be created to combine them + - When `--format file` is specified AND `<file-name>` is the expected name for the `.cnb` file + - For each `target` an OCI layout file will be created, following these rules + - `pack` will determine the **platform root folder**, this is the specific root folder for a given `target` (based on the `targets.path` in the buildpack.toml or inferring it from a folder structure similar to the one show above) + - `pack` will execute the current process to create a buildpack package (.cnb file) using the **platform root folder** and the `target` values + - `pack` will saved on disk the `.cnb` file with a name `<file-name>-[os][-arch][-variant]-[name@version].cnb` - When `--daemon` is specified - `pack` can keep using `docker.OSType` to determine the target `os` and probably can do some validations it the `os` is valid target @@ -312,8 +314,7 @@ Let's suppose the Buildpack Author creates a multi-arch folder structure and wan ```bash . -├── buildpack.toml -├── package.toml +├── buildpack.toml └── linux ├── amd64 │ └── bin @@ -342,8 +343,7 @@ folder structure in the OCI image for each buildpack package will be: │ ├── build │ ├── detect │ └── foo // specific platform binary - ├── buildpack.toml - └── package.toml + └── buildpack.toml ``` On the other hand, When target is `linux/arm64`, the **platform root folder** determined is `<buildpack root folder>/linux/arm64` @@ -359,14 +359,13 @@ and the output OCI image folder structure looks like: │ ├── build │ └── detect ├── buildpack.toml - ├── foo - └── package.toml + └── foo ``` -#### Buildpacks authors do not use targets AND `platform.os` is not present at `package.toml` +#### Buildpacks authors do not use targets or the new folder structure -This seems to be the case for [Paketo Buildpacks](https://github.com/paketo-buildpacks/java/blob/main/package.toml) -or [Heroku](https://github.com/heroku/buildpacks-jvm/blob/main/meta-buildpacks/java/package.toml), and it represents how `pack` +This seems to be the case for [Paketo Buildpacks](https://github.com/paketo-buildpacks/maven) +or [Heroku](https://github.com/heroku/buildpacks-jvm/tree/main/buildpacks/maven), and it represents how `pack` will work for most the users when new behavior is implemented A simplified version of Buildpack Authors folder structures is: @@ -487,7 +486,7 @@ uri = "<A URL or path to an archive, or a path to a directory>" [platform] os = "linux" ``` -These cases are similar to the previous one, but we the warning message will be changed. +These cases are similar to the previous one, but the warning message will be changed. ```bash pack buildpack package <buildpack> --config ./package.toml --publish @@ -537,8 +536,7 @@ Let's suppose a buildpack folder structure like: ├── bin │ ├── build │ └── detect -├── buildpack.toml -└── package.toml +└── buildpack.toml ``` And a `buildpack.toml` with `targets` defined as: @@ -747,6 +745,50 @@ with a content similar to: If the Buildpack Author wants to create a single buildpack package they will use the `target` flag, similar to our previous examples. +## Composite Buildpack Package + +When packaging a composite buildpack we need a `package.toml` to declare the dependencies, this could be improved and there is an [issue](https://github.com/buildpacks/pack/issues/1082) for it +but today the `package.toml` is mandatory on `pack`. Also, it's important to remember that **we can't** use `targets` in the `buildpack.toml` when we also need to declare an `order` so this open +the question: + +**Where do we define targets for composite buildpacks?** +The natural answer will be `package.toml`, as it already defines the dependencies, it seems very straight forward to include this section for this particular case. The new schema will look like: + +```toml +[buildpack] +uri = "<A URL or path to an archive, or a path to a directory. If path is relative, it must be relative to the package.toml>" + +[[targets]] +os = "<operating system>" +arch = "<system architecture>" +variant = "<architecture variant>" + +[[targets.distributions]] +name = "<distribution ID>" +versions = ["<distribution version>"] + +[[dependencies]] +uri = "<A URL or path to an archive, a packaged buildpack (saved as a .cnb file), or a directory. If path is relative, it must be relative to the package.toml>" + +# Deprecated +[platform] +os = "<The operating system type that the buildpackage will run on. Only linux or windows is supported. If omitted, linux will be the default.>" +``` + +This information will help `pack` to determine a multi-arch composite buildpack is expected, but there is another +problem to solve, currently, the dependencies can be located in several places: + - OCI Registry + - Local file in the filesystem (.cnb) file + - Local folder in the filesystem + - A .tar.gz file in a remote S3 bucket accessible through HTTPS + +**How will pack find the correct artifact for each target?** + +For the OCI registry case, we'd expect Buildpack Authors to release multi-arch single buildpacks behind an +[image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md) and pulling these dependencies +will be a natural process, this will be the **only valid** locator in the `dependencies.uri` in cases where a multi-arch +composite buildpack is expected to be built. + ## Builder Similar to how we did it for the `buildpack package`, lets summaries, our current process to create a **Builder**: From 0f5303144ec905513d50e52a8c68fbf24f575394 Mon Sep 17 00:00:00 2001 From: Juan Bustamante <jbustamante@vmware.com> Date: Wed, 27 Mar 2024 10:42:43 -0500 Subject: [PATCH 25/34] Apply suggestions from code review Co-authored-by: Rune Soerensen <runesoerensen@gmail.com> Signed-off-by: Juan Bustamante <bustamantejj@gmail.com> Signed-off-by: Juan Bustamante <jbustamante@vmware.com> --- text/0000-multiarch-builders-and-package.md | 30 ++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/text/0000-multiarch-builders-and-package.md b/text/0000-multiarch-builders-and-package.md index a44bf77a2..a48fa8e8c 100644 --- a/text/0000-multiarch-builders-and-package.md +++ b/text/0000-multiarch-builders-and-package.md @@ -13,7 +13,7 @@ [summary]: #summary The problem for adding support for multi-arch buildpacks can be divided into three parts: -1. Support buildpack authors to **migrate their existing buildpacks** to support multi-arch. +1. Support buildpack authors to **migrate their existing buildpacks** to support multiple operating systems, architectures, variants and distros. 2. Support buildpack authors to **create new buildpacks and builders** that handle multi-arch from the beginning. 3. Support application developers to **create application images** using multi-arch buildpacks and builders. @@ -235,7 +235,7 @@ a new `--target` flag is available and how to use it, or some helpful informatio ### To improve user experience We propose: -- Add a new `--target` flag with the follwing format `[os][/arch][/variant]:[name@version]` to build for a particular target, once the `platform.os` field is removed, +- Add a new `--target` flag using the format `[os][/arch][/variant]:[name@version]` to build for a particular target, once the `platform.os` field is removed, this will be the way for end-users to specify the platform for which they want to create single OCI artifact. - Add `targets` section to `buildpack.toml` to help Buildpack Authors to include support for new platforms without having to update their `pack buildpack package` command in their CI/CD pipelines @@ -248,8 +248,8 @@ this will be the way for end-users to specify the platform for which they want t └── {os} // optional └── {arch} // optional (becomes the platform root folder) └── bin - ├── build // platform dependant binary (mandatory) - └── detect // platform dependant binary (mandatory) + ├── build // platform dependent binary (mandatory) + └── detect // platform dependent binary (mandatory) # Option 2 - variant is required . @@ -259,22 +259,22 @@ this will be the way for end-users to specify the platform for which they want t └── {variant} // optional ├── {name@version-1} // optional (becomes the platform root folder) │ └── bin - │ ├── build // platform dependant binary (mandatory) - │ └── detect // platform dependant binary (mandatory) + │ ├── build // platform dependent binary (mandatory) + │ └── detect // platform dependent binary (mandatory) └── {name@version-2} // optional (becomes the platform root folder) └── bin - ├── build // platform dependant binary (mandatory) - └── detect // platform dependant binary (mandatory) + ├── build // platform dependent binary (mandatory) + └── detect // platform dependent binary (mandatory) ``` -- `buildpack.toml` file MUST be present at the **buildpack root folder** +- `buildpack.toml` file MUST be present in the **buildpack root folder** - For each platform, Buildpack Authors are responsible for copying or creating symlink or hard link for files into each **platform root folder** > **Note** > For cross-compile buildpacks like Paketo, it looks easy to add a step to their Makefile to compile and separate the binaries following this structure. It is important to mention > that the final buildpack image will not change, this will only change the buildpack structure from `pack` perspective -In case, this folder structure is not suitable for Buildpack Authors, **we propose** a new `path` attribute to be included -into the `target` section of the `buildpack.toml` to specify where the **buildapck root directoy** is located in the filesystem. +In case this folder structure is not suitable for Buildpack Authors, **we propose** a new `path` attribute to be included +in the `targets` section of the `buildpack.toml`, to specify where the **buildpack root directory** is located in the filesystem. Based on the [RFC-0096](https://github.com/buildpacks/rfcs/blob/main/text/0096-remove-stacks-mixins.md) the new `buildpack.toml` schema will look like this: @@ -428,7 +428,7 @@ platform: > Pack will assume the binaries are appropriate for the given target platform, what the flag is doing is expose a mechanism > to update the metadata present in the OCI config file -what about creating a multi-arch image for several target platforms? +what about creating a multi-platform image for several targets? ```bash pack buildpack package <buildpack> --config ./package.toml --publish --target linux/arm64 --target linux/amd64 @@ -464,7 +464,7 @@ will be similar to: "digest": "sha256:2589fe6bcf90466564741ae0d8309d1323f33b6ec8a5d401a62d0b256bcc3c37", "mediaType": "application/vnd.oci.image.manifest.v1+json", "platform": { - "architecture": "arm", + "architecture": "arm64", "os": "linux" }, "size": 424 @@ -817,7 +817,7 @@ We propose: - Add `targets` section to the `builder.toml` schema, this will keep consistency for end-users to understand how to define multi-architecture. Adding more than one target to the `builder.toml` will be considered by `pack` as an -acknowledgement of the desired to generate multi-arch [Builders](https://buildpacks.io/docs/concepts/components/builder/). +acknowledgement of the desire to generate [Builders](https://buildpacks.io/docs/concepts/components/builder/) with multiple platform targets. The new schema will be similar to: @@ -1056,7 +1056,7 @@ create [image indexes](https://github.com/opencontainers/image-spec/blob/master/ # Unresolved Questions [unresolved-questions]: #unresolved-questions -- If I already have an [image indexe](https://github.com/opencontainers/image-spec/blob/master/image-index.md) created and I want to add support for new plaform, how do I do it? +- How would I add support for a new platform to an existing [image index](https://github.com/opencontainers/image-spec/blob/master/image-index.md)? - What are the intermediate images for each target named/called? - What happen if I want to exclude some buildpack for a particular target? - What happen if I want to include the same file or folder for every image, do I have to copy then inside the {os}-{arch} folder? From abd3ba28d7648e03a9c2074a88dae9fe3b069683 Mon Sep 17 00:00:00 2001 From: Juan Bustamante <jbustamante@vmware.com> Date: Wed, 27 Mar 2024 10:46:24 -0500 Subject: [PATCH 26/34] Apply suggestions from code review Co-authored-by: Rune Soerensen <runesoerensen@gmail.com> Signed-off-by: Juan Bustamante <bustamantejj@gmail.com> Signed-off-by: Juan Bustamante <jbustamante@vmware.com> --- text/0000-multiarch-builders-and-package.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/text/0000-multiarch-builders-and-package.md b/text/0000-multiarch-builders-and-package.md index a48fa8e8c..d43f1ae7d 100644 --- a/text/0000-multiarch-builders-and-package.md +++ b/text/0000-multiarch-builders-and-package.md @@ -1,6 +1,6 @@ # Meta [meta]: #meta -- Name: Multi-arch support for builders and buildpack packages +- Name: Multi-platform support for builders and buildpack packages - Start Date: 2023-09-14 - Author(s): @jjbustamante - Status: Draft <!-- Acceptable values: Draft, Approved, On Hold, Superseded --> @@ -12,7 +12,7 @@ # Summary [summary]: #summary -The problem for adding support for multi-arch buildpacks can be divided into three parts: +The problem for adding support for multi-platform buildpacks can be divided into three parts: 1. Support buildpack authors to **migrate their existing buildpacks** to support multiple operating systems, architectures, variants and distros. 2. Support buildpack authors to **create new buildpacks and builders** that handle multi-arch from the beginning. 3. Support application developers to **create application images** using multi-arch buildpacks and builders. @@ -240,7 +240,7 @@ this will be the way for end-users to specify the platform for which they want t - Add `targets` section to `buildpack.toml` to help Buildpack Authors to include support for new platforms without having to update their `pack buildpack package` command in their CI/CD pipelines -- A new folder structure to organize the buildpacks binaries for multi-arch images, similar to this one: +- A new folder structure to organize the buildpacks binaries for multi-platform images, similar to this one: ```bash # Option 1 - no variant is required . @@ -310,7 +310,7 @@ Let's use some examples to explain the expected behavior in different use cases #### How to determine the platform root folder -Let's suppose the Buildpack Author creates a multi-arch folder structure and wants to create multiple buildpack packages +Let's suppose the Buildpack Author creates a multi-platform folder structure and wants to create multiple buildpack packages ```bash . @@ -432,7 +432,7 @@ what about creating a multi-platform image for several targets? ```bash pack buildpack package <buildpack> --config ./package.toml --publish --target linux/arm64 --target linux/amd64 -A multi-arch buildpack package will be created for target platforms: 'linux/amd64', 'linux/arm64' +A multi-platform buildpack package will be created for: 'linux/amd64', 'linux/arm64' Successfully published package <buildpack> and saved to registry # Or @@ -693,7 +693,7 @@ id = "*" When Buildpack Authors want to create a multi-arch images, they can execute the following command: ```bash pack buildpack package <buildpack> --config ./package.toml --publish -Info: A multi-arch buildpack package will be created for target platforms: 'linux/amd64', 'linux/arm64', 'windows/amd64' +Info: A multi-platform buildpack package will be created for targets: 'linux/amd64', 'linux/arm64', 'windows/amd64' Successfully published package <buildpack> and saved to registry ``` A fully multi-arch buildpack will be created automatically, because we have more than one target defined @@ -1002,7 +1002,7 @@ What about multi-architecture builders? ```bash pack builder create <builder> --config ./builder.toml --publish -Info: A multi-arch builder will be created for targets platform: 'linux/amd64', 'linux/arm64' +Info: A multi-platform builder will be created for targets: 'linux/amd64', 'linux/arm64' Successfully created builder image <builder> Tip: Run pack build <image-name> --builder <builder> to use this builder ``` @@ -1014,7 +1014,7 @@ pack builder create <builder> --config ./builder.toml \ --target linux/amd64 \ --target linux/arm64 \ --publish -Info: A multi-arch builder will be created for targets platform: 'linux/amd64', 'linux/arm64' +Info: A multi-platform builder will be created for targets: 'linux/amd64', 'linux/arm64' Successfully created builder image <builder> Tip: Run pack build <image-name> --builder <builder> to use this builder ``` From 822d70252536a5fe87db879bd38e87fde169c261 Mon Sep 17 00:00:00 2001 From: Natalie Arellano <narellano@vmware.com> Date: Wed, 10 Apr 2024 10:42:56 -0400 Subject: [PATCH 27/34] RFC 0128 [#295] Signed-off-by: Natalie Arellano <narellano@vmware.com> --- ...nd-package.md => 0128-multiarch-builders-and-package.md} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename text/{0000-multiarch-builders-and-package.md => 0128-multiarch-builders-and-package.md} (99%) diff --git a/text/0000-multiarch-builders-and-package.md b/text/0128-multiarch-builders-and-package.md similarity index 99% rename from text/0000-multiarch-builders-and-package.md rename to text/0128-multiarch-builders-and-package.md index d43f1ae7d..3d3844985 100644 --- a/text/0000-multiarch-builders-and-package.md +++ b/text/0128-multiarch-builders-and-package.md @@ -3,10 +3,10 @@ - Name: Multi-platform support for builders and buildpack packages - Start Date: 2023-09-14 - Author(s): @jjbustamante -- Status: Draft <!-- Acceptable values: Draft, Approved, On Hold, Superseded --> -- RFC Pull Request: (leave blank) +- Status: Approved +- RFC Pull Request: [rfcs#295](https://github.com/buildpacks/rfcs/pull/295) - CNB Pull Request: (leave blank) -- CNB Issue: (leave blank) +- CNB Issue: N/A - Supersedes: (put "N/A" unless this replaces an existing RFC, then link to that RFC) # Summary From 8c2a6a0bdc1b49d5e3d537bc6508e30fb5276c85 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Wed, 27 Mar 2024 23:43:12 +0000 Subject: [PATCH 28/34] Update RFC96 to match what landed in the spec A few changes were made to what was in the RFC when it came to update the spec. This backports those changes to the RFC to try and prevent user confusion if they use the RFC as a means of learning about targets when implementing. Specifically: - The `io.buildpacks.distribution.*` Docker labels were renamed to `io.buildpacks.base.distro.*`. - The `io.buildpacks.id` Docker label was renamed to `io.buildpacks.base.id`. - The `buildpack.toml` table `[[targets.distributions]]` was renamed to `[[targets.distros]]` and the `versions` field within it renamed to `version` (along with its type changing from an array to a string). See: https://github.com/buildpacks/spec/blob/platform/0.13/platform.md#target-data Signed-off-by: Ed Morley <501702+edmorley@users.noreply.github.com> --- text/0096-remove-stacks-mixins.md | 44 ++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 12 deletions(-) diff --git a/text/0096-remove-stacks-mixins.md b/text/0096-remove-stacks-mixins.md index 34f17ea98..10a584e5d 100644 --- a/text/0096-remove-stacks-mixins.md +++ b/text/0096-remove-stacks-mixins.md @@ -41,11 +41,11 @@ Instead of a stack ID, runtime and build-time base images must contain the follo - OS (e.g., "linux", `$GOOS`), specified as `os` in the base image `config` - Architecture (e.g., "arm", `$GOARCH`), specified as `architecture` in the base image `config` - Architecture Variant (optional) (e.g., "v6", `$GOARM`), specified as `variant` in the base image `config` -- Distribution (optional) (e.g., "ubuntu", `$ID`), specified as a label `io.buildpacks.distribution.name` -- Version (optional) (e.g., "18.04", `$VERSION_ID`), specified as a label `io.buildpacks.distribution.version` +- Distribution (optional) (e.g., "ubuntu", `$ID`), specified as a label `io.buildpacks.base.distro.name` +- Version (optional) (e.g., "18.04", `$VERSION_ID`), specified as a label `io.buildpacks.base.distro.version` Additionally, the runtime base may contain the following metadata: -- Target ID (optional) (e.g., "minimal"), specified as a label `io.buildpacks.id` +- Target ID (optional) (e.g., "minimal"), specified as a label `io.buildpacks.base.id` OS, Architecture, and Architecture Variant must be valid identifiers as defined in the [OCI Image specification](https://github.com/opencontainers/image-spec/blob/main/config.md). @@ -53,7 +53,7 @@ Target ID is an identifier specified on the runtime base image that must be prov This allows buildpacks to change their behavior if a run image is selected (e.g., distroless) that has special properties outside of OS, architecture, etc. For Linux-based images, each field should be canonicalized against values specified in `/etc/os-release` (`$ID` and `$VERSION_ID`). -The `os.version` field in an base image `config` may contain combined distribution and version information, but it is not used by the lifecycle. +The `os.version` field in a base image `config` may contain combined distribution and version information, but it is not used by the lifecycle. For Windows-based images, Distribution should be empty. Version should be the [suggested value of `os.version`](https://github.com/opencontainers/image-spec/blob/main/config.md#properties) in the OCI spec (e.g., `10.0.14393.1066`). @@ -81,17 +81,17 @@ versions = ["18.04", "20.04"] [[targets]] os = "linux" arch = "amd64" -[[targets.distributions]] +[[targets.distros]] name = "ubuntu" -versions = ["14.04", "16.04"] +version = "16.04" [[targets]] os = "linux" arch = "arm" variant = "v6" -[[targets.distributions]] +[[targets.distros]] name = "ubuntu" -versions = ["14.04", "16.04"] +version = "16.04" ``` ## Runtime Metadata @@ -153,11 +153,11 @@ If the newly-specified field values are missing, the lifecycle and pack may used ``` config.os = "linux" config.architecture = "amd64" -io.buildpacks.distribution.name = "ubuntu" -io.buildpacks.distribution.version = "18.04" +io.buildpacks.base.distro.name = "ubuntu" +io.buildpacks.base.distro.version = "18.04" ``` -Moving forward it's encouraged for buildpack authors to support both `[[stacks]]` and `[[targets]]` sections in `buildpack.toml` for maximum compatibility. In order to ease this process for those using the `io.buildpacks.stacks.bionic`, lifecycle will translate any section that sets this as on of the `stacks`: +Moving forward it's encouraged for buildpack authors to support both `[[stacks]]` and `[[targets]]` sections in `buildpack.toml` for maximum compatibility. In order to ease this process for those using the `io.buildpacks.stacks.bionic`, lifecycle will translate any section that sets this as one of the `stacks`: ```toml [[stacks]] @@ -170,7 +170,7 @@ to [[targets]] os = "linux" arch = "amd64" -[[targets.distributions]] +[[targets.distros]] name = "ubuntu" versions = ["18.04"] ``` @@ -210,3 +210,23 @@ rename x86_64 -> amd64 in keeping with all other usages of arch. descriptors. ### Motivation This is how we do it everywhere else, this is the way. + +## Amended +### Meta +[meta-1]: #meta-1 +- Name: Rename Docker labels and `buildpack.toml` table names +- Start Date: 2024-04-08 +- Author(s): @edmorley +- Amendment Pull Request: [rfcs#310](https://github.com/buildpacks/rfcs/pull/310) + +### Summary + +Changes were made to the Docker label and `buildpack.toml` table names between when this RFC was written and the changes were made to the spec in [spec#365](https://github.com/buildpacks/spec/pull/365), which have now been backported to the RFC: + +- The `io.buildpacks.distributions.*` Docker labels were renamed to `io.buildpacks.base.distro.*`. +- The `io.buildpacks.id` Docker label was renamed to `io.buildpacks.base.id`. +- The `buildpack.toml` table `[[targets.distributions]]` was renamed to `[[targets.distros]]` and the `versions` field within it renamed to `version` (along with its type changing from an array to a string). + +### Motivation + +To prevent use of the wrong Docker label or `buildpack.toml` table names, if users base their implementations on the RFC rather than reading the spec. From 55cfde33a629f126b7de3b07b4e84fea383f0d81 Mon Sep 17 00:00:00 2001 From: Ed Morley <501702+edmorley@users.noreply.github.com> Date: Thu, 11 Apr 2024 17:39:49 +0100 Subject: [PATCH 29/34] RFC 0128: Use correct `[[targets.distros]]` schema Updates RFC 0128 to use the correct `[[targets.distros]]` schema as defined already in the spec: https://github.com/buildpacks/spec/blob/main/buildpack.md#buildpacktoml-toml I've not added an `## Amended` section, since: 1. The RFC has only just merged (this is effectively a review comment that missed the merge by a day) 2. The parts of the RFC being fixed are existing concepts already in the spec, rather than design decisions relating to the purpose of the RFC itself. Fixes: https://github.com/buildpacks/rfcs/pull/295#discussion_r1559614121 Signed-off-by: Ed Morley <501702+edmorley@users.noreply.github.com> --- text/0128-multiarch-builders-and-package.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/text/0128-multiarch-builders-and-package.md b/text/0128-multiarch-builders-and-package.md index 3d3844985..e36d1d2bc 100644 --- a/text/0128-multiarch-builders-and-package.md +++ b/text/0128-multiarch-builders-and-package.md @@ -95,9 +95,9 @@ arch = "arm64" os = "windows" arch = "amd64" -[[targets.distributions]] +[[targets.distros]] name = "windows" -versions = ["10.0.20348.1970"] +version = "10.0.20348.1970" # Stacks (deprecated) the buildpack will work with [[stacks]] @@ -286,9 +286,9 @@ variant = "<architecture variant>" # optional path = "<path to look for the binaries if the folder structure convention is not followed>" -[[targets.distributions]] +[[targets.distros]] name = "<distribution ID>" -versions = ["<distribution version>"] +version = "<distribution version>" ``` - When `more than 1 target is defined` - When `--publish` is specified @@ -681,9 +681,9 @@ arch = "arm64" os = "windows" arch = "amd64" -[[targets.distributions]] +[[targets.distros]] name = "windows" -versions = ["10.0.20348.1970"] +version = "10.0.20348.1970" # Stacks (deprecated) the buildpack will work with [[stacks]] @@ -763,9 +763,9 @@ os = "<operating system>" arch = "<system architecture>" variant = "<architecture variant>" -[[targets.distributions]] +[[targets.distros]] name = "<distribution ID>" -versions = ["<distribution version>"] +version = "<distribution version>" [[dependencies]] uri = "<A URL or path to an archive, a packaged buildpack (saved as a .cnb file), or a directory. If path is relative, it must be relative to the package.toml>" @@ -843,9 +843,9 @@ image = "<build image reference>" os = "<operating system>" arch = "<system architecture>" variant = "<architecture variant>" -[[targets.distributions]] +[[targets.distros]] name = "<distribution ID>" -versions = ["<distribution version>"] +version = "<distribution version>" ``` - Add a new `--target` optional flag with format `[os][/arch][/variant]:[name@version]` to create a builder for a particular target, this will help end-users to specify the platform for which they want to create single OCI artifact. From 6c56aa24356633773b000f72e9a7b074306eda32 Mon Sep 17 00:00:00 2001 From: Joey Brown <brown.joseph@salesforce.com> Date: Thu, 11 Apr 2024 14:52:28 -0500 Subject: [PATCH 30/34] export run image metadata Signed-off-by: Joey Brown <brown.joseph@salesforce.com> --- text/0000-export-run-image-metadata.md | 121 +++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 text/0000-export-run-image-metadata.md diff --git a/text/0000-export-run-image-metadata.md b/text/0000-export-run-image-metadata.md new file mode 100644 index 000000000..6ef3802fa --- /dev/null +++ b/text/0000-export-run-image-metadata.md @@ -0,0 +1,121 @@ +# Meta +[meta]: #meta +- Name: Export Run Image Metadata +- Start Date: 2024-04-11 +- Author(s): joeybrown-sf +- Status: Draft <!-- Acceptable values: Draft, Approved, On Hold, Superseded --> +- RFC Pull Request: (leave blank) +- CNB Pull Request: (leave blank) +- CNB Issue: (leave blank) +- Supersedes: N/A + +# Summary +[summary]: #summary + +The `report.toml` file created by the lifecycle exporter and rebaser should include `run-image.image`, `run-image.reference`, and `run-image.top-layer`. These values can be critical to a platform rebase process. + +# Motivation +[motivation]: #motivation + +When publishing an image directly to a registry, parsing the [`lifecycle.metadata` label](https://github.com/buildpacks/spec/blob/main/platform.md#iobuildpackslifecyclemetadata-json) is inefficient--it requires a call to the registry after the image is published. Adding these values to `report.toml` lets platforms efficiently access this data after an export or rebase without a call to the registry. + +# What it is +[what-it-is]: #what-it-is + +These values will be included when the lifecycle exporter/creator/rebaser binary writes `report.toml`. + +Here are two examples of `report.toml` content. (Other values are omitted for readability.) + +#### Image published to a registry: +``` +[image] +tags = ... +digest = ... +image-id = ... +manifest-size = ... + +[run-image] +image = "run/name:foo" +reference = "index.docker.io/run/name@sha256:94f85561b0976bf1e2bef6b14de92299ebcd4c8148802cf9b217654651e4f416" +top-layer = "sha256:83ad2f0b091621ce19357e19d853c8be1b8f4d60d99c281fc2db75e0f56df42a" +``` + +#### Image exported to the docker daemon: +``` +[image] +tags = ... +digest = ... +image-id = ... +manifest-size = ... + +[run-image] +image = "run/name:foo" +reference = "5b90f9c0e189" +top-layer = "sha256:83ad2f0b091621ce19357e19d853c8be1b8f4d60d99c281fc2db75e0f56df42a" +``` + +# How it Works +[how-it-works]: #how-it-works + +This metadata is readily available when `report.toml` is created, so it will be straight-forward to extend `report.toml`. + +# Migration +[migration]: #migration + +N/A + +This is an additive change to a metadata file and will be backwards compatible. + +# Drawbacks +[drawbacks]: #drawbacks + +This metadata is written to the [`lifecycle.metadata` label](https://github.com/buildpacks/spec/blob/main/platform.md#iobuildpackslifecyclemetadata-json). It can be accessed by querying the config from docker daemon or registry. So we will be writing this data to two outputs. + +# Alternatives +[alternatives]: #alternatives + +Do nothing and continue to require platforms to retrieve this information via alternative means--either querying the docker daemon or registry. + +Introduce a new output file (`lifecycle-metadata.toml?`) that contains everything in [`lifecycle.metadata` label](https://github.com/buildpacks/spec/blob/main/platform.md#iobuildpackslifecyclemetadata-json). + +# Prior Art +[prior-art]: #prior-art + +These values are among those that `pack inspect` returns. + +# Unresolved Questions +[unresolved-questions]: #unresolved-questions + +N/A + +# Spec. Changes +[spec-changes]: #spec-changes + +The following would be appended to the [`report.toml` spec](https://github.com/buildpacks/spec/blob/main/platform.md#reporttoml-toml) (this section would be materially identical to the [`lifecycle.metadata` label](https://github.com/buildpacks/spec/blob/main/platform.md#iobuildpackslifecyclemetadata-json)): + +> run-image.top-layer MUST contain the uncompressed digest of the top layer of the run-image. +> +>run-image.reference MUST uniquely identify the run image. It MAY contain one of the following +> - An image ID (the digest of the uncompressed config blob) +> - A digest reference to a manifest stored in an OCI registry + +# History +[history]: #history + +<!-- +## Amended +### Meta +[meta-1]: #meta-1 +- Name: (fill in the amendment name: Variable Rename) +- Start Date: (fill in today's date: YYYY-MM-DD) +- Author(s): (Github usernames) +- Amendment Pull Request: (leave blank) + +### Summary + +A brief description of the changes. + +### Motivation + +Why was this amendment necessary? +---> From 0af349b834dc7396052fd97d1ed2d91894033b1f Mon Sep 17 00:00:00 2001 From: Joey Brown <brown.joseph@salesforce.com> Date: Thu, 18 Apr 2024 09:01:29 -0500 Subject: [PATCH 31/34] provide more motivation content & alternatives Signed-off-by: Joey Brown <brown.joseph@salesforce.com> --- text/0000-export-run-image-metadata.md | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/text/0000-export-run-image-metadata.md b/text/0000-export-run-image-metadata.md index 6ef3802fa..8d9922674 100644 --- a/text/0000-export-run-image-metadata.md +++ b/text/0000-export-run-image-metadata.md @@ -12,12 +12,16 @@ # Summary [summary]: #summary -The `report.toml` file created by the lifecycle exporter and rebaser should include `run-image.image`, `run-image.reference`, and `run-image.top-layer`. These values can be critical to a platform rebase process. +The `report.toml` file created by the lifecycle exporter and rebaser should include `run-image.image`, `run-image.reference`, and `run-image.top-layer`. These values are not necessarily known prior to export or rebase they can be critical to a platform rebase process. # Motivation [motivation]: #motivation -When publishing an image directly to a registry, parsing the [`lifecycle.metadata` label](https://github.com/buildpacks/spec/blob/main/platform.md#iobuildpackslifecyclemetadata-json) is inefficient--it requires a call to the registry after the image is published. Adding these values to `report.toml` lets platforms efficiently access this data after an export or rebase without a call to the registry. +Platform operators may need a comprehensive understanding of images on their platform in order to make decisions about rebase and image publishing. Run image metadata is likely part of this comprehensive understanding for rebase. It is likely that this data may only be known after an image is created or rebased, and today it is only accessible via reading the image. Therefore, in order to access this metadata, platform operators must query the image. + +Querying the docker daemon or querying an image registry is suboptimal and we should make this data more accessible. It is suboptimal because it requires the platform to run an additional service to query the data it just published. If we make this data more accessible, we could potentially reduce image queries (registry calls) calls by a significant factor. + +Putting this data into `report.toml` is advantageous over other methods, especially when considering the kubernetes `terminationMessagePath` message [pattern](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#pod-v1-core). In this pattern, the content of `report.toml` can be used as a container's termination message, making this data easily accessible after an image is exported or rebased within a kubernetes container. # What it is [what-it-is]: #what-it-is @@ -69,19 +73,27 @@ This is an additive change to a metadata file and will be backwards compatible. # Drawbacks [drawbacks]: #drawbacks -This metadata is written to the [`lifecycle.metadata` label](https://github.com/buildpacks/spec/blob/main/platform.md#iobuildpackslifecyclemetadata-json). It can be accessed by querying the config from docker daemon or registry. So we will be writing this data to two outputs. +This metadata is written to the [`lifecycle.metadata` label](https://github.com/buildpacks/spec/blob/main/platform.md#iobuildpackslifecyclemetadata-json) and it can be accessed by querying a docker daemon or registry. So we will be writing this data to two outputs. # Alternatives [alternatives]: #alternatives -Do nothing and continue to require platforms to retrieve this information via alternative means--either querying the docker daemon or registry. +1. Do nothing and continue to require platforms to retrieve this information via alternative means--either querying the docker daemon or registry. + - Rebase process may remain suboptimal for some platform providers. + +2. Write all the metadata labels to `report.toml`. + - This could break platform operators that are using the `terminationMessagePath` [pattern](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#pod-v1-core). Because some of the metadata includes unbounded arrays, we could explode this report beyond the max size of 4096 bytes. -Introduce a new output file (`lifecycle-metadata.toml?`) that contains everything in [`lifecycle.metadata` label](https://github.com/buildpacks/spec/blob/main/platform.md#iobuildpackslifecyclemetadata-json). +3. Write another file that contains this metadata (and potentially more metadata). + - If we consider this approach and take it to the logical conclusion, we should consider writing a sparse image as output. A sparse image would contain all the metadata available, and it would be in a well-known format that other image tools like `crane`, `skopeo`, or `pack` can read. + - Writing to another file is not as simple as writing to `report.toml`. + - It increases the complexity of lifecycle exporter & rebaser. + - Writing to another file would not give platform operators the advantage of the `terminationMessagePath` [pattern](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.25/#pod-v1-core), because they are likely already reading `report.toml`. # Prior Art [prior-art]: #prior-art -These values are among those that `pack inspect` returns. +These values are written to image labels. And they are among values that `pack inspect` returns. # Unresolved Questions [unresolved-questions]: #unresolved-questions From 7ccbed177ec86c33b54c939fcbef543e9662d280 Mon Sep 17 00:00:00 2001 From: Joey Brown <brown.joseph@salesforce.com> Date: Thu, 18 Apr 2024 11:27:06 -0500 Subject: [PATCH 32/34] update to add mirrors and change casing Signed-off-by: Joey Brown <brown.joseph@salesforce.com> --- text/0000-export-run-image-metadata.md | 32 +++++++++++++++----------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/text/0000-export-run-image-metadata.md b/text/0000-export-run-image-metadata.md index 8d9922674..394a0c956 100644 --- a/text/0000-export-run-image-metadata.md +++ b/text/0000-export-run-image-metadata.md @@ -12,7 +12,13 @@ # Summary [summary]: #summary -The `report.toml` file created by the lifecycle exporter and rebaser should include `run-image.image`, `run-image.reference`, and `run-image.top-layer`. These values are not necessarily known prior to export or rebase they can be critical to a platform rebase process. +The `report.toml` file created by the lifecycle exporter and rebaser should include the following properties: +- `run-image.image` +- `run-image.mirrors` +- `run-image.reference` +- `run-image.top-layer` + +These values are not necessarily known prior to export or rebase they can be critical to a platform rebase process. # Motivation [motivation]: #motivation @@ -37,11 +43,10 @@ tags = ... digest = ... image-id = ... manifest-size = ... - -[run-image] -image = "run/name:foo" -reference = "index.docker.io/run/name@sha256:94f85561b0976bf1e2bef6b14de92299ebcd4c8148802cf9b217654651e4f416" -top-layer = "sha256:83ad2f0b091621ce19357e19d853c8be1b8f4d60d99c281fc2db75e0f56df42a" +run-image.image = "run/name:foo" +run-image.reference = "index.docker.io/run/name@sha256:94f85561b0976bf1e2bef6b14de92299ebcd4c8148802cf9b217654651e4f416" +run-image.top-layer = "sha256:83ad2f0b091621ce19357e19d853c8be1b8f4d60d99c281fc2db75e0f56df42a" +run-image.mirrors = ["<mirror1>", "<mirror2>"] ``` #### Image exported to the docker daemon: @@ -51,11 +56,10 @@ tags = ... digest = ... image-id = ... manifest-size = ... - -[run-image] -image = "run/name:foo" -reference = "5b90f9c0e189" -top-layer = "sha256:83ad2f0b091621ce19357e19d853c8be1b8f4d60d99c281fc2db75e0f56df42a" +run-image.image = "run/name:foo" +run-image.reference = "5b90f9c0e189" +run-image.top-layer = "sha256:83ad2f0b091621ce19357e19d853c8be1b8f4d60d99c281fc2db75e0f56df42a" +run-image.mirrors = ["<mirror1>", "<mirror2>"] ``` # How it Works @@ -105,11 +109,13 @@ N/A The following would be appended to the [`report.toml` spec](https://github.com/buildpacks/spec/blob/main/platform.md#reporttoml-toml) (this section would be materially identical to the [`lifecycle.metadata` label](https://github.com/buildpacks/spec/blob/main/platform.md#iobuildpackslifecyclemetadata-json)): -> run-image.top-layer MUST contain the uncompressed digest of the top layer of the run-image. +> runImage.topLayer MUST contain the uncompressed digest of the top layer of the run-image. > ->run-image.reference MUST uniquely identify the run image. It MAY contain one of the following +> runImage.reference MUST uniquely identify the run image. It MAY contain one of the following > - An image ID (the digest of the uncompressed config blob) > - A digest reference to a manifest stored in an OCI registry +> +> runImage.image and runImage.mirrors MUST be resolved from run.toml from the given <run-image> # History [history]: #history From fcbe0f3deb4f0d62ddf9381a3043de8119e6975a Mon Sep 17 00:00:00 2001 From: Joey Brown <brown.joseph@salesforce.com> Date: Thu, 18 Apr 2024 12:18:12 -0500 Subject: [PATCH 33/34] add a reference to the RFC that introduces report.toml Signed-off-by: Joey Brown <brown.joseph@salesforce.com> --- text/0000-export-run-image-metadata.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/text/0000-export-run-image-metadata.md b/text/0000-export-run-image-metadata.md index 394a0c956..6bd8013f7 100644 --- a/text/0000-export-run-image-metadata.md +++ b/text/0000-export-run-image-metadata.md @@ -99,6 +99,8 @@ This metadata is written to the [`lifecycle.metadata` label](https://github.com/ These values are written to image labels. And they are among values that `pack inspect` returns. +`report.toml` was introduced in [RFC 0040](/text/0040-export-report.md). That RFC includes some context for why `report.toml` exists. + # Unresolved Questions [unresolved-questions]: #unresolved-questions From fb53ceb92f323010516d3e9e932b185326092522 Mon Sep 17 00:00:00 2001 From: Jesse Brown <jabrown85@gmail.com> Date: Mon, 8 Jul 2024 14:55:23 -0500 Subject: [PATCH 34/34] Update and rename 0000-export-run-image-metadata.md to 0129-export-run-image-metadata.md Updating for merge Signed-off-by: Jesse Brown <jabrown85@gmail.com> Signed-off-by: Jesse Brown <jabrown85@gmail.com> --- ...-image-metadata.md => 0129-export-run-image-metadata.md} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename text/{0000-export-run-image-metadata.md => 0129-export-run-image-metadata.md} (96%) diff --git a/text/0000-export-run-image-metadata.md b/text/0129-export-run-image-metadata.md similarity index 96% rename from text/0000-export-run-image-metadata.md rename to text/0129-export-run-image-metadata.md index 6bd8013f7..124b24088 100644 --- a/text/0000-export-run-image-metadata.md +++ b/text/0129-export-run-image-metadata.md @@ -3,10 +3,10 @@ - Name: Export Run Image Metadata - Start Date: 2024-04-11 - Author(s): joeybrown-sf -- Status: Draft <!-- Acceptable values: Draft, Approved, On Hold, Superseded --> -- RFC Pull Request: (leave blank) +- Status: Approved <!-- Acceptable values: Draft, Approved, On Hold, Superseded --> +- RFC Pull Request: https://github.com/buildpacks/rfcs/pull/313 - CNB Pull Request: (leave blank) -- CNB Issue: (leave blank) +- CNB Issue: https://github.com/buildpacks/lifecycle/issues/1372 - Supersedes: N/A # Summary