Skip to content

Commit

Permalink
Merge branch 'buildpacks:main' into manifest-list
Browse files Browse the repository at this point in the history
  • Loading branch information
WYGIN authored Nov 2, 2023
2 parents 1a750a3 + cf17f4c commit 87f67fd
Show file tree
Hide file tree
Showing 25 changed files with 769 additions and 97 deletions.
12 changes: 8 additions & 4 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@ updates:
- package-ecosystem: "gomod"
directory: "/"
schedule:
# Check for updates to GitHub Actions every weekday
interval: "daily"
interval: "weekly"
groups:
# Group all minor/patch go dependencies into a single PR.
go-dependencies:
update-types:
- "minor"
- "patch"
labels:
- "dependencies"
- "go"
Expand All @@ -15,8 +20,7 @@ updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
# Check for updates to GitHub Actions every weekday
interval: "daily"
interval: "weekly"
labels:
- "dependencies"
- "github_actions"
Expand Down
32 changes: 18 additions & 14 deletions .github/workflows/delivery-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,21 @@ on:
default: false

env:
BUILDER: "paketobuildpacks/builder-jammy-tiny"
IMG_NAME: 'pack'
USERNAME: 'buildpacksio'

jobs:
deliver-docker:
strategy:
matrix:
config: [tiny, base]
include:
- config: tiny
base_image: gcr.io/distroless/static
suffix:
- config: base
base_image: ubuntu:jammy
suffix: -base
runs-on: ubuntu-latest
steps:
- name: Determine version
Expand All @@ -42,16 +51,6 @@ jobs:
uses: actions/checkout@v4
with:
ref: v${{ steps.version.outputs.result }}
# This has to come after the first checkout, so it isn't clobbered
- name: Checkout delivery configuration
uses: actions/checkout@v4
with:
path: ./head
- name: Setup Working Dir
shell: bash
run: |
rm project.toml || true
cp head/.github/workflows/delivery/docker/project.toml project.toml
- name: Determine App Name
run: 'echo "IMG_NAME=${{ env.USERNAME }}/${{ env.IMG_NAME }}" >> $GITHUB_ENV'
- name: Login to Dockerhub
Expand All @@ -61,16 +60,21 @@ jobs:
password: ${{ secrets.DOCKER_PASSWORD }}
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
- uses: buildpacks/github-actions/setup-tools@v5.4.0
- uses: buildpacks/github-actions/setup-tools@v5.5.0
- name: Buildx Build/Publish
run: |
docker buildx build . \
--tag ${{ env.IMG_NAME }}:${{ steps.version.outputs.result }} \
--tag ${{ env.IMG_NAME }}:${{ steps.version.outputs.result }}${{ matrix.suffix }} \
--platform linux/amd64,linux/arm64 \
--build-arg pack_version=${{ steps.version.outputs.result }} \
--build-arg base_image=${{ matrix.base_image }} \
--provenance=false \
--push
- name: Tag Image as Base
if: ${{ (github.event.release != '' || github.event.inputs.tag_latest) && matrix.config == 'base' }}
run: |
crane copy ${{ env.IMG_NAME }}:${{ steps.version.outputs.result }} ${{ env.IMG_NAME }}:base
- name: Tag Image as Latest
if: ${{ github.event.release != '' || github.event.inputs.tag_latest }}
if: ${{ (github.event.release != '' || github.event.inputs.tag_latest) && matrix.config != 'base' }}
run: |
crane copy ${{ env.IMG_NAME }}:${{ steps.version.outputs.result }} ${{ env.IMG_NAME }}:latest
7 changes: 0 additions & 7 deletions .github/workflows/delivery/docker/project.toml

This file was deleted.

6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
ARG base_image=gcr.io/distroless/static

FROM golang:1.20 as builder
ARG pack_version
ENV PACK_VERSION=$pack_version
WORKDIR /app
COPY . .
RUN make build

FROM scratch
FROM ${base_image}
COPY --from=builder /app/out/pack /usr/local/bin/pack
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /tmp /tmp
ENTRYPOINT [ "/usr/local/bin/pack" ]
2 changes: 1 addition & 1 deletion acceptance/testdata/pack_fixtures/report_output.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Pack:
Version: {{ .Version }}
OS/Arch: {{ .OS }}/{{ .Arch }}

Default Lifecycle Version: 0.17.1
Default Lifecycle Version: 0.17.2

Supported Platform APIs: 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.10, 0.11, 0.12

Expand Down
110 changes: 109 additions & 1 deletion builder/config_reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"
"path/filepath"
"strings"

"github.com/BurntSushi/toml"
"github.com/pkg/errors"
Expand Down Expand Up @@ -70,7 +71,25 @@ type RunImageConfig struct {

// BuildConfig build image configuration
type BuildConfig struct {
Image string `toml:"image"`
Image string `toml:"image"`
Env []BuildConfigEnv `toml:"env"`
}

type Suffix string

const (
NONE Suffix = ""
DEFAULT Suffix = "default"
OVERRIDE Suffix = "override"
APPEND Suffix = "append"
PREPEND Suffix = "prepend"
)

type BuildConfigEnv struct {
Name string `toml:"name"`
Value string `toml:"value"`
Suffix Suffix `toml:"suffix,omitempty"`
Delim string `toml:"delim,omitempty"`
}

// ReadConfig reads a builder configuration from the file path provided and returns the
Expand Down Expand Up @@ -162,3 +181,92 @@ func parseConfig(file *os.File) (Config, error) {

return builderConfig, nil
}

func ParseBuildConfigEnv(env []BuildConfigEnv, path string) (envMap map[string]string, warnings []string, err error) {
envMap = map[string]string{}
var appendOrPrependWithoutDelim = 0
for _, v := range env {
if name := v.Name; name == "" || len(name) == 0 {
return nil, nil, errors.Wrapf(errors.Errorf("env name should not be empty"), "parse contents of '%s'", path)
}
if val := v.Value; val == "" || len(val) == 0 {
warnings = append(warnings, fmt.Sprintf("empty value for key/name %s", style.Symbol(v.Name)))
}
suffixName, delimName, err := getBuildConfigEnvFileName(v)
if err != nil {
return envMap, warnings, err
}
if val, e := envMap[suffixName]; e {
warnings = append(warnings, fmt.Sprintf(errors.Errorf("overriding env with name: %s and suffix: %s from %s to %s", style.Symbol(v.Name), style.Symbol(string(v.Suffix)), style.Symbol(val), style.Symbol(v.Value)).Error(), "parse contents of '%s'", path))
}
if val, e := envMap[delimName]; e {
warnings = append(warnings, fmt.Sprintf(errors.Errorf("overriding env with name: %s and delim: %s from %s to %s", style.Symbol(v.Name), style.Symbol(v.Delim), style.Symbol(val), style.Symbol(v.Value)).Error(), "parse contents of '%s'", path))
}
if delim := v.Delim; (delim != "" || len(delim) != 0) && (delimName != "" || len(delimName) != 0) {
envMap[delimName] = delim
}
envMap[suffixName] = v.Value
}

for k := range envMap {
name, suffix, err := getFilePrefixSuffix(k)
if err != nil {
continue
}
if _, ok := envMap[name+".delim"]; (suffix == "append" || suffix == "prepend") && !ok {
warnings = append(warnings, fmt.Sprintf(errors.Errorf("env with name/key %s with suffix %s must to have a %s value", style.Symbol(name), style.Symbol(suffix), style.Symbol("delim")).Error(), "parse contents of '%s'", path))
appendOrPrependWithoutDelim++
}
}
if appendOrPrependWithoutDelim > 0 {
return envMap, warnings, errors.Errorf("error parsing [[build.env]] in file '%s'", path)
}
return envMap, warnings, err
}

func getBuildConfigEnvFileName(env BuildConfigEnv) (suffixName, delimName string, err error) {
suffix, err := getActionType(env.Suffix)
if err != nil {
return suffixName, delimName, err
}
if suffix == "" {
suffixName = env.Name
} else {
suffixName = env.Name + suffix
}
if delim := env.Delim; delim != "" || len(delim) != 0 {
delimName = env.Name + ".delim"
}
return suffixName, delimName, err
}

func getActionType(suffix Suffix) (suffixString string, err error) {
const delim = "."
switch suffix {
case NONE:
return "", nil
case DEFAULT:
return delim + string(DEFAULT), nil
case OVERRIDE:
return delim + string(OVERRIDE), nil
case APPEND:
return delim + string(APPEND), nil
case PREPEND:
return delim + string(PREPEND), nil
default:
return suffixString, errors.Errorf("unknown action type %s", style.Symbol(string(suffix)))
}
}

func getFilePrefixSuffix(filename string) (prefix, suffix string, err error) {
val := strings.Split(filename, ".")
if len(val) <= 1 {
return val[0], suffix, errors.Errorf("Suffix might be null")
}
if len(val) == 2 {
suffix = val[1]
} else {
suffix = strings.Join(val[1:], ".")
}
return val[0], suffix, err
}
107 changes: 107 additions & 0 deletions builder/config_reader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,4 +229,111 @@ uri = "noop-buildpack.tgz"
h.AssertError(t, builder.ValidateConfig(config), "build.image is required")
})
})
when("#ParseBuildConfigEnv()", func() {
it("should return an error when name is not defined", func() {
_, _, err := builder.ParseBuildConfigEnv([]builder.BuildConfigEnv{
{
Name: "",
Value: "vaiue",
},
}, "")
h.AssertNotNil(t, err)
})
it("should warn when the value is nil or empty string", func() {
env, warn, err := builder.ParseBuildConfigEnv([]builder.BuildConfigEnv{
{
Name: "key",
Value: "",
Suffix: "override",
},
}, "")

h.AssertNotNil(t, warn)
h.AssertNil(t, err)
h.AssertMapContains[string, string](t, env, h.NewKeyValue[string, string]("key.override", ""))
})
it("should return an error when unknown suffix is specified", func() {
_, _, err := builder.ParseBuildConfigEnv([]builder.BuildConfigEnv{
{
Name: "key",
Value: "",
Suffix: "invalid",
},
}, "")

h.AssertNotNil(t, err)
})
it("should override and show a warning when suffix or delim is defined multiple times", func() {
env, warn, err := builder.ParseBuildConfigEnv([]builder.BuildConfigEnv{
{
Name: "key1",
Value: "value1",
Suffix: "append",
Delim: "%",
},
{
Name: "key1",
Value: "value2",
Suffix: "append",
Delim: ",",
},
{
Name: "key1",
Value: "value3",
Suffix: "default",
Delim: ";",
},
{
Name: "key1",
Value: "value4",
Suffix: "prepend",
Delim: ":",
},
}, "")

h.AssertNotNil(t, warn)
h.AssertNil(t, err)
h.AssertMapContains[string, string](
t,
env,
h.NewKeyValue[string, string]("key1.append", "value2"),
h.NewKeyValue[string, string]("key1.default", "value3"),
h.NewKeyValue[string, string]("key1.prepend", "value4"),
h.NewKeyValue[string, string]("key1.delim", ":"),
)
h.AssertMapNotContains[string, string](
t,
env,
h.NewKeyValue[string, string]("key1.append", "value1"),
h.NewKeyValue[string, string]("key1.delim", "%"),
h.NewKeyValue[string, string]("key1.delim", ","),
h.NewKeyValue[string, string]("key1.delim", ";"),
)
})
it("should return an error when `suffix` is defined as `append` or `prepend` without a `delim`", func() {
_, warn, err := builder.ParseBuildConfigEnv([]builder.BuildConfigEnv{
{
Name: "key",
Value: "value",
Suffix: "append",
},
}, "")

h.AssertNotNil(t, warn)
h.AssertNotNil(t, err)
})
it("when suffix is NONE or omitted should default to `override`", func() {
env, warn, err := builder.ParseBuildConfigEnv([]builder.BuildConfigEnv{
{
Name: "key",
Value: "value",
Suffix: "",
},
}, "")

h.AssertNotNil(t, warn)
h.AssertNil(t, err)
h.AssertMapContains[string, string](t, env, h.NewKeyValue[string, string]("key", "value"))
})
})
}
Loading

0 comments on commit 87f67fd

Please sign in to comment.