Skip to content

Commit

Permalink
Updates from the discussions from the WG meeting
Browse files Browse the repository at this point in the history
* remove dependencies table
* move buildpack entries to the top level: stacks, order, metadata
* add additional build plan groupings using `[[or]]` key

Signed-off-by: Terence Lee <[email protected]>
  • Loading branch information
hone committed Jul 25, 2019
1 parent 6f094b3 commit b1d3ac6
Showing 1 changed file with 27 additions and 107 deletions.
134 changes: 27 additions & 107 deletions text/0000-buildpack-config-for-dist.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,10 @@ We propose the following changes to `buildpack.toml`:

- Add a required top level `[buildpack]` table that describes buildpack configuration.
- Remove the `[[buildpacks]]` array of tables.
- Add support for `[[buildpack.order]]` array, which defines the ordering of buildpack.
- Add support for `[[order]]` array, which defines the ordering of buildpack.
- Add support for `path` to the `order.group = [{}]` table so that `id` and `version` do not have to be repeated and can instead be derived from a nested `buildpack.toml`.
- Add a `[[buildpack.dependencies]]` array that defines a list of buildpacks that must be included in the buildpackage. The schema of the `dependencies` table matches the `[buildpack]` table (minus `dependencies`).
- Add a `[buildpack.metadata]` table that is unstructured.
- Add a `[[buildpack.stacks]]` array of tables that is required for buildpacks that do not define a `[[buildpack.order]]` (i.e. non-metabuildpacks). The `stacks` table contains an `id` with the name of a stack.
- Add a `[metadata]` table that is unstructured.
- Add a `[[stacks]]` array of tables that is required for buildpacks that do not define a `[[order]]` (i.e. non-metabuildpacks). The `stacks` table contains an `id` with the name of a stack.

In order for a repository to be run by a platform, included in a builder, or packaged into a buildpackage; it must contain a `buildpack.toml` with the `buildpack.id` and `buildpack.version` keys. For example:

Expand All @@ -83,7 +82,7 @@ version = "<string>"
The top level `[buildpack]` table may contain an `order` key. This key has a schema similar to the `[[buildpack.order]]` described in the Distribution Spec, but now with support for a `path` key in a group. The `path` key can be used to reduce redundancy in the `buildpack.toml` by pointing to a nested `buildpack.toml` files that contain buildpack metadata. For example:

```toml
[[buildpack.order]]
[[order]]
group = [
{ path = "node-cnb" },
{ path = "buildpack.npm.toml" },
Expand All @@ -95,23 +94,31 @@ In this case, the `node-cnb/` directory contains a `buildpack.toml`. In this way
Alternatively, the `group` may contain a `id` and `version` like this:

```toml
[[buildpack.order]]
[[order]]
group = [
{ id = "io.buildpacks.node", version = "0.0.5" },
{ id = "io.buildpacks.npm", version = "0.0.7" },
]
```

When `id` and `version` are used, a platform will attempt to resolve the group entry to a buildpack in the `[[buildpack.dependencies]]` array. The `[[buildpack.dependencies]]` array is a list of buildpacks that are associated with the main buildpack. For example:
## Optional Build Plan Groups
To simplify `buildpack.toml`, this RFC will also be extending the [Contractual Build Plan RFC](https://github.com/buildpack/rfcs/blob/master/text/0005-contractual-build-plan.md) to include the ability to add additional groupings of `provides` and `requires` inside of a `[[or]]` Array.

```toml
[[buildpack.dependencies]]
id = "<string>"
version = "<string>"
path = "<string>"
[[or]]
[[or.requires]]
name = "nodejs"
[or.requires.metadata]
version = "LTS"
[[or.provides]]
name = "node.js"
```

Any buildpack defined in the `[[buildpack.dependencies]]` array (regardless of whether it is used in a group or not) will be included in the packaging of the buildpack.
The `[[or]]` Array is optional, but the top-level `[[requires]]` and `[[provides]]` must be provided first if the Build Plan is being used.

For a given buildpack group, a sequence of trials is generated by selecting a single potential Build Plan from each buildpack in a left-to-right, depth-first order. The group fails to detect if all trials fail to detect.

This supports the use case described in the discussion of the [Distribution Spec](https://github.com/buildpack/rfcs/pull/12#issuecomment-504781945), by providing a single buildpack that can generate two different build plan groupings.

# How it Works
[how-it-works]: #how-it-works
Expand All @@ -128,73 +135,12 @@ id = "com.example.node"
name = "Node.js Buildpack"
version = "0.0.9"

[[buildpack.stacks]]
[[stacks]]
id = "io.buildpacks.stacks.bionic"
```

As long as this repository also contains a valid `bin/detect` and `bin/build`, it can produce a valid buildpack.

## Example: Same code, different buildpack

These elements described above can be used to define a metabuildpack that includes two buildpacks sharing the same source code, but are published as two distinct buildpacks with different `id` values:

```toml
[buildpack]
id = "com.example.myapm"
name = "APM Buildpack"
version = "0.0.9"
[[buildpack.order]]
group = [
{ id = "com.example.myapm.node", version = "0.0.7" }
]
[[buildpack.order]]
group = [
{ id = "com.example.myapm.java", version = "0.0.5" }
]

[[buildpack.dependencies]]
id = "com.example.myapm.node"
name = "APM Buildpack for Node"
version = "0.0.7"
path = "."

[[buildpack.dependencies]]
id = "com.example.myapm.java"
name = "APM Buildpack for Java"
version = "0.0.5"
path = "."
```

This supports the use case described in the discussion of the [Distribution Spec](https://github.com/buildpack/rfcs/pull/12#issuecomment-504781945).

## Example: Node.js buildpack with composite `buildpack.toml` file

This example is equivalent to the `buildpack.toml` described in the [Distribution Spec](https://github.com/buildpack/rfcs/blob/master/text/0007-spec-distribution.md) and shown earlier in the [Motivation](#motivation) section. However, we now define the `buildpack.toml` with a `[buildpack]` table and `[[buildpack.dependencies]]` array:

```toml
[buildpack]
id = "io.buildpacks.nodejs"
name = "Node.js Buildpack"
version = "0.0.9"
[[buildpack.order]]
group = [
{ id = "io.buildpacks.node", version = "0.0.5" },
{ id = "io.buildpacks.npm", version = "0.0.7" },
]

[[buildpack.dependencies]]
id = "io.buildpacks.npm"
name = "NPM Buildpack"
version = "0.0.7"
path = "./npm-cnb/"

[[buildpack.dependencies]]
id = "io.buildpacks.node"
name = "Node Engine Buildpack"
version = "0.0.5"
path = "./node-cnb/"
```

## Example: Node.js buildpack with multiple `buildpack.toml` files

This example describes a buildpack defined in the same repository as the buildpacks it's composed from, but with separate `buildpack.toml` files to define the constituents. The directory structure is:
Expand All @@ -215,7 +161,7 @@ The root `buildpack.toml` contains the following:
id = "io.buildpacks.npm-nodejs"
name = "NPM Node.js Buildpack"
version = "0.0.9"
[[buildpack.order]]
[[order]]
group = [
{ path = "node-cnb" },
{ path = "npm-cnb" },
Expand All @@ -230,13 +176,13 @@ id = "io.buildpacks.node"
name = "Node Engine Buildpack"
version = "0.0.5"

[[buildpack.stacks]]
[[stacks]]
id = "io.buildpacks.stacks.bionic"

[[buildpack.stacks]]
[[stacks]]
id = "org.cloudfoundry.stacks.cflinuxfs3"

[buildpack.metadata.dependencies]
[metadata.dependencies]
id = "node"
name = "Node.js runtime"
version = "0.1.1"
Expand All @@ -252,48 +198,22 @@ id = "io.buildpacks.npm"
name = "NPM Buildpack"
version = "0.0.7"

[[buildpack.stacks]]
[[stacks]]
id = "io.buildpacks.stacks.bionic"
```

In this example, the configuration for each buildpack in the metabuildpack is decomposed into separate `buildpack.toml` files such that they can be used or published on their own.

## Example: Ruby buildpack with Node.js

In this example, a self-contained Ruby buildpack can define a composite buildpack that use itself and a Node.js buildpack to form a buildpackage. The `io.buildpacks.ruby-node` buildpack isn't used, but is optionally available for platforms that may wish to consume it.

```toml
[buildpack]
id = "io.buildpacks.ruby"
name = "Ruby Buildpack"
version = "0.0.7"
[[buildpack.stacks]]
id = "io.buildpacks.stacks.bionic"

[[buildpack.dependencies]]
id = "io.buildpacks.ruby-node"
name = "Ruby with Node.js Buildpack"
version = "0.0.9"

[buildpack.dependencies.order]
group = [
{ id = "io.buildpacks.node", version = "0.0.5" },
{ id = "io.buildpacks.ruby", version = "0.0.7" },
]
```

# Drawbacks
[drawbacks]: #drawbacks

- Requires a single buildpack per `buildpack.toml`, which may not be preferable in certain monorepo situations. With hope that the support for separate `buildpack.toml` files referenced with `path` will mitigate this.
- This proposal does not do a good job of supporting the use case where a `buildpack.toml` must define multiple buildpacks that have no connection to each other. We propose two patterns that accomodate this case:
* Pick one lucky buildpack to define in the `[buildpack]` table, and add the others to the `[[buildpack.dependencies]]` array.
* Use the `[[profiles]]` alternative described below.
- This proposal does not do a good job of supporting the use case where a `buildpack.toml` must define multiple buildpacks that have no connection to each other. We propose the `[[profiles]]` pattern alternative described below to accomodate this case.

# Alternatives
[alternatives]: #alternatives

This proposal provides a good balance of concerns. It accommodates the need to define multiple buildpacks in a `buildpack.toml`, while still allowing a 1:1 pattern between `buildpack.toml` and a buildpack. The 1:1 pattern is important to ensure that no odd inferences are defined in the spec (like treating the first buildpack in the `[[buildpacks]]` array as special). This allows a `buildpack.toml` to stand on its own such that it can be used without any outside configuration (like a `package.toml`) if the platform allows it.
The 1:1 pattern is important to ensure that no odd inferences are defined in the spec (like treating the first buildpack in the `[[buildpacks]]` array as special). This allows a `buildpack.toml` to stand on its own such that it can be used without any outside configuration (like a `package.toml`) if the platform allows it.

However, there are alternatives we could implement, but they favor one concern over another.

Expand Down

0 comments on commit b1d3ac6

Please sign in to comment.