Skip to content

Build and Push Image #649

Build and Push Image

Build and Push Image #649

Workflow file for this run

name: Build and Push Image
on:
push:
branches:
- "custom"
schedule:
- cron: "00 01 * * *" # 10:00am everyday
merge_group:
pull_request:
branches:
- custom
paths-ignore:
- "**.md"
workflow_dispatch:
env:
IMAGE_REGISTRY: ghcr.io/${{ github.repository_owner }}
concurrency:
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
cancel-in-progress: true
jobs:
push-ghcr:
name: Make
runs-on: ubuntu-24.04
env:
BASE_IMAGE_NAME: silverblue
permissions:
contents: read
packages: write
id-token: write
strategy:
fail-fast: false
matrix:
image_flavor: [main, nvidia]
base_name: [os]
fedora_version: [stable, latest]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Check just syntax
uses: ublue-os/just-action@v1
- name: Matrix Variables
run: |
# IMAGE_NAME
if [[ "${{ matrix.image_flavor }}" == "main" ]]; then
echo "IMAGE_NAME=${{ matrix.base_name }}" >> $GITHUB_ENV
else
echo "IMAGE_NAME=${{ format('{0}-{1}', matrix.base_name, matrix.image_flavor) }}" >> $GITHUB_ENV
fi
# AKMODS_FLAVOR
if [[ "${{ matrix.fedora_version }}" =~ stable|gts ]]; then
echo "AKMODS_FLAVOR=coreos-stable" >> $GITHUB_ENV
else
echo "AKMODS_FLAVOR=main" >> $GITHUB_ENV
fi
# Env for matrix.image_flavor
if [[ "${{ matrix.image_flavor }}" == "nvidia" && \
"${{ matrix.fedora_version }}" != "beta" ]]; then
echo "image_flavor=main" >> $GITHUB_ENV
echo "nvidia_type=nvidia" >> $GITHUB_ENV
elif [[ "${{ matrix.image_flavor }}" == "main" && \
"${{ matrix.fedora_version }}" != "beta" ]]; then
echo "image_flavor=${{ matrix.image_flavor }}" >> $GITHUB_ENV
else
echo "image_flavor=${{ matrix.image_flavor }}" >> $GITHUB_ENV
fi
- name: Get Current Fedora Version
id: labels
uses: Wandalen/wretry.action@6feedb7dedadeb826de0f45ff482b53b379a7844 # v3.5.0
with:
attempt_limit: 3
attempt_delay: 15000
command: |
set -eox pipefail
if [[ ${{ matrix.fedora_version }} == "stable" ]]; then
KERNEL_RELEASE=$(skopeo inspect docker://quay.io/fedora/fedora-coreos:stable | jq -r '.Labels["ostree.linux"]')
elif [[ ${{ matrix.fedora_version }} == "gts" ]]; then
# always get base kernel release because we use it to get Fedora release not from CoreOS
base_kernel_release=$(skopeo inspect docker://ghcr.io/ublue-os/silverblue-${{ env.image_flavor }}:${{ matrix.fedora_version }} | jq -r '.Labels["ostree.linux"]')
coreos_kernel_release=$(skopeo inspect docker://quay.io/fedora/fedora-coreos:stable | jq -r '.Labels["ostree.linux"]')
coreos_fedora_version=$(echo $coreos_kernel_release | grep -oP 'fc\K[0-9]+')
# this allows GTS to be same as CoreOS or earlier, depending on release cycle timing
fedora_version=$(echo $base_kernel_release | grep -oP 'fc\K[0-9]+')
KERNEL_RELEASE=$(skopeo inspect docker://ghcr.io/ublue-os/coreos-stable-kernel:${fedora_version} | jq -r '.Labels["ostree.linux"]')
else
base_kernel_release=$(skopeo inspect docker://ghcr.io/ublue-os/silverblue-${{ env.image_flavor }}:${{ matrix.fedora_version }} | jq -r '.Labels["ostree.linux"]')
base_fedora_version=$(echo $base_kernel_release | grep -oP 'fc\K[0-9]+')
KERNEL_RELEASE=$(skopeo inspect docker://ghcr.io/ublue-os/${{ env.AKMODS_FLAVOR }}-kernel:${base_fedora_version} | jq -r '.Labels["ostree.linux"]')
fi
fedora_version=$(echo $KERNEL_RELEASE | grep -oP 'fc\K[0-9]+')
echo "kernel_release=$KERNEL_RELEASE" >> $GITHUB_ENV
echo "fedora_version=$fedora_version" >> $GITHUB_ENV
ver=$(skopeo inspect docker://ghcr.io/ublue-os/${{ env.BASE_IMAGE_NAME }}-${{ env.image_flavor }}:$fedora_version | jq -r '.Labels["org.opencontainers.image.version"]')
if [ -z "$ver" ] || [ "null" = "$ver" ]; then
echo "inspected image version must not be empty or null"
exit 1
fi
echo "VERSION=$ver" >> $GITHUB_ENV
- name: Verify Kernel Version Matches
uses: Wandalen/wretry.action@6feedb7dedadeb826de0f45ff482b53b379a7844 # v3.5.0
with:
attempt_limit: 3
attempt_delay: 15000
command: |
set -x
akmods_version=$(skopeo inspect docker://ghcr.io/ublue-os/akmods:${{ env.AKMODS_FLAVOR }}-${{ env.fedora_version }} | jq -r '.Labels["ostree.linux"]')
if [[ "${akmods_version}" == "${{ env.kernel_release }}" ]]; then
echo "Kernel Versions Match"
else
echo "Kernel Version do Not Match"
exit 1
fi
- name: Generate tags
id: generate-tags
shell: bash
run: |
# Generate a timestamp for creating an image version history
TIMESTAMP="$(date +%Y%m%d)"
FEDORA_VERSION="${{ matrix.fedora_version }}"
if [[ "${{ matrix.fedora_version }}" == "stable" ]]; then
IS_LATEST_VERSION=false
IS_STABLE_VERSION=true
IS_GTS_VERSION=false
IS_BETA_VERSION=false
IS_COREOS=true
elif [[ "${{ matrix.fedora_version }}" == "gts" ]]; then
IS_LATEST_VERSION=false
IS_STABLE_VERSION=true
IS_GTS_VERSION=true
IS_BETA_VERSION=false
IS_COREOS=false
elif [[ "${{ matrix.fedora_version }}" == "latest" ]]; then
IS_LATEST_VERSION=true
IS_STABLE_VERSION=true
IS_GTS_VERSION=false
IS_BETA_VERSION=false
IS_COREOS=false
elif [[ "${{ matrix.fedora_version }}" == "beta" ]]; then
IS_LATEST_VERSION=false
IS_STABLE_VERSION=false
IS_GTS_VERSION=false
IS_BETA_VERSION=true
IS_COREOS=false
fi
COMMIT_TAGS=()
BUILD_TAGS=()
# Have tags for tracking builds during pull request
SHA_SHORT="${GITHUB_SHA::7}"
COMMIT_TAGS+=("pr-${{ github.event.number }}-${FEDORA_VERSION}")
COMMIT_TAGS+=("${SHA_SHORT}-${FEDORA_VERSION}")
if [[ "$IS_LATEST_VERSION" == "true" ]] && \
[[ "$IS_STABLE_VERSION" == "true" ]]; then
COMMIT_TAGS+=("pr-${{ github.event.number }}")
COMMIT_TAGS+=("${SHA_SHORT}")
fi
TODAY="$(date +%A)"
BUILD_TAGS=("${{ env.fedora_version }}" "${{ env.fedora_version }}-${TIMESTAMP}")
if [[ "$IS_LATEST_VERSION" == "true" ]] && \
[[ "$IS_STABLE_VERSION" == "true" ]]; then
BUILD_TAGS+=("latest")
echo "DEFAULT_TAG=latest" >> $GITHUB_ENV
elif [[ "$IS_LATEST_VERSION" == "false" ]] && \
[[ "$IS_STABLE_VERSION" == "true" ]]; then
BUILD_TAGS+=("stable")
echo "DEFAULT_TAG=stable" >> $GITHUB_ENV
elif [[ "$IS_GTS_VERSION" == "true" ]]; then
BUILD_TAGS+=("gts")
echo "DEFAULT_TAG=gts" >> $GITHUB_ENV
elif [[ "$IS_BETA_VERSION" == "true" ]]; then
BUILD_TAGS+=("beta")
echo "DEFAULT_TAG=beta" >> $GITHUB_ENV
elif [[ "$IS_COREOS" == "true" ]]; then
echo "DEFAULT_TAG=stable" >> $GITHUB_ENV
fi
alias_tags=("${BUILD_TAGS[@]}")
echo "Generated the following build tags: "
for TAG in "${BUILD_TAGS[@]}"; do
echo "${TAG}"
done
echo "alias_tags=${alias_tags[*]}" >> $GITHUB_OUTPUT
# Build metadata
- name: Image Metadata
uses: docker/metadata-action@v5
id: meta
with:
images: |
${{ env.IMAGE_NAME }}
labels: |
org.opencontainers.image.title=${{ env.IMAGE_NAME }}
org.opencontainers.image.version=${{ env.VERSION }}
org.opencontainers.image.description=Fedora Silverblue with tweaks
ostree.linux=${{ env.kernel_release }}
- name: Define env.SHA_HEAD_SHORT
run: |
echo "SHA_HEAD_SHORT=${GITHUB_SHA::7}" >> $GITHUB_ENV
- name: Maximize build space
uses: ublue-os/remove-unwanted-software@v7
with:
remove-codeql: true
- name: Pull images
uses: Wandalen/wretry.action@6feedb7dedadeb826de0f45ff482b53b379a7844 # v3.5.0
with:
attempt_limit: 3
attempt_delay: 15000
command: |
# pull the base image used for FROM in containerfile so
# we can retry on that unfortunately common failure case
sudo podman pull ghcr.io/ublue-os/${{ env.BASE_IMAGE_NAME }}-${{ env.image_flavor }}:${{ env.fedora_version }}
sudo podman pull ghcr.io/ublue-os/akmods:${{ env.AKMODS_FLAVOR }}-${{ env.fedora_version }}
sudo podman pull ghcr.io/ublue-os/akmods-nvidia:${{ env.AKMODS_FLAVOR }}-${{ env.fedora_version }}
sudo podman pull ghcr.io/ublue-os/${{ env.AKMODS_FLAVOR }}-kernel:${{ env.kernel_release }}
- name: Build Image
id: build_image
run: |
set -euox pipefail
BUILD_ARGS=()
BUILD_ARGS+=("--build-arg" "BASE_IMAGE_NAME=${{ env.BASE_IMAGE_NAME }}")
BUILD_ARGS+=("--build-arg" "IMAGE_NAME=${{ env.IMAGE_NAME }}")
BUILD_ARGS+=("--build-arg" "IMAGE_FLAVOR=${{ env.image_flavor }}")
BUILD_ARGS+=("--build-arg" "IMAGE_VENDOR=${{ github.repository_owner }}")
BUILD_ARGS+=("--build-arg" "FEDORA_MAJOR_VERSION=${{ env.fedora_version }}")
BUILD_ARGS+=("--build-arg" "TARGET_BASE=${{ env.TARGET_BASE }}")
BUILD_ARGS+=("--build-arg" "AKMODS_FLAVOR=${{ env.AKMODS_FLAVOR }}")
BUILD_ARGS+=("--build-arg" "NVIDIA_TYPE=${{ env.nvidia_type }}")
BUILD_ARGS+=("--build-arg" "KERNEL=${{ env.kernel_release }}")
BUILD_ARGS+=("--build-arg" "IMAGE_TAG=${{ matrix.fedora_version }}")
BUILD_ARGS+=("--build-arg" "SHA_HEAD_SHORT=${{ env.SHA_HEAD_SHORT }}")
TAG_ARGS=()
IFS=' ' read -r -a tags_array <<< "${{ steps.generate-tags.outputs.alias_tags }}"
for tag in "${tags_array[@]}"; do
TAG_ARGS+=("--tag" "${{ env.IMAGE_NAME }}:${tag}")
done
LABEL_ARGS=()
IFS=' ' read -r -a labels_array <<< "${{ steps.meta.outputs.labels }}"
for label in "${labels_array[@]}"; do
LABEL_ARGS+=("--label" "${label}")
done
sudo podman build --format docker --target base \
"${BUILD_ARGS[@]}" \
"${TAG_ARGS[@]}" \
"${LABEL_ARGS[@]}" \
.
sudo podman image ls
echo "image=${{ env.IMAGE_NAME }}" >> $GITHUB_OUTPUT
echo "tags=${{ steps.generate-tags.outputs.alias_tags }}" >> $GITHUB_OUTPUT
- name: Lowercase Registry
id: registry_case
uses: ASzc/change-string-case-action@d0603cd0a7dd490be678164909f65c7737470a7f # v6
with:
string: ${{ env.IMAGE_REGISTRY }}
- name: Rechunk Image
id: rechunk
uses: hhd-dev/rechunk@v0.8.6
with:
rechunk: ghcr.io/hhd-dev/rechunk:v0.8.6
ref: ${{ steps.build_image.outputs.image }}:${{ env.DEFAULT_TAG }}
skip_compression: "true"
labels: ${{ steps.meta.outputs.labels }}
prev-ref: ${{ steps.registry_case.outputs.lowercase }}/${{ steps.build_image.outputs.image }}:${{ env.DEFAULT_TAG }}
# Overwrite the image with the chuncked image
- name: Load Rechunked Image
run: |
sudo podman rmi $(sudo podman image ls -qa) --force
IMAGE=$(sudo podman pull ${{ steps.rechunk.outputs.ref }})
sudo rm -rf ${{ steps.rechunk.outputs.output }}
for tag in ${{ steps.build_image.outputs.tags }}; do
sudo podman tag $IMAGE ${{ env.IMAGE_NAME }}:${tag}
done
- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
run: |
echo ${{ secrets.GITHUB_TOKEN }} | podman login ghcr.io -u ${{ github.actor }} --password-stdin
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Push to GHCR
id: push
if: github.event_name != 'pull_request'
uses: Wandalen/wretry.action@6feedb7dedadeb826de0f45ff482b53b379a7844 # v3.5.0
with:
attempt_limit: 3
attempt_delay: 15000
command: |
set -euox pipefail
for tag in ${{ steps.build_image.outputs.tags }}; do
sudo podman push ${{ env.IMAGE_NAME }}:${tag} ${{ steps.registry_case.outputs.lowercase }}/${{ env.IMAGE_NAME }}:${tag}
done
digest=$(skopeo inspect docker://${{ steps.registry_case.outputs.lowercase }}/${{ env.IMAGE_NAME }}:${{ env.DEFAULT_TAG }} --format '{{.Digest}}')
echo "digest=${digest}" >> $GITHUB_OUTPUT
# Sign container
- uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3.7.0
- name: Sign container image
if: github.event_name != 'pull_request'
run: |
cosign sign -y --key env://COSIGN_PRIVATE_KEY ${{ steps.registry_case.outputs.lowercase }}/${{ env.IMAGE_NAME }}@${TAGS}
env:
TAGS: ${{ steps.push.outputs.outputs && fromJSON(steps.push.outputs.outputs).digest }}
COSIGN_EXPERIMENTAL: false
COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}
- name: Generate file containing outputs
if: github.event_name != 'pull_request'
env:
DIGEST: ${{ steps.push.outputs.outputs && fromJSON(steps.push.outputs.outputs).digest }}
IMAGE_REGISTRY: ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}
IMAGE_NAME: ${{ env.IMAGE_NAME }}
IMAGE_FLAVOR: ${{ env.image_flavor }}
FEDORA_VERSION: ${{ matrix.fedora_version }}
run: echo "${IMAGE_REGISTRY}@${DIGEST}" > "${IMAGE_NAME}-${IMAGE_FLAVOR}-${FEDORA_VERSION}.txt"
- name: Upload artifact
if: github.event_name != 'pull_request'
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4
with:
name: image-${{ env.IMAGE_NAME }}-${{ env.image_flavor }}-${{ matrix.fedora_version }}
retention-days: 1
if-no-files-found: error
path: |
${{ env.IMAGE_NAME }}-${{ env.image_flavor }}-${{ matrix.fedora_version }}.txt
check:
name: Check all builds successful
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
needs: [push-ghcr]
steps:
- name: Exit on failure
if: ${{ needs.push-ghcr.result == 'failure' }}
shell: bash
run: exit 1
- name: Exit
shell: bash
run: exit 0