Updated the workflow to fetch the final image digest directly from GHCR instead of calculating it from the OCI archive.
171 lines
6.9 KiB
YAML
171 lines
6.9 KiB
YAML
name: Build container image
|
|
on:
|
|
pull_request:
|
|
branches:
|
|
- main
|
|
schedule:
|
|
- cron: '05 12 * * 2,5'
|
|
workflow_dispatch:
|
|
|
|
env:
|
|
IMAGE_DESC: "Custom Fedora bootc image"
|
|
IMAGE_NAME: "${{ github.event.repository.name }}"
|
|
IMAGE_REGISTRY: "ghcr.io/${{ github.repository_owner }}"
|
|
DEFAULT_TAG: "stable"
|
|
|
|
concurrency:
|
|
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
build_push:
|
|
name: Build and push image
|
|
runs-on: ubuntu-24.04
|
|
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
id-token: write
|
|
|
|
steps:
|
|
- name: Prepare environment
|
|
run: |
|
|
echo "IMAGE_REGISTRY=${IMAGE_REGISTRY,,}" >> ${GITHUB_ENV}
|
|
echo "IMAGE_NAME=${IMAGE_NAME,,}" >> ${GITHUB_ENV}
|
|
|
|
- name: Checkout
|
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
|
|
|
- name: Mount BTRFS for podman storage
|
|
id: container-storage-action
|
|
uses: ublue-os/container-storage-action@911baca08baf30c8654933e9e9723cb399892140 # main
|
|
continue-on-error: true
|
|
with:
|
|
target-dir: /var/lib/containers
|
|
mount-opts: compress-force=zstd:2
|
|
|
|
- name: Image Metadata
|
|
uses: docker/metadata-action@030e881283bb7a6894de51c315a6bfe6a94e05cf # v5
|
|
id: metadata
|
|
with:
|
|
tags: |
|
|
type=raw,value=${{ env.DEFAULT_TAG }}
|
|
type=raw,value=${{ env.DEFAULT_TAG }}.{{date 'YYYYMMDD'}}
|
|
type=raw,value={{date 'YYYYMMDD'}}
|
|
type=sha,enable=${{ github.event_name == 'pull_request' }}
|
|
type=ref,event=pr
|
|
labels: |
|
|
org.opencontainers.image.created={{date 'YYYY-MM-DDTHH:mm:ssZ'}}
|
|
org.opencontainers.image.description=${{ env.IMAGE_DESC }}
|
|
org.opencontainers.image.documentation=https://raw.githubusercontent.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}/${{ github.sha }}/README.md
|
|
org.opencontainers.image.source=https://github.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}/blob/${{ github.sha }}/Containerfile
|
|
org.opencontainers.image.title=${{ env.IMAGE_NAME }}
|
|
org.opencontainers.image.url=https://github.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}/tree/${{ github.sha }}
|
|
org.opencontainers.image.vendor=${{ github.repository_owner }}
|
|
org.opencontainers.image.version=${{ env.DEFAULT_TAG }}.{{date 'YYYYMMDD'}}
|
|
containers.bootc=1
|
|
sep-tags: " "
|
|
sep-annotations: " "
|
|
|
|
- name: Cache buildah layers
|
|
uses: actions/cache@v5
|
|
with:
|
|
path: |
|
|
/var/lib/containers/storage/overlay
|
|
~/.cache/buildah
|
|
/tmp/.buildah-cache
|
|
key: ${{ runner.os }}-${{ github.workflow }}-${{ hashFiles('Containerfile') }}-${{ github.ref }}
|
|
restore-keys: |
|
|
${{ runner.os }}-${{ github.workflow }}-${{ hashFiles('Containerfile') }}-
|
|
|
|
- name: Build Image
|
|
id: build_image
|
|
uses: redhat-actions/buildah-build@7a95fa7ee0f02d552a32753e7414641a04307056 # v2
|
|
with:
|
|
containerfiles: |
|
|
./Containerfile
|
|
image: ${{ env.IMAGE_NAME }}
|
|
tags: ${{ env.DEFAULT_TAG }}
|
|
labels: ${{ steps.metadata.outputs.labels }}
|
|
oci: true
|
|
|
|
- name: Apply chunkah optimization
|
|
id: chunkah
|
|
run: |
|
|
set -x
|
|
BASE_IMAGE="${{ env.IMAGE_NAME }}:${{ env.DEFAULT_TAG }}"
|
|
|
|
# 1. Das ostree-Label im Runner sichern, bevor wir das Image zerlegen
|
|
OSTREE_DIFFID=$(podman inspect $BASE_IMAGE --format '{{index .Config.Labels "ostree.final-diffid"}}' 2>/dev/null || echo "")
|
|
|
|
# Rootfs extrahieren
|
|
CONTAINER_ID=$(podman create $BASE_IMAGE)
|
|
mkdir -p ./chunkah-in ./chunkah-out
|
|
podman export $CONTAINER_ID | tar -xf - -C ./chunkah-in
|
|
podman rm $CONTAINER_ID
|
|
|
|
# Die originale Image-Config extrahieren
|
|
podman inspect $BASE_IMAGE --format '{{json .Config}}' > ./chunkah-config.json
|
|
|
|
# LOKALER PATCH: Falls die DiffID existiert, schreiben wir sie via jq direkt in das JSON
|
|
if [ ! -z "$OSTREE_DIFFID" ]; then
|
|
jq --arg diffid "$OSTREE_DIFFID" '.Labels["ostree.final-diffid"] = $diffid' ./chunkah-config.json > ./chunkah-config-patched.json
|
|
mv ./chunkah-config-patched.json ./chunkah-config.json
|
|
fi
|
|
|
|
# Chunkah-Lauf (Übernimmt das lokal modifizierte JSON)
|
|
podman run --rm \
|
|
-v ./chunkah-in:/inputs:z \
|
|
-v ./chunkah-out:/outputs:z \
|
|
-v ./chunkah-config.json:/config.json:z \
|
|
quay.io/coreos/chunkah:latest \
|
|
build \
|
|
--config /config.json \
|
|
--prune /sysroot/ \
|
|
--max-layers 128 \
|
|
--compressed \
|
|
--output /outputs/image.ociarchive \
|
|
--rootfs /inputs
|
|
|
|
- name: Login to GitHub Container Registry
|
|
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v3
|
|
if: github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.actor }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Push to GHCR via Skopeo
|
|
if: github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
|
|
run: |
|
|
set -x
|
|
|
|
export REGISTRY_AUTH_FILE=$HOME/.docker/config.json
|
|
REGISTRY_PATH="${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}"
|
|
|
|
# Loop über alle Tags
|
|
for tag in ${{ steps.metadata.outputs.tags }}; do
|
|
skopeo copy \
|
|
--dest-compress-format=zstd \
|
|
--dest-compress-level=5 \
|
|
oci-archive:./chunkah-out/image.ociarchive \
|
|
docker://$REGISTRY_PATH:$tag
|
|
done
|
|
|
|
# KORREKTUR: Wir fragen den echten, finalen Digest direkt von GHCR ab
|
|
FINAL_REGISTRY_DIGEST=$(skopeo inspect docker://$REGISTRY_PATH:${{ env.DEFAULT_TAG }} --format '{{.Digest}}')
|
|
echo "REGISTRY_DIGEST=$FINAL_REGISTRY_DIGEST" >> $GITHUB_ENV
|
|
|
|
- name: Install Cosign
|
|
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
|
|
if: github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
|
|
|
|
- name: Sign container image
|
|
if: github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
|
|
run: |
|
|
# Signiert den exakten, von der Registry bestätigten Digest
|
|
cosign sign -y --key env://COSIGN_PRIVATE_KEY "${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}@${{ env.REGISTRY_DIGEST }}"
|
|
env:
|
|
COSIGN_EXPERIMENTAL: false
|
|
COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}
|