buildpacks / libcnb

A non-opinionated language binding for the Cloud Native Buildpack Buildpack and Extension specifications
Apache License 2.0
32 stars 13 forks source link

Add support for buildpack extensions #230

Closed dmikusa closed 1 year ago

dmikusa commented 1 year ago

The extensions specification will require some changes but will allow users to write both buildpacks and extensions with libcnb.

This requires buildpacks API 0.9, so there is a question if this should be backported to 1.x.

BarDweller commented 1 year ago

The obvious extension changes would be to introduce

Main issues occur with things that could/should be common, but are unable to be so today.

Eg, detect phase is common to both extensions, and buildpacks, but DetectContext contains Buildpack (built from buildpack.toml) which would need to become mutually exclusive with a new Extension Struct. Much of Buildpack and Extension should be shared (Eg, Licenses, and much of the currently named 'BuildpackInfo')

Extension toml has this schema..

api = "<buildpack API version>"

[extension]
id = "<extension ID>"
name = "<extension name>"
version = "<extension version>"
homepage = "<extension homepage>"
description = "<extension description>"
keywords = [ "<string>" ]

[[extension.licenses]]
type = "<string>"
uri = "<uri>"

Where as buildpack has

api = "<buildpack API version>"

[buildpack]
id = "<buildpack ID>"
name = "<buildpack name>"
version = "<buildpack version>"
homepage = "<buildpack homepage>"
clear-env = false
description = "<buildpack description>"
keywords = [ "<string>" ]
sbom-formats = [ "<string>" ]

[[buildpack.licenses]]
type = "<string>"
uri = "<uri>"

[[order]]
[[order.group]]
id = "<buildpack ID>"
version = "<buildpack version>"
optional = false

[[stacks]]
id = "<stack ID>"
mixins = ["<mixin name>"]

[metadata]
# buildpack-specific data

Extensions don't have the concept of meta-extensions that group extensions together, they can only be added directly to a builder image (as they really only make sense within the context of a builder image given they are modifying that image specifically, it's the role of the builder image assembler to understand which extensions are appropriate to package). Without the meta grouping concept, Extension doesn't need the [[order]] related section.

Similarly, Extensions came along after stack removal was considered, so the stacks block is also absent from Extension.toml

Metadata should probably be part of extension.toml (I'm raising a PR to add this, it feels like an oversight)

And the other differences come down to 'clear-env' and 'sbom' not making sense for extensions.

Considering the detect code, much of it would work just fine with an Extension, except for the issue that it expects a Buildpack struct with a nested BuildpackInfo struct.. so ideally it would be nice to restructure those to be less Buildpack centric, still performing the same task, but allowing for the possibility of Extensions being processed. (If it's relevant, both pack, and the lifecycle code refer to the common concept of a BuildPack/Extension as a 'BuildModule' .. it might be beneficial to propagate that terminology and reuse it within libcnb for structs that represent common data)

Generate.go would be the rough equiv of build.go except within the context of https://github.com/buildpacks/spec/blob/main/image_extension.md#generation Note the important differences re which env vars are available though.. this will impact the setup of GenerateContext (to be passed to the GenerateFunc in the same manner as BuildFunc). In general generate.go will be simpler than build though as extensions do not have access to the layers directory, and thus cannot write out env vars, or store persistent metadata, or sboms. A GenerateFunc would write out the build/run Dockerfiles, and/or extend-config.toml file with args for build.Dockerfile

It might be useful to offer some basic templating support via generate.go that would accept a GenerateContext and a template with a map of values to fill in (not required, but is likely a common task for an extension)

dmikusa commented 1 year ago
  1. With #234 we added initial support for extensions. The API may change a little before we cut a 2.0 release, but we think it's mostly all there.
  2. This will not be backported to 1.x.

Closing this issue.