Skip to content

fix: move os-update script to new permanent location after steamos-update refactor #8871

fix: move os-update script to new permanent location after steamos-update refactor

fix: move os-update script to new permanent location after steamos-update refactor #8871

Workflow file for this run

name: Build Bazzite
on:
schedule:
- cron: "40 4 * * 1" # 4:40 utc monday
pull_request:
branches:
- testing
- unstable
paths-ignore:
- "**.md"
- "**.txt"
- "installer/**"
- "repo_content/**"
- "spec_files/**"
- "post_install_files/**"
- "press_kit/**"
- "docs/**"
- ".github/workflows/build_iso*.yml"
push:
branches:
- testing
- unstable
paths-ignore:
- "**.md"
- "**.txt"
- "repo_content/**"
- "spec_files/**"
- "post_install_files/**"
- "press_kit/**"
- ".github/workflows/build_iso*.yml"
merge_group:
workflow_dispatch:
inputs:
handwritten:
description: "Small changelog:"
permissions: {}
concurrency:
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
cancel-in-progress: true
env:
REPO_OWNER: ${{ github.repository_owner }}
jobs:
push-ghcr:
name: Make
runs-on: ubuntu-24.04
continue-on-error: false
permissions:
contents: read
packages: write
id-token: write
attestations: write
artifact-metadata: write
strategy:
fail-fast: false
matrix:
image:
- bazzite
- bazzite-gnome
- bazzite-deck
- bazzite-deck-gnome
- bazzite-deck-nvidia
- bazzite-deck-nvidia-gnome
- bazzite-nvidia
- bazzite-gnome-nvidia
- bazzite-nvidia-open
- bazzite-gnome-nvidia-open
include:
- fedora_version: 44
kernel_flavor: ogc
kernel_version: 7.0.9-ogc3.2.fc44.x86_64
base_image_flavor: main
arch: x86_64
steps:
- name: Show disk space
run: sudo df -h
- name: Check if /mnt is there
id: check_mnt
run: |
if sudo mountpoint /mnt; then
echo "mnt_is_there=1" >>$GITHUB_OUTPUT
else
echo "mnt_is_there=0" >>$GITHUB_OUTPUT
fi
- name: Free Disk Space (Ubuntu)
if: ${{ steps.check_mnt.outputs.mnt_is_there == '1' }}
uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1
- name: Mount BTRFS for podman storage
uses: ublue-os/container-storage-action@main
if: ${{ steps.check_mnt.outputs.mnt_is_there == '1' }}
with:
target-dir: /var/lib/containers
# The image registry name must be lower-case, but GitHub usernames can be capitalized.
- name: Get lower-case equivalent of the repository owner's username
id: repo_owner_case
run: echo "lowercase=${REPO_OWNER,,}" >> "$GITHUB_OUTPUT"
- name: Define base variables
id: base
run: |
IMAGE="${{ matrix.image }}"
if [[ "$IMAGE" == *gnome* ]]; then
BASE_IMAGE_NAME="silverblue"
else
BASE_IMAGE_NAME="kinoite"
fi
echo "base_image_name=$BASE_IMAGE_NAME" >> "$GITHUB_OUTPUT"
#
# Define Container Target
#
if [[ "$IMAGE" == *"deck"* && "$IMAGE" == *"nvidia"* ]]; then
echo "container_target=bazzite-nvidia" >> "$GITHUB_OUTPUT"
echo "nvidia_base=bazzite-deck" >> "$GITHUB_OUTPUT"
echo "install_nvidia=true" >> "$GITHUB_OUTPUT"
elif [[ "$IMAGE" == *"nvidia"* ]]; then
echo "container_target=bazzite-nvidia" >> "$GITHUB_OUTPUT"
echo "nvidia_base=bazzite" >> "$GITHUB_OUTPUT"
echo "install_nvidia=true" >> "$GITHUB_OUTPUT"
elif [[ "$IMAGE" == *"deck"* ]]; then
echo "container_target=bazzite-deck" >> "$GITHUB_OUTPUT"
echo "nvidia_base=bazzite-deck" >> "$GITHUB_OUTPUT" # NOOP
echo "install_nvidia=false" >> "$GITHUB_OUTPUT"
else
echo "container_target=bazzite" >> "$GITHUB_OUTPUT"
echo "nvidia_base=bazzite" >> "$GITHUB_OUTPUT" # NOOP
echo "install_nvidia=false" >> "$GITHUB_OUTPUT"
fi
# Nvidia flavor
if [[ "$IMAGE" == *"nvidia-open" || "$IMAGE" == *"-deck-nvidia"* ]]; then
echo "nvidia_flavor=nvidia-open" >> "$GITHUB_OUTPUT"
else
echo "nvidia_flavor=nvidia-lts" >> "$GITHUB_OUTPUT"
fi
#
# Define push and pull registries
#
PULL_REGISTRY=ghcr.io/ublue-os
PUSH_REGISTRY=ghcr.io/${{ steps.repo_owner_case.outputs.lowercase }}
echo "push_registry=${PUSH_REGISTRY}" >> $GITHUB_OUTPUT
echo "pull_registry=${PULL_REGISTRY}" >> $GITHUB_OUTPUT
echo "output_image=${PUSH_REGISTRY}/${{ matrix.image }}" >> $GITHUB_OUTPUT
BASE_IMAGE="${PULL_REGISTRY}/$BASE_IMAGE_NAME-${{ matrix.base_image_flavor }}:${{ matrix.fedora_version }}"
echo "base_image=${BASE_IMAGE}" >> $GITHUB_OUTPUT
IMAGEREF="$PULL_REGISTRY/${{ matrix.image }}:stable"
echo "prev_ref=${IMAGEREF}" >> $GITHUB_OUTPUT
AKMODS_TAG="${{ matrix.kernel_flavor }}-${{ matrix.fedora_version }}-${{ matrix.kernel_version }}"
echo "akmods_tag=${AKMODS_TAG}" >> $GITHUB_OUTPUT
echo "Generated the following:"
cat $GITHUB_OUTPUT
# Checkout push-to-registry action GitHub repository
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
submodules: recursive
# Prepare offline documentation
- name: Download offline docs
id: download_offline_docs
continue-on-error: true
env:
docs_repo: ublue-os/docs.bazzite.gg
GH_TOKEN: ${{ github.token }}
run: |
DOCS_DIR="${{ github.workspace }}/system_files/desktop/shared/usr/share/ublue-os/docs/html"
mkdir -p $DOCS_DIR
cd $(mktemp -d)
gh run download --repo=$docs_repo -n github-pages
tar -xC "$DOCS_DIR" -f artifact.tar
- name: Check just syntax
uses: ublue-os/just-action@v3
- name: Pull Images and find versions
id: labels
env:
GH_TOKEN: ${{ github.token }}
run: |
set -eo pipefail
#
# Base Image and version
#
sudo podman pull ${{ steps.base.outputs.base_image }}
sudo skopeo inspect docker://${{ steps.base.outputs.base_image }} > source.json
UPSTREAM_TAG=$(jq -r '.Labels["org.opencontainers.image.version"]' source.json)
if [ -z "$UPSTREAM_TAG" ] || [ "null" = "$UPSTREAM_TAG" ]; then
echo "inspected image version must not be empty or null"
exit 1
fi
# Remove .0 suffix from upstream tag so we can add our own and
# the wrong one does not end up in the image.
UPSTREAM_TAG="${UPSTREAM_TAG%\.[0-9]}"
FEDORA_VERSION="${{ matrix.fedora_version }}"
SHA_SHORT="${GITHUB_SHA::7}"
if [ -n "${{ github.event.pull_request.number }}" ]; then
VERSION="pr-${FEDORA_VERSION}-${{ github.event.pull_request.number }}"
PRETTY_VERSION="PR (${{ github.event.pull_request.number }}, ${UPSTREAM_TAG})"
elif [[ ${{ github.ref_name }} == "unstable" ]]; then
VERSION="unstable-${UPSTREAM_TAG}"
PRETTY_VERSION="Unstable (F${UPSTREAM_TAG}, #${SHA_SHORT})"
elif [[ ${{ github.ref_name }} == "testing" ]]; then
VERSION="testing-${UPSTREAM_TAG}"
PRETTY_VERSION="Testing (F${UPSTREAM_TAG}, #${SHA_SHORT})"
else
VERSION="${UPSTREAM_TAG}"
PRETTY_VERSION="Stable (F${UPSTREAM_TAG})"
fi
echo "tag=${VERSION}" >> $GITHUB_OUTPUT
echo "pretty=${PRETTY_VERSION}" >> $GITHUB_OUTPUT
#
# Kernel & akmods
#
AKMODS_TAG="${{ steps.base.outputs.akmods_tag }}"
sudo podman pull ghcr.io/ublue-os/akmods:${AKMODS_TAG}
# sudo podman pull ghcr.io/ublue-os/akmods-extra:${AKMODS_TAG}
if [ "${{ steps.base.outputs.install_nvidia }}" == "true" ]; then
NVIDIA_FLAVOR="${{ steps.base.outputs.nvidia_flavor }}"
sudo podman pull "ghcr.io/ublue-os/akmods-${NVIDIA_FLAVOR}:${AKMODS_TAG}"
fi
echo "Generated the following:"
cat $GITHUB_OUTPUT
# Generate a file with all the build-args passed to buildah
- name: Prepare build args file
run: |
cat <<'EOF' >>build_args.txt
BASE_IMAGE_NAME=${{ steps.base.outputs.base_image_name }}
FEDORA_VERSION=${{ matrix.fedora_version }}
BASE_IMAGE=${{ steps.base.outputs.base_image }}
IMAGE_NAME=${{ matrix.image }}
IMAGE_VENDOR=${{ steps.repo_owner_case.outputs.lowercase }}
IMAGE_BRANCH=${{ github.ref_name }}
KERNEL_FLAVOR=${{ matrix.kernel_flavor }}
KERNEL_VERSION=${{ matrix.kernel_version }}
NVIDIA_FLAVOR=${{ steps.base.outputs.nvidia_flavor }}
NVIDIA_BASE=${{ steps.base.outputs.nvidia_base }}
SHA_HEAD_SHORT=${{ steps.base.outputs.sha_head_short }}
VERSION_TAG=${{ steps.labels.outputs.tag }}
VERSION_PRETTY=${{ steps.labels.outputs.pretty }}
ARCH=${{ matrix.arch }}
EOF
- name: DNF Package Cache Prep
id: cache-prep
env:
IMAGE: ${{ matrix.image }}
EVENT_NAME: ${{ github.event_name }}
REF_NAME: ${{ github.ref_name }}
FEDORA_VERSION: ${{ matrix.fedora_version }}
run: |
set -eoux pipefail
CACHE_NAME="bazzite-${FEDORA_VERSION}"
ALLOW_CACHE_WRITE="false"
# TODO: If we ever integrate dx images here then this may need to be adjusted
# TODO: remove testing here when we have cache on main branch
# PR caches are useless and may wipe cache on main
if [[ "${IMAGE}" =~ "-deck" ]] && \
[[ ! "${IMAGE}" =~ "gnome" ]] && \
[[ "${EVENT_NAME}" != "pull_request" ]] && \
[[ "${REF_NAME}" == "main" || "${REF_NAME}" == "testing" ]]; then
ALLOW_CACHE_WRITE="true"
fi
echo "cache_name=${CACHE_NAME}" >> "$GITHUB_OUTPUT"
echo "allow_cache_write=${ALLOW_CACHE_WRITE}" >> "$GITHUB_OUTPUT"
- name: Restore DNF package cache
uses: actions/cache/restore@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
env:
CACHE_NAME: ${{ steps.cache-prep.outputs.cache_name }}
ALLOW_CACHE_WRITE: ${{ steps.cache-prep.outputs.allow_cache_write }}
with:
path: /var/tmp/buildah-cache-*
key: ${{ runner.os }}-${{ runner.arch }}-buildah-${{ env.CACHE_NAME }}-${{ github.run_id }}
restore-keys: |
${{ runner.os }}-${{ runner.arch }}-buildah-${{ env.CACHE_NAME }}-
${{ runner.os }}-${{ runner.arch }}-buildah-${{ env.CACHE_NAME }}
# Build image using buildah and save it to raw-img
- name: Build Image
id: build_image
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
sudo -E buildah build \
--target ${{ steps.base.outputs.container_target }} \
--build-arg-file build_args.txt \
--secret "id=GITHUB_TOKEN,env=GITHUB_TOKEN" \
--tag raw-img .
# https://github.com/actions/cache/issues/1533
- name: Hack around permission issue caching
id: cache-perms
run: |
sudo chmod 777 --recursive /var/tmp/buildah-cache-0
- name: Save DNF package cache
if: steps.cache-prep.outputs.allow_cache_write == 'true'
uses: actions/cache/save@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
env:
CACHE_NAME: ${{ steps.cache-prep.outputs.cache_name }}
ALLOW_CACHE_WRITE: ${{ steps.cache-prep.outputs.allow_cache_write }}
with:
path: /var/tmp/buildah-cache-*
key: ${{ runner.os }}-${{ runner.arch }}-buildah-${{ env.CACHE_NAME }}
# Relabel the image with Bazzite labels
- name: Apply Labels
id: relabel
env:
IMAGE_LABELS: |
io.artifacthub.package.logo-url=https://raw.githubusercontent.com/ublue-os/bazzite/main/repo_content/logo.png
io.artifacthub.package.readme-url=https://raw.githubusercontent.com/ublue-os/bazzite/refs/heads/main/README.md
org.opencontainers.image.description=Bazzite is a custom image that brings the best of Linux gaming to all of your devices - including your favorite handheld.
org.opencontainers.image.licenses=Apache-2.0
org.opencontainers.image.revision=${{ github.sha }}
org.opencontainers.image.source=https://bazzite.gg
org.opencontainers.image.title=Bazzite
org.opencontainers.image.vendor=Universal Blue
org.opencontainers.image.url=https://bazzite.gg
run: |
version="${{ matrix.fedora_version }}.$(date +%Y%m%d)"
if [[ "${{ github.ref_name }}" == "unstable" ]]; then
version="unstable-${version}"
elif [[ "${{ github.ref_name }}" == "testing" ]]; then
version="testing-${version}"
fi
# Clean out labels from base image
img=raw-img
container=$(sudo buildah from $img)
sudo buildah config --label "-" $container
sudo buildah commit --identity-label=false --rm $container $img
declare -A tags
while read -r t; do
tags["$t"]=1
done < <(skopeo list-tags "docker://${{ steps.base.outputs.output_image }}" 2>/dev/null | jq -r '.Tags[]' || true)
if [[ -v tags[$version] ]]; then
build=1
while true; do
tag="$version.$build"
if [[ ! -v tags[$tag] ]]; then
version=$tag
break
fi
((build++))
done
fi
# Figure out config
kver=$(sudo podman run --rm "$img" rpm -q --qf "%{VERSION}-%{RELEASE}.%{ARCH}\n" kernel-core)
filter='{ "packages": [inputs | split(" ") | select(length==2) | { (.[0]): .[1] }] | sort_by(keys) | add }'
mapfile -t labels <<< "$IMAGE_LABELS"
labels+=(
"org.opencontainers.image.version=$version"
"org.opencontainers.image.created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
"ostree.bootable=true"
"ostree.linux=$kver"
)
# Apply config to labels and annotations
container=$(sudo buildah from $img)
for line in "${labels[@]}"; do
[ -z "$line" ] && continue
sudo buildah config --label "$line" --annotation "$line" "$container"
done
sudo buildah commit --identity-label=false --rm $container $img
echo "version=$version" >> "$GITHUB_OUTPUT"
# Reprocess raw-img using rechunker which will delete it
- name: Run Rechunker
id: rechunk
run: |
container=$(sudo buildah from raw-img)
mnt=$(sudo buildah mount $container)
sudo bash -c "rm -rf $mnt/run/.* $mnt/run/* $mnt/tmp/.* $mnt/tmp/*"
sudo buildah umount $container
sudo buildah commit --identity-label=false --rm $container raw-img
sudo podman run --rm --privileged --volume /var/lib/containers:/var/lib/containers \
localhost/raw-img \
rpm-ostree compose build-chunked-oci \
--bootc --max-layers 127 --format-version 2 \
--from localhost/raw-img --output containers-storage:localhost/chunked-img
sudo podman untag raw-img
echo "ref=containers-storage:localhost/chunked-img" >> "$GITHUB_OUTPUT"
- name: Setup Syft
id: setup-syft
if: github.event_name != 'pull_request'
uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
with:
# FIXME: a renovate rule for this would be nice
syft-version: v1.44.0
- name: Generate SBOM
if: github.event_name != 'pull_request'
id: generate-sbom
env:
IMAGE: ${{ matrix.image }}
VERSION_TAG: ${{ steps.labels.outputs.tag }}
SYFT_CMD: ${{ steps.setup-syft.outputs.cmd }}
OCI_DIR: "/tmp/image-oci-dir"
run: |
mkdir -p ${OCI_DIR}/rootfs
sudo podman container create --replace --name "${IMAGE}" "localhost/chunked-img"
sudo podman export "${IMAGE}" | sudo tar -C ${OCI_DIR}/rootfs -xf -
sudo podman container rm "${IMAGE}"
SBOM="$(mktemp -d)/sbom.json"
export SYFT_PARALLELISM=$(($(nproc)*2))
sudo $SYFT_CMD --source-name "${IMAGE}"-"${VERSION_TAG}" ${OCI_DIR} -o syft-json=${SBOM}
du -sh ${SBOM}
echo "SBOM=${SBOM}" >> $GITHUB_OUTPUT
sudo rm -rf ${OCI_DIR}
# Generate tags after relabel runs and checks the primary tag is not duplicated
# If it is, relabel will suffix it by .1, .2, etc and put it in steps.relabel.outputs.version
- name: Generate tags
id: generate-tags
shell: bash
run: |
# Common vars for generating tags
VERSION_TAG="${{ steps.relabel.outputs.version }}"
if [[ ${{ github.ref_name }} == "unstable" ]]; then
BUILD_TAGS=("unstable" "unstable-${{ matrix.fedora_version }}")
elif [[ ${{ github.ref_name }} == "testing" ]]; then
BUILD_TAGS=("testing" "testing-${{ matrix.fedora_version }}")
else
BUILD_TAGS=("stable-${VERSION_TAG}" "latest" "stable" "stable-${{ matrix.fedora_version }}")
fi
echo "Generated the following build tags: "
for TAG in "${BUILD_TAGS[@]}"; do
echo "${TAG}"
done
echo "alias_tags=${BUILD_TAGS[*]}" >> $GITHUB_OUTPUT
- name: Install dgoss
run: |
curl -L \
https://github.com/goss-org/goss/releases/latest/download/goss-linux-amd64 \
-o /usr/local/bin/goss
chmod +rx /usr/local/bin/goss
curl -L \
https://github.com/goss-org/goss/releases/latest/download/dgoss \
-o /usr/local/bin/dgoss
chmod +rx /usr/local/bin/dgoss
- name: Run goss tests
run: |
sudo tests/dgoss/dgoss-tests.sh tests/dgoss/tests.d "${{ steps.rechunk.outputs.ref }}"
- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
run: |
echo ${{ secrets.GITHUB_TOKEN }} | sudo podman login ghcr.io -u ${{ github.actor }} --password-stdin
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
# Push the image to GHCR (Image Registry)
- name: Push to GHCR
id: push
if: github.event_name != 'pull_request'
uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v4.0.0
env:
ALIAS_TAGS: ${{ steps.generate-tags.outputs.alias_tags }}
OUTPUT_IMAGE: ${{ steps.base.outputs.output_image }}
RECHUNK_REF: ${{ steps.rechunk.outputs.ref }}
VERSION: ${{ steps.relabel.outputs.version }}
with:
max_attempts: 3
retry_wait_seconds: 15
timeout_minutes: 10
command: |
log_sum() { echo "$1" >> $GITHUB_STEP_SUMMARY; }
log_sum '# Push to GHCR result'
log_sum '```'
for tag in ${VERSION} ${ALIAS_TAGS}; do
dest_image="${OUTPUT_IMAGE}:$tag"
sudo skopeo copy ${RECHUNK_REF} docker://$dest_image --digestfile=/tmp/digestfile
log_sum "$dest_image"
done
log_sum '```'
echo "digest=$(< /tmp/digestfile)" >> $GITHUB_OUTPUT
- name: Install Cosign
if: github.event_name != 'pull_request'
uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
with:
cosign-release: "v2.6.1"
- name: Sign container image
if: github.event_name != 'pull_request'
run: |
cosign sign -y --key env://COSIGN_PRIVATE_KEY --new-bundle-format=false ${{ steps.base.outputs.output_image }}@${{ steps.push.outputs.digest }}
env:
COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}
- name: Install ORAS
if: github.event_name != 'pull_request'
uses: oras-project/setup-oras@38de303aac69abb66f3e6255b7198bff35f323e3 # v2.0.0
- name: Login to GitHub Container Registry with ORAS
if: github.event_name != 'pull_request'
run: |
echo ${{ secrets.GITHUB_TOKEN }} | oras login ghcr.io -u ${{ github.actor }} --password-stdin
- name: Upload SBOM
if: github.event_name != 'pull_request'
id: upload-sbom
env:
IMAGE: ${{ steps.base.outputs.output_image }}
DIGEST: ${{ steps.push.outputs.digest }}
SBOM: ${{ steps.generate-sbom.outputs.SBOM }}
run: |
cd "$(dirname "${SBOM}")"
oras attach \
--artifact-type application/vnd.spdx+json \
--annotation filename=$(basename "$SBOM") \
"${IMAGE}@${DIGEST}" \
"$(basename ${SBOM})"
sbom_digest=$(oras discover --format json "${IMAGE}@${DIGEST}" | jq -r '.referrers[] | select(.artifactType == "application/vnd.spdx+json") | .digest')
echo "sbom_digest=${sbom_digest}" >> $GITHUB_OUTPUT
- name: Sign SBOM OCI Artifact
if: github.event_name != 'pull_request'
env:
COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}
IMAGE: ${{ steps.base.outputs.output_image }}
SBOM_DIGEST: ${{ steps.upload-sbom.outputs.sbom_digest }}
run: |
cosign sign -y --key env://COSIGN_PRIVATE_KEY --new-bundle-format=false ${IMAGE}@${SBOM_DIGEST}
- name: Attestation
if: github.event_name != 'pull_request'
uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
with:
subject-name: ${{ steps.base.outputs.output_image }}
subject-digest: ${{ steps.push.outputs.digest }}
push-to-registry: true
generate_release:
name: Generate Release
needs: [push-ghcr]
if: github.event_name != 'pull_request'
permissions:
contents: write
secrets: inherit
uses: ./.github/workflows/generate_release.yml
kickoff_bazzite_dx:
runs-on: ubuntu-24.04
needs: [generate_release]
if: github.repository == 'ublue-os/bazzite' && github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
steps:
- name: Kickoff Bazzite-DX
uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v4
continue-on-error: true
with:
token: ${{ secrets.PAT }}
repository: ublue-os/bazzite-dx
event-type: build