5.0 KiB
Meta
- Name: Inline Buildpacks
- Start Date: 2020-06-11
- Author(s): Joe Kutner
- Status: Implemented
- RFC Pull Request: rfcs#86
- CNB Pull Request: (leave blank)
- CNB Issue: (leave blank)
- Supersedes: N/A
Summary
This is a proposal for a type of buildpack that can be defined in the same repo as the app it is used with.
Motivation
One characteristic of Dockerfile that Buildpacks do not replace well is the ability to create a single, one-off file to quickly define a custom build process for an app or project. A Dockerfile may contain just a few lines of code, and a developer can generate a complete image. The only quick way to create a custom build for an app using a buildpack is by creating no fewer than three files: buildpack.toml, bin/build, and bin/detect (and likely storing those in a new repo).
We seek to reduce the barrier to entry for buildpacks when a developer needs to quickly create a custom, one-off build step by introducing a new mechanism that will allow a buildpack to be defined inline with an app (and with fewer files).
What it is
- inline - existing in the same repository
The target personas for this RFC are the buildpack author and buildpack user who need to create a custom, one-off build or are just getting started with buildpacks and do not want the overhead of a new repo.
We propose two new keys in the [[build.buildpacks]] table in project.toml:
api- the API compatibility version of the buildpack. Matches the schema ofbuildpack.tomlinline- the contents of a script that will be run as thebin/buildof the inline buildpackshell- defines the shebang line of the script ininline
When any of these keys are provided the following keys are disallowed: version, uri.
(Note: there is no need to implement bin/detect. The detect phase will always pass because there's no foreseeable reason that a user would create an inline buildpack that they don't want to use)
How it Works
When an entry in the [[build.buildpacks]] table contains an inline value, the following is implied:
- a
bin/detectthat always passes (i.e.exit 0) - a
bin/buildthat contains the value ofinlinescript without any changes (i.e. no magic) - a
buildpack.tomlusing theidandversionfrom the buildpack entry inproject.toml
When the inline buildpack is executed, the working directory will be the app directory (as normal). In this way, an inline script MAY reference other scripts in the repo. For example, a lib/utils.sh may be sourced by an inline Bash script.
Example
The following project.toml creates a buildpack that will run two Rake tasks after running JVM and Ruby buildpacks.
[project]
id = "my-app"
[[build.buildpacks]]
id = "example/jvm"
version = "1.0"
[[build.buildpacks]]
id = "example/ruby"
version = "1.0"
[[build.buildpacks]]
id = "me/rake-tasks"
[build.buildpacks.script]
api = "0.3"
inline = """
rake war
rake db:migrate
"""
Drawbacks
- It discourages buildpack reuse (i.e. if it's really easy to create a one-off buildpack, people are less like to make reuseable buildpacks and share them)
- It encourages the copy-paste problems created by
Dockerfile - There is no built-in mechanism to provide dependencies in the build plan. However, this can be worked-around with a generic build-plan-buildpack that either statically or dynamically creates entries in the build plan.
Alternatives
Prior Art
Dockerfile- Packfile
- HTML
<script>element
Unresolved Questions
- Can an inline buildpack be published to a registry?
- Can inline buildpacks be root buildpacks?
- Can a
project.tomlcontain more than one inline buildpack? - How will platforms implement this behavior?
- A future
/lifecycle/preparecould generate the temporary buildpack from the inline script.
- A future
Spec. Changes (OPTIONAL)
The Project Descriptor extension will be ammended to include:
build.buildpacks
The build table MAY contain an array of buildpacks. The schema for this table is:
[[build.buildpacks]]
[build.buildpacks.script]
api = "<buildpack api>"
shell = "<string (optional default=/bin/sh)>"
inline = "<script contents (optional)>"
This defines the buildpacks that a platform should use on the repo.
Either an version, uri, or script table MUST be included, but MUST NOT include any combination of these elements.
The api and inline key MUST be defined in the script table.