Skip to content

Commit db1464d

Browse files
committed
staged-images: Add chunkah-staged bootc base image builds
Add infrastructure to build rechunked bootc base images using chunkah. These 'staged' images mirror upstream fedora-bootc and centos-bootc, strip /sysroot (ostree data), and rechunk with content-based layers for optimal layer reuse across updates. Source images are pinned by @sha256 digest for reproducibility, with a Renovate custom regex manager to automatically bump digests when upstream tags are updated. Target images: - ghcr.io/bootc-dev/fedora-bootc-staged:43 - ghcr.io/bootc-dev/fedora-bootc-staged:44 - ghcr.io/bootc-dev/centos-bootc-staged:stream10 Closes: #151 Assisted-by: OpenCode (Claude Opus 4)
1 parent 86f10ae commit db1464d

4 files changed

Lines changed: 154 additions & 0 deletions

File tree

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
name: Build chunkah-staged bootc base images
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- 'staged-images/**'
8+
- '.github/workflows/build-staged-images.yml'
9+
pull_request:
10+
paths:
11+
- 'staged-images/**'
12+
- '.github/workflows/build-staged-images.yml'
13+
schedule:
14+
# Rebuild weekly to pick up upstream base image updates
15+
- cron: '0 6 * * 1'
16+
workflow_dispatch:
17+
18+
concurrency:
19+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
20+
cancel-in-progress: true
21+
22+
env:
23+
REGISTRY: ghcr.io
24+
25+
jobs:
26+
build-staged:
27+
name: Build ${{ matrix.name }}:${{ matrix.tag }}
28+
runs-on: ubuntu-24.04
29+
permissions:
30+
contents: read
31+
packages: write
32+
strategy:
33+
fail-fast: false
34+
matrix:
35+
include:
36+
- name: fedora-bootc-staged
37+
tag: "43"
38+
# renovate: datasource=docker depName=quay.io/fedora/fedora-bootc
39+
source: quay.io/fedora/fedora-bootc:43@sha256:53829d163d685800b3223c216f0714d00051b8e585d2797defcfc4953dc120e5
40+
- name: fedora-bootc-staged
41+
tag: "44"
42+
# renovate: datasource=docker depName=quay.io/fedora/fedora-bootc
43+
source: quay.io/fedora/fedora-bootc:44@sha256:ce6d9786604260fc26adf1df50805b3b39e6c9bcb7f3f40411339e83c4a5d36a
44+
- name: centos-bootc-staged
45+
tag: stream9
46+
# renovate: datasource=docker depName=quay.io/centos-bootc/centos-bootc
47+
source: quay.io/centos-bootc/centos-bootc:stream9@sha256:70236424fb0ffb6a59e8e3d3cbc0df9f87bd3284ccbc70a93efd24da1e6544fb
48+
- name: centos-bootc-staged
49+
tag: stream10
50+
# renovate: datasource=docker depName=quay.io/centos-bootc/centos-bootc
51+
source: quay.io/centos-bootc/centos-bootc:stream10@sha256:d46e5198288642f45ce559f39be4ac6b34d1afe03c1d7836591b8a57655010c2
52+
53+
steps:
54+
- name: Checkout
55+
uses: actions/checkout@v6
56+
57+
- name: Log in to GHCR
58+
if: github.event_name != 'pull_request'
59+
uses: docker/login-action@v4
60+
with:
61+
registry: ${{ env.REGISTRY }}
62+
username: ${{ github.actor }}
63+
password: ${{ secrets.GITHUB_TOKEN }}
64+
65+
- name: Pull source image
66+
run: podman pull ${{ matrix.source }}
67+
68+
- name: Write source image config to build context
69+
working-directory: staged-images
70+
run: podman inspect ${{ matrix.source }} > source-config.json
71+
72+
- name: Build staged image
73+
working-directory: staged-images
74+
run: |
75+
buildah build --skip-unused-stages=false \
76+
--build-arg SOURCE_IMAGE=${{ matrix.source }} \
77+
--build-arg MAX_LAYERS=128 \
78+
-f Containerfile.staged \
79+
-t ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ matrix.name }}:${{ matrix.tag }} \
80+
.
81+
82+
- name: Verify image
83+
run: |
84+
echo "=== Image labels ==="
85+
podman inspect ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ matrix.name }}:${{ matrix.tag }} | jq '.[0].Config.Labels'
86+
echo "=== Layer count ==="
87+
podman inspect ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ matrix.name }}:${{ matrix.tag }} | jq '.[0].RootFS.Layers | length'
88+
89+
- name: Push staged image
90+
if: github.event_name != 'pull_request'
91+
run: |
92+
podman push ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ matrix.name }}:${{ matrix.tag }}

renovate-shared-config.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,17 @@
5757
"# renovate: datasource=(?<datasource>[a-z-]+) depName=(?<depName>[^\\s]+)\\n\\s*(?:export )?\\w*VERSION=(?<currentValue>v?\\S+)"
5858
]
5959
},
60+
// Container image digest pinning in YAML workflows
61+
// Matches patterns like:
62+
// # renovate: datasource=docker depName=quay.io/fedora/fedora-bootc
63+
// source: quay.io/fedora/fedora-bootc:43@sha256:abc123...
64+
{
65+
"customType": "regex",
66+
"managerFilePatterns": ["**/*.yml", "**/*.yaml"],
67+
"matchStrings": [
68+
"# renovate: datasource=(?<datasource>docker) depName=(?<depName>[^\\s]+)\\n\\s*\\w+:\\s*\\S+:(?<currentValue>[^@\\s]+)@(?<currentDigest>sha256:[a-f0-9]+)"
69+
]
70+
},
6071
// Git refs (commit SHA) tracking in Justfiles and YAML workflows
6172
// Justfile example:
6273
// # renovate: datasource=git-refs depName=https://github.com/org/repo branch=main
@@ -134,6 +145,22 @@
134145
"groupName": "Docker",
135146
"enabled": true
136147
},
148+
// Group staged bootc base image digest updates separately
149+
//
150+
// These are the upstream source images for chunkah-staged builds.
151+
// Digest updates trigger a rebuild of the staged images, so they
152+
// get their own PR. Must come after the Docker group rule so it
153+
// takes precedence (Renovate applies all matching rules in order,
154+
// later rules win).
155+
{
156+
"description": ["Staged bootc base image digest updates"],
157+
"matchManagers": ["custom.regex"],
158+
"matchDepNames": [
159+
"quay.io/fedora/fedora-bootc",
160+
"quay.io/centos-bootc/centos-bootc"
161+
],
162+
"groupName": "staged-images"
163+
},
137164
// bcvk gets its own group so it isn't blocked by the weekly schedule
138165
// applied to other Docker group members. Without this, the Docker group
139166
// PR can only be created on Sundays (when all deps are in-schedule),

staged-images/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
source-config.json
2+
out.ociarchive

staged-images/Containerfile.staged

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Containerfile.staged — Rechunk a bootc base image with chunkah
2+
#
3+
# Takes an upstream bootc image (fedora-bootc or centos-bootc), strips
4+
# the /sysroot (ostree data), and rechunks using chunkah for optimal
5+
# layer reuse across updates. The result is a "staged" base image
6+
# suitable for use as a FROM base in bootc development.
7+
#
8+
# Usage:
9+
# podman pull quay.io/fedora/fedora-bootc:44
10+
# podman inspect quay.io/fedora/fedora-bootc:44 > source-config.json
11+
# buildah build --skip-unused-stages=false \
12+
# --build-arg SOURCE_IMAGE=quay.io/fedora/fedora-bootc:44 \
13+
# -f Containerfile.staged .
14+
15+
ARG SOURCE_IMAGE
16+
ARG CHUNKAH=quay.io/jlebon/chunkah:latest
17+
ARG MAX_LAYERS=128
18+
19+
FROM ${SOURCE_IMAGE} AS source
20+
21+
FROM ${CHUNKAH} AS chunkah
22+
ARG MAX_LAYERS
23+
RUN --mount=type=bind,target=/run/src,rw \
24+
--mount=from=source,target=/chunkah,ro \
25+
chunkah build \
26+
--config /run/src/source-config.json \
27+
--prune /sysroot/ \
28+
--max-layers "${MAX_LAYERS}" \
29+
--label ostree.commit- \
30+
--label ostree.final-diffid- \
31+
> /run/src/out.ociarchive
32+
33+
FROM oci-archive:out.ociarchive

0 commit comments

Comments
 (0)