Skip to content

Commit

Permalink
Merge pull request #1 from paketo-buildpacks/main
Browse files Browse the repository at this point in the history
  • Loading branch information
emmjohnson authored Mar 23, 2021
2 parents 306ef03 + 9b65445 commit 91d7876
Show file tree
Hide file tree
Showing 90 changed files with 2,054 additions and 1,858 deletions.
35 changes: 35 additions & 0 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: "CodeQL"

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
schedule:
- cron: '0 0 * * *' # Once a day at midnight

jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
language:
- 'go'

steps:
- name: Checkout repository
uses: actions/checkout@v2

- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}

- name: Autobuild
uses: github/codeql-action/autobuild@v1

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1
6 changes: 5 additions & 1 deletion .github/workflows/create-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v1
with:
go-version: 1.14
go-version: 1.16
- name: Checkout
uses: actions/checkout@v2
- name: Run Unit Tests
Expand All @@ -24,6 +24,10 @@ jobs:
runs-on: ubuntu-latest
needs: unit
steps:
- name: Setup Go
uses: actions/setup-go@v1
with:
go-version: 1.16
- name: Reset Draft Release
uses: paketo-buildpacks/github-config/actions/release/reset-draft@main
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v1
with:
go-version: 1.14
go-version: 1.16
- name: Checkout
uses: actions/checkout@v2
- name: Run Unit Tests
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ according to the specification:

## Buildpack Interface

According to the specification, the buildpack interface is composed of both
According to the CNB specification, the buildpack interface is composed of both
a detect and build phase. Each of these phases has a corresponding set of
packit primitives enable developers to easily implement a buildpack.

Expand Down Expand Up @@ -206,6 +206,8 @@ the types and functions declared herein.

* [chronos](./chronos): Package chronos provides clock functionality that can be useful when developing and testing Cloud Native Buildpacks.

* [draft](./draft): Package draft provides a mechanism for combining Buildpack Plan entries for a dependency into an single entry. The entry has layer metadata that meets all of the entries' specifications. Its version constraint is based on a user-provided prioritized list of version sources. Useful during the build phase. See [the CNB Buildpacks specification](https://github.com/buildpacks/spec/blob/main/buildpack.md#purpose-2) for context.

* [fakes](./fakes)

* [fs](./fs): Package fs provides a set of filesystem helpers that can be useful when developing Cloud Native Buildpacks.
Expand Down
16 changes: 16 additions & 0 deletions bom.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package packit

// BOMEntry contains a bill of materials entry.
type BOMEntry struct {
// Name represents the name of the entry.
Name string `toml:"name"`

// Metadata is the metadata of the entry. Optional.
Metadata map[string]interface{} `toml:"metadata,omitempty"`
}

// UnmetEntry contains the name of an unmet dependency from the build process
type UnmetEntry struct {
// Name represents the name of the entry.
Name string `toml:"name"`
}
184 changes: 77 additions & 107 deletions build.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ import (
"strings"

"github.com/BurntSushi/toml"
"github.com/Masterminds/semver/v3"
"github.com/paketo-buildpacks/packit/internal"
)

// BuildFunc is the definition of a callback that can be invoked when the Build
// function is executed. Buildpack authors should implement a BuildFunc that
// performs the specific build phase operations for a buildpack.
type BuildFunc func(BuildContext) (BuildResult, error)

// BuildContext provides the contextual details that are made available by the
// buildpack lifecycle during the build phase. This context is populated by the
// Build function and passed to BuildFunc during execution.
Expand All @@ -24,6 +30,10 @@ type BuildContext struct {
// files included in the buildpack.
CNBPath string

// Platform includes the platform context according to the specification:
// https://github.com/buildpacks/spec/blob/main/buildpack.md#build
Platform Platform

// Layers provides access to layers managed by the buildpack. It can be used
// to create new layers or retrieve cached layers from previous builds.
Layers Layers
Expand All @@ -42,18 +52,16 @@ type BuildContext struct {
WorkingDir string
}

// BuildFunc is the definition of a callback that can be invoked when the Build
// function is executed. Buildpack authors should implement a BuildFunc that
// performs the specific build phase operations for a buildpack.
type BuildFunc func(BuildContext) (BuildResult, error)

// BuildResult allows buildpack authors to indicate the result of the build
// phase for a given buildpack. This result, returned in a BuildFunc callback,
// will be parsed and persisted by the Build function and returned to the
// lifecycle at the end of the build phase execution.
type BuildResult struct {
// Plan is the set of refinements to the Buildpack Plan that were performed
// during the build phase.
//
// Deprecated: Use LaunchMetadata or BuildMetadata instead. For more information
// see https://buildpacks.io/docs/reference/spec/migration/buildpack-api-0.4-0.5/
Plan BuildpackPlan

// Layers is a list of layers that will be persisted by the lifecycle at the
Expand All @@ -65,93 +73,11 @@ type BuildResult struct {
// the buildpack lifecycle specification:
// https://github.com/buildpacks/spec/blob/main/buildpack.md#launchtoml-toml
Launch LaunchMetadata
}

// LaunchMetadata represents the launch metadata details persisted in the
// launch.toml file according to the buildpack lifecycle specification:
// https://github.com/buildpacks/spec/blob/main/buildpack.md#launchtoml-toml.
type LaunchMetadata struct {
// Processes is a list of processes that will be returned to the lifecycle to
// be executed during the launch phase.
Processes []Process

// Slices is a list of slices that will be returned to the lifecycle to be
// exported as separate layers during the export phase.
Slices []Slice

// Labels is a map of key-value pairs that will be returned to the lifecycle to be
// added as config label on the image metadata. Keys must be unique.
Labels map[string]string
}

// Process represents a process to be run during the launch phase as described
// in the specification:
// https://github.com/buildpacks/spec/blob/main/buildpack.md#launch. The
// fields of the process are describe in the specification of the launch.toml
// file:
// https://github.com/buildpacks/spec/blob/main/buildpack.md#launchtoml-toml.
type Process struct {
// Type is an identifier to describe the type of process to be executed, eg.
// "web".
Type string `toml:"type"`

// Command is the start command to be executed at launch.
Command string `toml:"command"`

// Args is a list of arguments to be passed to the command at launch.
Args []string `toml:"args"`

// Direct indicates whether the process should bypass the shell when invoked.
Direct bool `toml:"direct"`
}

// Slice represents a layer of the working directory to be exported during the
// export phase. These slices help to optimize data transfer for files that are
// commonly shared across applications. Slices are described in the layers
// section of the buildpack spec:
// https://github.com/buildpacks/spec/blob/main/buildpack.md#layers. The slice
// fields are described in the specification of the launch.toml file:
// https://github.com/buildpacks/spec/blob/main/buildpack.md#launchtoml-toml.
type Slice struct {
Paths []string `toml:"paths"`
}

// BuildpackInfo is a representation of the basic information for a buildpack
// provided in its buildpack.toml file as described in the specification:
// https://github.com/buildpacks/spec/blob/main/buildpack.md#buildpacktoml-toml.
type BuildpackInfo struct {
// ID is the identifier specified in the `buildpack.id` field of the buildpack.toml.
ID string `toml:"id"`

// Name is the identifier specified in the `buildpack.name` field of the buildpack.toml.
Name string `toml:"name"`

// Version is the identifier specified in the `buildpack.version` field of the buildpack.toml.
Version string `toml:"version"`
}

// BuildpackPlan is a representation of the buildpack plan provided by the
// lifecycle and defined in the specification:
// https://github.com/buildpacks/spec/blob/main/buildpack.md#buildpack-plan-toml.
// It is also used to return a set of refinements to the plan at the end of the
// build phase.
type BuildpackPlan struct {
// Entries is a list of BuildpackPlanEntry fields that are declared in the
// buildpack plan TOML file.
Entries []BuildpackPlanEntry `toml:"entries"`
}

// BuildpackPlanEntry is a representation of a single buildpack plan entry
// specified by the lifecycle.
type BuildpackPlanEntry struct {
// Name is the name of the dependency the the buildpack should provide.
Name string `toml:"name"`

// Metadata is an unspecified field allowing buildpacks to communicate extra
// details about their requirement. Examples of this type of metadata might
// include details about what source was used to decide the version
// constraint for a requirement.
Metadata map[string]interface{} `toml:"metadata"`
// Build is the metadata that will be persisted as build.toml according to
// the buildpack lifecycle specification:
// https://github.com/buildpacks/spec/blob/main/buildpack.md#buildtoml-toml
Build BuildMetadata
}

// Build is an implementation of the build phase according to the Cloud Native
Expand All @@ -170,8 +96,9 @@ func Build(f BuildFunc, options ...Option) {
}

var (
layersPath = config.args[1]
planPath = config.args[3]
layersPath = config.args[1]
platformPath = config.args[2]
planPath = config.args[3]
)

pwd, err := os.Getwd()
Expand All @@ -193,16 +120,28 @@ func Build(f BuildFunc, options ...Option) {
}

var buildpackInfo struct {
Buildpack BuildpackInfo `toml:"buildpack"`
APIVersion string `toml:"api"`
Buildpack BuildpackInfo `toml:"buildpack"`
}

_, err = toml.DecodeFile(filepath.Join(cnbPath, "buildpack.toml"), &buildpackInfo)
if err != nil {
config.exitHandler.Error(err)
return
}

apiV05, _ := semver.NewVersion("0.5")
apiVersion, err := semver.NewVersion(buildpackInfo.APIVersion)
if err != nil {
config.exitHandler.Error(err)
return
}

result, err := f(BuildContext{
CNBPath: cnbPath,
CNBPath: cnbPath,
Platform: Platform{
Path: platformPath,
},
Stack: os.Getenv("CNB_STACK_ID"),
WorkingDir: pwd,
Plan: plan,
Expand All @@ -216,10 +155,17 @@ func Build(f BuildFunc, options ...Option) {
return
}

err = config.tomlWriter.Write(planPath, result.Plan)
if err != nil {
config.exitHandler.Error(err)
return
if len(result.Plan.Entries) > 0 {
if apiVersion.GreaterThan(apiV05) || apiVersion.Equal(apiV05) {
config.exitHandler.Error(fmt.Errorf(`buildpack plan is read only since BuildPack API v0.5`))
return
}

err = config.tomlWriter.Write(planPath, result.Plan)
if err != nil {
config.exitHandler.Error(err)
return
}
}

layerTomls, err := filepath.Glob(filepath.Join(layersPath, "*.toml"))
Expand All @@ -229,7 +175,7 @@ func Build(f BuildFunc, options ...Option) {
}

for _, file := range layerTomls {
if filepath.Base(file) != "launch.toml" && filepath.Base(file) != "store.toml" {
if filepath.Base(file) != "launch.toml" && filepath.Base(file) != "store.toml" && filepath.Base(file) != "build.toml" {
err = os.Remove(file)
if err != nil {
config.exitHandler.Error(fmt.Errorf("failed to remove layer toml: %w", err))
Expand Down Expand Up @@ -262,26 +208,37 @@ func Build(f BuildFunc, options ...Option) {
config.exitHandler.Error(err)
return
}

for process, processEnv := range layer.ProcessLaunchEnv {
err = config.envWriter.Write(filepath.Join(layer.Path, "env.launch", process), processEnv)
if err != nil {
config.exitHandler.Error(err)
return
}
}
}

if len(result.Launch.Processes) > 0 ||
len(result.Launch.Slices) > 0 ||
len(result.Launch.Labels) > 0 {
if !result.Launch.isEmpty() {
if apiVersion.LessThan(apiV05) && len(result.Launch.BOM) > 0 {
config.exitHandler.Error(fmt.Errorf("BOM entries in launch.toml is only supported with Buildpack API v0.5 or higher"))
return
}

type label struct {
Key string `toml:"key"`
Value string `toml:"value"`
}

var launch struct {
Processes []Process `toml:"processes"`
Slices []Slice `toml:"slices"`
Labels []label `toml:"labels"`
Processes []Process `toml:"processes"`
Slices []Slice `toml:"slices"`
Labels []label `toml:"labels"`
BOM []BOMEntry `toml:"bom"`
}

launch.Processes = result.Launch.Processes
launch.Slices = result.Launch.Slices

launch.BOM = result.Launch.BOM
if len(result.Launch.Labels) > 0 {
launch.Labels = []label{}
for k, v := range result.Launch.Labels {
Expand All @@ -299,4 +256,17 @@ func Build(f BuildFunc, options ...Option) {
return
}
}

if !result.Build.isEmpty() {
if apiVersion.LessThan(apiV05) {
config.exitHandler.Error(fmt.Errorf("build.toml is only supported with Buildpack API v0.5 or higher"))
return

}
err = config.tomlWriter.Write(filepath.Join(layersPath, "build.toml"), result.Build)
if err != nil {
config.exitHandler.Error(err)
return
}
}
}
14 changes: 14 additions & 0 deletions build_metadata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package packit

// BuildMetadata represents the build metadata details persisted in the
// build.toml file according to the buildpack lifecycle specification:
// https://github.com/buildpacks/spec/blob/main/buildpack.md#buildtoml-toml.
type BuildMetadata struct {
// BOM is the Bill-of-Material entries containing information about the
// dependencies provided to the build environment.
BOM []BOMEntry `toml:"bom"`

// Unmet is a list of unmet entries from the build process that it was unable
// to provide.
Unmet []UnmetEntry `toml:"unmet"`
}
Loading

0 comments on commit 91d7876

Please sign in to comment.