Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 23 additions & 33 deletions .github/workflows/build-disk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,14 @@ on:
required: false
default: false
type: boolean
platform:
required: true
type: choice
options:
- amd64
- arm64
pull_request:
branches:
- main
paths:
- './disk_config/disk.toml'
- './disk_config/iso.toml'
- './.github/workflows/build-disk.yml'
- 'disk_config/**'
- '.github/workflows/build-disk.yml'
- 'Containerfile.builder'
- 'scripts/build-disk.sh'

env:
IMAGE_NAME: ${{ github.event.repository.name }} # output of build.yml, keep in sync
Expand All @@ -36,7 +31,7 @@ concurrency:
jobs:
build:
name: Build disk images
runs-on: ${{ inputs.platform == 'amd64' && 'ubuntu-24.04' || 'ubuntu-24.04-arm' }}
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
Expand All @@ -54,22 +49,15 @@ jobs:
# Concatenate the types with a hyphen
DISK_TYPE=$(echo "${{ matrix.disk-type }}" | tr ' ' '-')
# Lowercase the image uri
echo "IMAGE_REGISTRY=${IMAGE_REGISTRY,,}" >> ${GITHUB_ENV}
echo "IMAGE_NAME=${IMAGE_NAME,,}" >> ${GITHUB_ENV}
echo "DISK_TYPE=${DISK_TYPE}" >> ${GITHUB_ENV}
echo "USER_UID=${USER_UID}" >> ${GITHUB_ENV}
echo "USER_GID=${USER_GID}" >> ${GITHUB_ENV}

- name: Install dependencies
if: inputs.platform == 'arm64'
run: |
set -x
sudo apt update -y
sudo apt install -y \
podman
{
echo "IMAGE_REGISTRY=${IMAGE_REGISTRY,,}"
echo "IMAGE_NAME=${IMAGE_NAME,,}"
echo "DISK_TYPE=${DISK_TYPE}"
echo "USER_UID=${USER_UID}"
echo "USER_GID=${USER_GID}"
} >> "$GITHUB_ENV"

- name: Maximize build space
if: inputs.platform != 'arm64'
uses: ublue-os/remove-unwanted-software@cc0becac701cf642c8f0a6613bbdaf5dc36b259e # v9
with:
remove-codeql: true
Expand All @@ -79,19 +67,20 @@ jobs:

- name: Build disk images
id: build
uses: osbuild/bootc-image-builder-action@main
with:
builder-image: ${{ env.BIB_IMAGE }}
config-file: ${{ matrix.disk-type == 'anaconda-iso' && './disk_config/iso.toml' || './disk_config/disk.toml' }}
image: ${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.DEFAULT_TAG }}
chown: ${{ env.USER_UID }}:${{ env.USER_GID }}
types: ${{ matrix.disk-type }}
additional-args: --use-librepo=True
env:
IMAGE_TYPE: ${{ matrix.disk-type }}
DISK_CONFIG: ${{ matrix.disk-type == 'anaconda-iso' && 'disk_config/iso-kde.toml' || 'disk_config/disk.toml' }}
run: |
sudo bash scripts/build-disk.sh \
"${IMAGE_REGISTRY}/${IMAGE_NAME}:${DEFAULT_TAG}" "$IMAGE_TYPE" \
"$DISK_CONFIG" "$PWD/output" "$BIB_IMAGE"
echo "output-directory=$PWD/output" >> "$GITHUB_OUTPUT"

- name: Upload disk images and Checksum to Job Artifacts
if: inputs.upload-to-s3 != true && github.event_name != 'pull_request'
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: tuxlinux-${{ matrix.disk-type }}-amd64
path: ${{ steps.build.outputs.output-directory }}
if-no-files-found: error
retention-days: 0
Expand All @@ -108,8 +97,9 @@ jobs:
RCLONE_CONFIG_S3_SECRET_ACCESS_KEY: ${{ secrets.S3_SECRET_ACCESS_KEY }}
RCLONE_CONFIG_S3_REGION: ${{ secrets.S3_REGION }}
RCLONE_CONFIG_S3_ENDPOINT: ${{ secrets.S3_ENDPOINT }}
S3_BUCKET: ${{ secrets.S3_BUCKET_NAME }}
SOURCE_DIR: ${{ steps.build.outputs.output-directory }}
run: |
sudo apt-get update
sudo apt-get install -y rclone
rclone copy $SOURCE_DIR S3:${{ secrets.S3_BUCKET_NAME }}
rclone copy "$SOURCE_DIR" "S3:${S3_BUCKET}/${DISK_TYPE}/"
28 changes: 18 additions & 10 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ on:
workflow_dispatch:

env:
IMAGE_DESC: "My Customized Universal Blue Image"
IMAGE_DESC: "TuxLinux: Bazzite NVIDIA-open KDE with development tools"
IMAGE_KEYWORDS: "bootc,ublue,universal-blue"
IMAGE_LOGO_URL: "https://avatars.githubusercontent.com/u/120078124?s=200&v=4" # Put your own image here for a fancy profile on https://artifacthub.io/!
IMAGE_NAME: "${{ github.event.repository.name }}" # output image name, usually same as repo name
IMAGE_REGISTRY: "ghcr.io/${{ github.repository_owner }}" # do not edit
DEFAULT_TAG: "latest"

concurrency:
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}-${{ inputs.brand_name}}-${{ inputs.stream_name }}
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
cancel-in-progress: true

jobs:
Expand All @@ -39,8 +39,10 @@ jobs:
- name: Prepare environment
run: |
# Lowercase the image uri
echo "IMAGE_REGISTRY=${IMAGE_REGISTRY,,}" >> ${GITHUB_ENV}
echo "IMAGE_NAME=${IMAGE_NAME,,}" >> ${GITHUB_ENV}
{
echo "IMAGE_REGISTRY=${IMAGE_REGISTRY,,}"
echo "IMAGE_NAME=${IMAGE_NAME,,}"
} >> "$GITHUB_ENV"

# These stage versions are pinned by https://github.com/renovatebot/renovate
- name: Checkout
Expand Down Expand Up @@ -69,7 +71,7 @@ jobs:
# E.G: 2022-02-08T15:38:15Z'
# https://artifacthub.io/docs/topics/repositories/container-images/
# https://linux.die.net/man/1/date
echo "date=$(date -u +%Y\-%m\-%d\T%H\:%M\:%S\Z)" >> $GITHUB_OUTPUT
echo "date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> "$GITHUB_OUTPUT"

# Image metadata for https://artifacthub.io/ - This is optional but is highly recommended so we all can get a index of all the custom images
# The metadata by itself is not going to do anything, you choose if you want your image to be on ArtifactHub or not.
Expand All @@ -83,7 +85,7 @@ jobs:
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=sha
type=ref,event=pr
labels: |
io.artifacthub.package.readme-url=https://raw.githubusercontent.com/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}/${{ github.sha }}/README.md
Expand Down Expand Up @@ -117,6 +119,13 @@ jobs:
labels: ${{ steps.metadata.outputs.labels }}
oci: false

- name: Smoke test as an ordinary user with a read-only image
run: |
podman run --rm --read-only --user 1000:1000 \
--tmpfs /tmp:rw,mode=1777 --env HOME=/tmp/home \
--volume "$PWD/build_files/smoke-test.sh:/smoke-test.sh:ro" \
--entrypoint /bin/bash "${IMAGE_NAME}:${DEFAULT_TAG}" /smoke-test.sh

# Rechunk is a script that we use on Universal Blue to make sure there isnt a single huge layer when your image gets published.
# This does not make your image faster to download, just provides better resumability and fixes a few errors.
# Documentation for Rechunk is provided on their github repository at https://github.com/hhd-dev/rechunk
Expand Down Expand Up @@ -179,10 +188,9 @@ jobs:
if: github.event_name != 'pull_request' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
run: |
IMAGE_FULL="${{ env.IMAGE_REGISTRY }}/${{ env.IMAGE_NAME }}"
for tag in ${{ steps.metadata.outputs.tags }}; do
cosign sign -y --key env://COSIGN_PRIVATE_KEY $IMAGE_FULL:$tag
done
cosign sign -y --key env://COSIGN_PRIVATE_KEY "$IMAGE_FULL@$IMAGE_DIGEST"
cosign verify --key cosign.pub "$IMAGE_FULL@$IMAGE_DIGEST"
env:
TAGS: ${{ steps.push.outputs.digest }}
IMAGE_DIGEST: ${{ steps.push.outputs.digest }}
COSIGN_EXPERIMENTAL: false
COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}
43 changes: 43 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Validate source
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
check:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- run: |
bash -n build_files/build.sh
shellcheck build_files/*.sh scripts/*.sh
python3 -m unittest discover -s tests -v
python3 - <<'PY'
import pathlib, tomllib
for path in pathlib.Path('disk_config').glob('*.toml'):
tomllib.loads(path.read_text())
PY
signing-key:
# Fork PRs cannot access repository secrets. Same-repository PRs validate
# that the shipped trust key matches the key used by the publishing job.
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2
with:
cosign-release: 'v2.6.1'
- name: Check publishing key matches the committed public key
env:
COSIGN_PRIVATE_KEY: ${{ secrets.SIGNING_SECRET }}
run: |
cosign public-key --key env://COSIGN_PRIVATE_KEY > /tmp/signing-key.pub
diff -u cosign.pub /tmp/signing-key.pub
native-sdk:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- name: Build and link native SDK dependencies
run: podman build -f Containerfile.devel -t localhost/tuxlinux-native-sdk:test .
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@ cosign.key
_build_*
output
_build-*/**

__pycache__/
*.pyc
1 change: 1 addition & 0 deletions Containerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Allow build scripts to be referenced without being copied into the final image
FROM scratch AS ctx
COPY build_files /
COPY cosign.pub /cosign.pub

# Base Image
FROM ghcr.io/ublue-os/bazzite-nvidia-open:stable
Expand Down
8 changes: 8 additions & 0 deletions Containerfile.builder
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ARG SOURCE_IMAGE
ARG BIB_IMAGE=quay.io/centos-bootc/bootc-image-builder:latest
FROM ${SOURCE_IMAGE} AS source-keys
# BIB's dependency solver resolves file:// key URLs in the builder filesystem.
# Dereference source-image symlinks; retain the builder's other distro keys.
RUN mkdir /tmp/tuxlinux-rpm-gpg && cp -L /etc/pki/rpm-gpg/* /tmp/tuxlinux-rpm-gpg/
FROM ${BIB_IMAGE}
COPY --from=source-keys /tmp/tuxlinux-rpm-gpg/ /etc/pki/rpm-gpg/
10 changes: 10 additions & 0 deletions Containerfile.devel
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# A coherent Fedora userspace for native development without replacing Bazzite's
# custom, epoch-bumped host graphics stack. Update this alongside Fedora rebases.
FROM registry.fedoraproject.org/fedora:44
RUN dnf5 install -y gcc gcc-c++ cmake ninja-build git pkgconf-pkg-config \
pipewire-devel mesa-libgbm-devel \
&& dnf5 clean all
# Link against the libraries supplied by the same package manager as the headers.
RUN printf '#include <pipewire/pipewire.h>\n#include <gbm.h>\nint main(void) { pw_init(0, 0); return gbm_create_device(-1) != 0; }\n' > /tmp/headers-smoke.c \
&& cc /tmp/headers-smoke.c $(pkg-config --cflags --libs libpipewire-0.3 gbm) -o /tmp/headers-smoke \
&& rm /tmp/headers-smoke.c /tmp/headers-smoke
31 changes: 7 additions & 24 deletions Justfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export image_name := env("IMAGE_NAME", "TuxLinux") # output image name, usually same as repo name, change as needed
export image_name := env("IMAGE_NAME", "tuxlinux") # output image name, usually same as repo name, change as needed
export default_tag := env("DEFAULT_TAG", "latest")
export bib_image := env("BIB_IMAGE", "quay.io/centos-bootc/bootc-image-builder:latest")

Expand Down Expand Up @@ -42,7 +42,7 @@ clean:
rm -f previous.manifest.json
rm -f changelog.md
rm -f output.env
rm -f output/
rm -rf -- output/

# Sudo Clean Repo
[group('Utility')]
Expand Down Expand Up @@ -141,7 +141,7 @@ _rootful_load_image $target_image=image_name $tag=default_tag:
if [[ "$ID" != "$USER_IMG_ID" ]]; then
# If the image ID is not found or different from user, copy the image from user podman to root podman
COPYTMP=$(mktemp -p "${PWD}" -d -t _build_podman_scp.XXXXXXXXXX)
just sudoif TMPDIR=${COPYTMP} podman image scp ${UID}@localhost::"${target_image}:${tag}" root@localhost::"${target_image}:${tag}"
just sudoif env TMPDIR="${COPYTMP}" podman image scp ${UID}@localhost::"${target_image}:${tag}" root@localhost::"${target_image}:${tag}"
rm -rf "${COPYTMP}"
fi
else
Expand All @@ -162,25 +162,8 @@ _build-bib $target_image $tag $type $config: (_rootful_load_image target_image t
#!/usr/bin/env bash
set -euo pipefail

args="--type ${type} "
args+="--use-librepo=True "
args+="--rootfs=btrfs"

BUILDTMP=$(mktemp -p "${PWD}" -d -t _build-bib.XXXXXXXXXX)

sudo podman run \
--rm \
-it \
--privileged \
--pull=newer \
--net=host \
--security-opt label=type:unconfined_t \
-v $(pwd)/${config}:/config.toml:ro \
-v $BUILDTMP:/output \
-v /var/lib/containers/storage:/var/lib/containers/storage \
"${bib_image}" \
${args} \
"${target_image}:${tag}"
sudo bash scripts/build-disk.sh "${target_image}:${tag}" "$type" "$config" "$BUILDTMP" "$bib_image"

mkdir -p output
sudo mv -f $BUILDTMP/* output/
Expand All @@ -207,7 +190,7 @@ build-raw $target_image=("localhost/" + image_name) $tag=default_tag: && (_build

# Build an ISO virtual machine image
[group('Build Virtal Machine Image')]
build-iso $target_image=("localhost/" + image_name) $tag=default_tag: && (_build-bib target_image tag "iso" "disk_config/iso.toml")
build-iso $target_image=("localhost/" + image_name) $tag=default_tag: && (_build-bib target_image tag "anaconda-iso" "disk_config/iso-kde.toml")

# Rebuild a QCOW2 virtual machine image
[group('Build Virtal Machine Image')]
Expand All @@ -219,7 +202,7 @@ rebuild-raw $target_image=("localhost/" + image_name) $tag=default_tag: && (_reb

# Rebuild an ISO virtual machine image
[group('Build Virtal Machine Image')]
rebuild-iso $target_image=("localhost/" + image_name) $tag=default_tag: && (_rebuild-bib target_image tag "iso" "disk_config/iso.toml")
rebuild-iso $target_image=("localhost/" + image_name) $tag=default_tag: && (_rebuild-bib target_image tag "anaconda-iso" "disk_config/iso-kde.toml")

# Run a virtual machine with the specified image type and configuration
_run-vm $target_image $tag $type $config:
Expand Down Expand Up @@ -273,7 +256,7 @@ run-vm-raw $target_image=("localhost/" + image_name) $tag=default_tag: && (_run-

# Run a virtual machine from an ISO
[group('Run Virtal Machine')]
run-vm-iso $target_image=("localhost/" + image_name) $tag=default_tag: && (_run-vm target_image tag "iso" "disk_config/iso.toml")
run-vm-iso $target_image=("localhost/" + image_name) $tag=default_tag: && (_run-vm target_image tag "iso" "disk_config/iso-kde.toml")

# Run a virtual machine using systemd-vmspawn
[group('Run Virtal Machine')]
Expand Down
Loading
Loading