Skip to content

Build and Push

Build and Push #312

name: Build and Push
on:
push:
branches:
- main
tags:
- "v*"
pull_request:
branches:
- main
schedule:
- cron: "0 3 * * *"
permissions:
contents: read
env:
REGISTRY: ghcr.io
IMAGE_BASE: ghcr.io/patbaumgartner/distroless-buildpack-builder-java-tiny
jobs:
build-stack-build:
name: Build stack – build image
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
attestations: write
id-token: write
outputs:
image: ${{ steps.meta.outputs.tags }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Log in to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
with:
images: |
${{ env.IMAGE_BASE }}/build
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push build stack image
id: build
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: ./stack/build
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# sbom and provenance add extra OCI manifests to the image index;
# the pack CLI misidentifies these as platform manifests and fails
# with "missing required env var 'CNB_USER_ID'".
sbom: false
provenance: false
- name: Generate SBOM with Syft (build stack)
if: github.event_name != 'pull_request'
uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
with:
image: ${{ env.IMAGE_BASE }}/build:latest
artifact-name: sbom-build-stack.spdx.json
output-file: sbom-build-stack.spdx.json
- name: Attest build stack image (GHCR)
if: github.event_name != 'pull_request'
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
with:
subject-name: ${{ env.IMAGE_BASE }}/build
subject-digest: ${{ steps.build.outputs.digest }}
push-to-registry: true
build-stack-run:
name: Build stack – run image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
attestations: write
id-token: write
outputs:
image: ${{ steps.meta.outputs.tags }}
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Log in to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
with:
images: |
${{ env.IMAGE_BASE }}/run
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest,enable={{is_default_branch}}
- name: Build and push run stack image
id: build
uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0
with:
context: ./stack/run
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# sbom and provenance add extra OCI manifests to the image index;
# the pack CLI misidentifies these as platform manifests and fails
# with "missing required env var 'CNB_USER_ID'".
sbom: false
provenance: false
- name: Generate SBOM with Syft (run stack)
if: github.event_name != 'pull_request'
uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
with:
image: ${{ env.IMAGE_BASE }}/run:latest
artifact-name: sbom-run-stack.spdx.json
output-file: sbom-run-stack.spdx.json
- name: Attest run stack image (GHCR)
if: github.event_name != 'pull_request'
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
with:
subject-name: ${{ env.IMAGE_BASE }}/run
subject-digest: ${{ steps.build.outputs.digest }}
push-to-registry: true
validate-builder:
name: Validate builder locally
runs-on: ubuntu-latest
needs:
- build-stack-build
- build-stack-run
if: |
always() &&
github.event_name != 'pull_request' &&
(needs.build-stack-run.result == 'success') &&
(needs.build-stack-build.result == 'success' || needs.build-stack-build.result == 'skipped')
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0
- name: Set up pack CLI
uses: buildpacks/github-actions/setup-pack@c1c71086a0e89a65c04ea113390227fd7f05d9df # v6.0.0
- name: Log in to GHCR
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build stack images locally (single-arch)
run: |
docker build -t "${{ env.IMAGE_BASE }}/build:latest" ./stack/build
docker build -t "${{ env.IMAGE_BASE }}/run:latest" ./stack/run
- name: Create local builder
run: |
pack builder create validate-builder:ci \
--config builder.toml \
--pull-policy if-not-present
- name: Build Java sample with local builder
run: |
pack build validate-app:ci \
--path ./samples/java \
--builder validate-builder:ci \
--trust-builder \
--pull-policy if-not-present
- name: Verify Java sample responds correctly
run: |
docker run -d --name validate-test -p 8099:8080 validate-app:ci
for i in $(seq 1 30); do
RESP=$(curl -sf http://localhost:8099/ 2>/dev/null || echo "")
if echo "${RESP}" | grep -qi "hello"; then
echo "Validation passed: ${RESP}"
break
fi
echo "Waiting... (${i}/30)"
sleep 3
done
echo "${RESP}" | grep -qi "hello"
docker rm -f validate-test
build-builder:
name: Build builder image
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
needs:
- build-stack-build
- build-stack-run
- validate-builder
if: |
always() &&
github.event_name != 'pull_request' &&
(needs.build-stack-run.result == 'success') &&
(needs.build-stack-build.result == 'success' || needs.build-stack-build.result == 'skipped') &&
needs.validate-builder.result == 'success'
steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Set up pack CLI
uses: buildpacks/github-actions/setup-pack@c1c71086a0e89a65c04ea113390227fd7f05d9df # v6.0.0
- name: Log in to GHCR
uses: docker/login-action@abd2ef45e78c5afb21d64d4ca52ee8550d9572c7 # v4.5.1
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Determine builder tag
id: tag
run: |
if [[ "${GITHUB_REF}" == refs/tags/v* ]]; then
echo "tag=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"
else
echo "tag=latest" >> "$GITHUB_OUTPUT"
fi
- name: Create and publish builder to GHCR
run: |
pack builder create "${{ env.IMAGE_BASE }}:${{ steps.tag.outputs.tag }}" \
--config ./builder.toml \
--publish
cleanup-packages:
name: Cleanup old package versions
runs-on: ubuntu-latest
needs: [build-builder]
if: github.event_name != 'pull_request'
permissions:
packages: write
steps:
- name: Delete old versions – builder image
uses: actions/delete-package-versions@e5bc658cc4c965c472efe991f8beea3981499c55 # v5.0.0
with:
package-name: distroless-buildpack-builder-java-tiny
package-type: container
min-versions-to-keep: 20
token: ${{ secrets.GITHUB_TOKEN }}
- name: Delete old versions – build stack image
uses: actions/delete-package-versions@e5bc658cc4c965c472efe991f8beea3981499c55 # v5.0.0
with:
package-name: distroless-buildpack-builder-java-tiny/build
package-type: container
min-versions-to-keep: 20
token: ${{ secrets.GITHUB_TOKEN }}
- name: Delete old versions – run stack image
uses: actions/delete-package-versions@e5bc658cc4c965c472efe991f8beea3981499c55 # v5.0.0
with:
package-name: distroless-buildpack-builder-java-tiny/run
package-type: container
min-versions-to-keep: 20
token: ${{ secrets.GITHUB_TOKEN }}