Skip to content

Commit e3678c8

Browse files
committed
Merge remote-tracking branch 'origin/main' into pass-ci-vars-as-build-args
2 parents 9f920bf + 6ecd076 commit e3678c8

File tree

6 files changed

+49
-128
lines changed

6 files changed

+49
-128
lines changed

.github/workflows/build.yml

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -218,66 +218,6 @@ jobs:
218218
cat apppack.toml
219219
test "$(python -c 'import tomllib; print(tomllib.load(open("apppack.toml", "rb"))["services"]["web"]["command"])')" = "bash -c 'gunicorn --access-logfile - --bind 0.0.0.0:\$PORT --forwarded-allow-ips '\"'\"'*'\"'\"' app:app'"
220220
221-
integration-heroku20:
222-
runs-on: ubuntu-latest
223-
needs: [test, build-image]
224-
permissions:
225-
id-token: write
226-
contents: read
227-
packages: read
228-
steps:
229-
- name: Login to GitHub Container Registry
230-
uses: docker/login-action@v2
231-
with:
232-
registry: ghcr.io
233-
username: ${{ github.actor }}
234-
password: ${{ secrets.GITHUB_TOKEN }}
235-
- name: Pull image
236-
run: docker pull ${{ needs.build-image.outputs.image }}
237-
- name: configure aws credentials
238-
uses: aws-actions/configure-aws-credentials@v4
239-
with:
240-
role-to-assume: arn:aws:iam::891426818781:role/github-actions-integration-tests
241-
aws-region: us-east-1
242-
- name: Checkout sample repo
243-
run: git clone --branch buildpacks-20 https://github.com/apppackio/apppack-demo-python.git
244-
- name: Run integration tests
245-
working-directory: ./apppack-demo-python
246-
run: |
247-
cat <<EOF > .envfile
248-
APPNAME=gh-integration
249-
CODEBUILD_BUILD_ID=demo-python:${{ github.run_id }}
250-
CODEBUILD_SOURCE_VERSION=${{ github.sha }}
251-
DOCKERHUB_USERNAME=${{ secrets.DOCKERHUB_USERNAME }}
252-
DOCKERHUB_ACCESS_TOKEN=${{ secrets.DOCKERHUB_ACCESS_TOKEN }}
253-
DOCKER_REPO=891426818781.dkr.ecr.us-east-1.amazonaws.com/github-integration-test
254-
ARTIFACT_BUCKET=integration-test-buildartifacts
255-
ALLOW_EOL_SHIMMED_BUILDER=1
256-
AWS_REGION
257-
AWS_ACCESS_KEY_ID
258-
AWS_SECRET_ACCESS_KEY
259-
AWS_SESSION_TOKEN
260-
EOF
261-
262-
docker run \
263-
--rm \
264-
--privileged \
265-
--env-file .envfile \
266-
--volume /var/run/docker.sock:/var/run/docker.sock \
267-
--volume "$(pwd):/app" \
268-
--workdir /app \
269-
${{ needs.build-image.outputs.image }} \
270-
/bin/sh -c "set -x; git config --global --add safe.directory /app && apppack-builder prebuild; apppack-builder build; apppack-builder postbuild"
271-
- uses: actions/setup-python@v4
272-
with:
273-
python-version: "3.11"
274-
- name: Verify apppack.toml
275-
working-directory: ./apppack-demo-python
276-
run: |
277-
set -ex
278-
cat apppack.toml
279-
test "$(python -c 'import tomllib; print(tomllib.load(open("apppack.toml", "rb"))["services"]["web"]["command"])')" = 'gunicorn --access-logfile - --bind 0.0.0.0:$PORT --forwarded-allow-ips '"'"'*'"' app:app"
280-
281221
integration-docker:
282222
runs-on: ubuntu-latest
283223
needs: [test, build-image]
@@ -346,7 +286,6 @@ jobs:
346286
- integration
347287
- integration-docker
348288
- integration-appjson
349-
- integration-heroku20
350289
- integration-heroku24
351290
permissions:
352291
id-token: write

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
### Changed
11+
12+
* Removed support for EOL `heroku-20` builds
13+
814
## [2.5.0] - 2025-10-21
915

1016
### Added

Dockerfile

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
FROM golang:1.25-alpine AS builder
22
RUN apk add --no-cache curl
3-
# Install current `pack` and v0.31.0, the last pack version that supports heroku/buildpacks:20 builder
43
ENV PACK_VER=0.38.0
54
RUN set -ex && \
6-
mkdir -p /tmp/legacy-pack /tmp/current-pack && \
7-
cd /tmp/legacy-pack && \
8-
curl -sLO "https://github.com/buildpacks/pack/releases/download/v0.31.0/pack-v0.31.0-linux.tgz" && \
9-
tar xvzf "pack-v0.31.0-linux.tgz" && \
10-
cd /tmp/current-pack && \
5+
mkdir -p /tmp/pack && \
6+
cd /tmp/pack && \
117
curl -sLO "https://github.com/buildpacks/pack/releases/download/v$PACK_VER/pack-v$PACK_VER-linux.tgz" && \
128
tar xvzf "pack-v$PACK_VER-linux.tgz"
139

@@ -16,7 +12,6 @@ COPY ./builder .
1612
RUN go build -o /go/bin/apppack-builder main.go
1713

1814
FROM docker:27-dind
19-
COPY --from=builder /tmp/legacy-pack/pack /usr/local/bin/pack-legacy
20-
COPY --from=builder /tmp/current-pack/pack /usr/local/bin/pack
15+
COPY --from=builder /tmp/pack/pack /usr/local/bin/pack
2116
RUN apk add --no-cache git
2217
COPY --from=builder /go/bin/apppack-builder /usr/local/bin/apppack-builder

builder/build/appjson.go

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package build
33
import (
44
"context"
55
"encoding/json"
6+
"fmt"
67
"os"
78

89
"github.com/rs/zerolog/log"
@@ -31,27 +32,6 @@ const DefaultStack = "heroku-22"
3132

3233
// buildpacks included in builder
3334
var IncludedBuildpacks = map[string][]string{
34-
"heroku-20": {
35-
// $ pack builder inspect heroku/buildpacks:20 -o json | jq '.remote_info.buildpacks[].id'
36-
"heroku/builder-eol-warning",
37-
"heroku/go",
38-
"heroku/gradle",
39-
"heroku/java",
40-
"heroku/jvm",
41-
"heroku/maven",
42-
"heroku/nodejs",
43-
"heroku/nodejs-corepack",
44-
"heroku/nodejs-engine",
45-
"heroku/nodejs-npm-engine",
46-
"heroku/nodejs-npm-install",
47-
"heroku/nodejs-pnpm-install",
48-
"heroku/nodejs-yarn",
49-
"heroku/php",
50-
"heroku/procfile",
51-
"heroku/python",
52-
"heroku/ruby",
53-
"heroku/scala",
54-
},
5535
"heroku-22": {
5636
// $ pack builder inspect heroku/builder:22 -o json | jq '.remote_info.buildpacks[].id'
5737
"heroku/deb-packages",
@@ -101,6 +81,9 @@ func patchBuildpack(buildpack string, stack string) string {
10181
return buildpack
10282
}
10383

84+
// EOLStacks contains stacks that have reached end-of-life
85+
var EOLStacks = []string{"heroku-18", "heroku-20"}
86+
10487
func (a *AppJSON) Unmarshal() error {
10588
content, err := a.reader()
10689
if err != nil {
@@ -115,6 +98,9 @@ func (a *AppJSON) Unmarshal() error {
11598
log.Ctx(a.ctx).Error().Err(err).Msg("failed to parse app.json")
11699
return err
117100
}
101+
if contains(EOLStacks, a.Stack) {
102+
return fmt.Errorf("stack %q is end-of-life and no longer supported; upgrade to heroku-24", a.Stack)
103+
}
118104
return nil
119105
}
120106

@@ -136,12 +122,6 @@ func ParseAppJson(ctx context.Context) (*AppJSON, error) {
136122
// the first item in the list is the builder, followed by the stack image
137123
// the stack image is only used for prefetching, so non-heroku stacks should still work
138124
func (a *AppJSON) GetBuilders() []string {
139-
if a.Stack == "heroku-18" {
140-
return []string{"heroku/buildpacks:18", "heroku/heroku:18-cnb"}
141-
}
142-
if a.Stack == "heroku-20" {
143-
return []string{"heroku/buildpacks:20", "heroku/heroku:20-cnb"}
144-
}
145125
if a.Stack == "heroku-22" {
146126
return []string{"heroku/builder:22", "heroku/heroku:22-cnb"}
147127
}

builder/build/appjson_test.go

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import (
44
"context"
55
"os"
66
"reflect"
7+
"strings"
78
"testing"
89

910
"github.com/rs/zerolog"
10-
"github.com/rs/zerolog/log"
1111
)
1212

1313
func stringSliceEqual(a, b []string) bool {
@@ -24,21 +24,6 @@ func stringSliceEqual(a, b []string) bool {
2424

2525
var testContext = zerolog.New(os.Stdout).With().Timestamp().Logger().WithContext(context.Background())
2626

27-
func TestAppJsonBuildpackPatch(t *testing.T) {
28-
a := AppJSON{
29-
Buildpacks: []Buildpack{
30-
{URL: "heroku/nodejs"},
31-
{URL: "heroku/python"},
32-
},
33-
Stack: "heroku-20",
34-
ctx: log.With().Logger().WithContext(context.Background()),
35-
}
36-
expected := []string{"urn:cnb:builder:heroku/nodejs", "urn:cnb:builder:heroku/python"}
37-
if !stringSliceEqual(a.GetBuildpacks(), expected) {
38-
t.Errorf("expected %s, got %s", expected, a.GetBuildpacks())
39-
}
40-
}
41-
4227
func TestAppJsonMissing(t *testing.T) {
4328
a := AppJSON{
4429
reader: func() ([]byte, error) {
@@ -58,27 +43,49 @@ func TestAppJsonMissing(t *testing.T) {
5843
func TestAppJsonStack(t *testing.T) {
5944
a := AppJSON{
6045
reader: func() ([]byte, error) {
61-
return []byte(`{"stack": "heroku-18"}`), nil
46+
return []byte(`{"stack": "heroku-22"}`), nil
6247
},
6348
ctx: testContext,
6449
}
6550
err := a.Unmarshal()
6651
if err != nil {
6752
t.Errorf("expected no error, got %s", err)
6853
}
69-
if a.Stack != "heroku-18" {
54+
if a.Stack != "heroku-22" {
7055
t.Errorf("expected heroku-22, got %s", a.Stack)
7156
}
7257
}
7358

7459
func TestAppJsonBuilders(t *testing.T) {
75-
a := AppJSON{
76-
Stack: "heroku-22",
77-
ctx: testContext,
60+
tests := []struct {
61+
stack string
62+
expected []string
63+
}{
64+
{"heroku-22", []string{"heroku/builder:22", "heroku/heroku:22-cnb"}},
65+
{"custom/builder:latest", []string{"custom/builder:latest"}},
66+
}
67+
for _, tt := range tests {
68+
a := AppJSON{Stack: tt.stack, ctx: testContext}
69+
if !stringSliceEqual(a.GetBuilders(), tt.expected) {
70+
t.Errorf("stack %s: expected %s, got %s", tt.stack, tt.expected, a.GetBuilders())
71+
}
7872
}
79-
expected := []string{"heroku/builder:22", "heroku/heroku:22-cnb"}
80-
if !stringSliceEqual(a.GetBuilders(), expected) {
81-
t.Errorf("expected %s, got %s", expected, a.GetBuilders())
73+
}
74+
75+
func TestAppJsonEOLStackError(t *testing.T) {
76+
for _, stack := range EOLStacks {
77+
a := AppJSON{
78+
reader: func() ([]byte, error) {
79+
return []byte(`{"stack": "` + stack + `"}`), nil
80+
},
81+
ctx: testContext,
82+
}
83+
err := a.Unmarshal()
84+
if err == nil {
85+
t.Errorf("stack %s: expected error for EOL stack, got nil", stack)
86+
} else if !strings.Contains(err.Error(), "end-of-life") {
87+
t.Errorf("stack %s: expected end-of-life error, got: %s", stack, err)
88+
}
8289
}
8390
}
8491

builder/build/build.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,7 @@ func (b *Build) buildWithDocker(config *containers.BuildConfig) error {
149149
func (b *Build) buildWithPack(config *containers.BuildConfig) error {
150150
b.Log().Debug().Msg("pack config registry-mirrors")
151151
builder := b.BuildpackBuilders()[0]
152-
packBinary := "pack"
153-
if builder == "heroku/buildpacks:20" {
154-
// use legacy pack for heroku/buildpacks:20
155-
packBinary = "pack-legacy"
156-
b.Log().Debug().Msg(fmt.Sprintf("using legacy pack version for %s", builder))
157-
}
158-
cmd := exec.Command(packBinary, "config", "registry-mirrors", "add", "index.docker.io", "--mirror", DockerHubMirror)
152+
cmd := exec.Command("pack", "config", "registry-mirrors", "add", "index.docker.io", "--mirror", DockerHubMirror)
159153
if err := cmd.Run(); err != nil {
160154
return err
161155
}
@@ -175,7 +169,7 @@ func (b *Build) buildWithPack(config *containers.BuildConfig) error {
175169
}
176170
packArgs = append(packArgs, config.Image)
177171
b.Log().Debug().Str("builder", builder).Str("buildpacks", buildpacks).Msg("building image")
178-
cmd = exec.Command(packBinary, packArgs...)
172+
cmd = exec.Command("pack", packArgs...)
179173
out := io.MultiWriter(os.Stdout, config.LogFile)
180174
cmd.Stdout = out
181175
cmd.Stderr = out

0 commit comments

Comments
 (0)