mirror of
https://github.com/KDE/kde-linux.git
synced 2026-08-01 01:37:17 -04:00
Integrates OpenQA image testing into CI. Builds images once in the imaging job, then passes the resulting image and update channel to the OpenQA pipeline in kde-linux/os-autoinst-distri-kdelinux. For regular test builds, upload the built ISO and a temporary sysupdate tree to ci-artifacts on storage.kde.org. The resulting IMAGE_URL, STAGING_CHANNEL_URL and ephemeral update signing key are exported through the imaging job dotenv artifact so OpenQA can boot the image and run upgrade tests against the build under test. For protected default-branch builds, stage the release artifacts under a per-job staging prefix in the kde-linux bucket. OpenQA tests the staged ISO and sysupdate channel before the publish job is allowed to run. Publishing downloads the staged artifacts, uploads the public ISO/torrent and sysupdate assets to files.kde.org, chunks and uploads the root to the desync chunk store, then merges the staged S3 tree into the live tree on the bucket and regenerates the published SHA256SUMS.
229 lines
10 KiB
Bash
Executable File
229 lines
10 KiB
Bash
Executable File
#!/bin/bash
|
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
|
# SPDX-FileCopyrightText: 2023 Harald Sitter <sitter@kde.org>
|
|
# SPDX-FileCopyrightText: 2024 Bruno Pajdek <brupaj@proton.me>
|
|
# SPDX-FileCopyrightText: 2026 Hadi Chokr <hadichokr@icloud.com>
|
|
|
|
# Build image using mkosi, well, somewhat. mkosi is actually a bit too inflexible for our purposes so we generate a OS
|
|
# tree using mkosi and then construct shipable .iso9660 (and gpt raw disk images) for installation and tarballs (for systemd-sysupdate)
|
|
# ourselves.
|
|
|
|
set -ex
|
|
|
|
# Creates a sysext containing the KDE debug symbols, downloaded from the packages pipeline.
|
|
make_debug_archive () {
|
|
# Create an empty directory at /var/tmp/debugroot to extract the debug symbols into before compressing.
|
|
rm --recursive --force /var/tmp/debugroot
|
|
mkdir --parents /var/tmp/debugroot
|
|
|
|
# Download and extract debug symbols produced by the packages pipeline.
|
|
curl --fail https://storage.kde.org/kde-linux-packages/testing/artifacts/debug.tar.zst \
|
|
| zstd --decompress | tar --extract --directory=/var/tmp/debugroot
|
|
|
|
# systemd-sysext uses the os-release in extension-release.d to verify the sysext matches the base OS,
|
|
# and can therefore be safely installed. Copy the base OS' os-release there.
|
|
mkdir --parents /var/tmp/debugroot/usr/lib/extension-release.d/
|
|
cp "${OUTPUT}/usr/lib/os-release" /var/tmp/debugroot/usr/lib/extension-release.d/extension-release.debug
|
|
|
|
# Compress /var/tmp/debugroot/usr into a zstd tarball at $DEBUG_TAR.
|
|
# We only need usr because that's where all the relevant stuff lives.
|
|
tar --directory=/var/tmp/debugroot --create --file="$DEBUG_TAR" usr
|
|
zstd --threads=0 --rm "$DEBUG_TAR" # --threads=0 automatically uses the optimal number
|
|
rm --recursive --force /var/tmp/debugroot
|
|
}
|
|
|
|
EPOCH=$(date --utc +%s) # The epoch (only used to then construct the various date strings)
|
|
VERSION_DATE=$(date --utc --date="@$EPOCH" --rfc-3339=seconds)
|
|
VERSION=$(date --utc --date="@$EPOCH" +%Y%m%d%H%M)
|
|
OUTPUT="mkosi.output/kde-linux_$VERSION" # Built rootfs path (mkosi uses this directory by default)
|
|
|
|
# Canonicalize the path in $OUTPUT to avoid any possible path issues.
|
|
OUTPUT="$(readlink --canonicalize-missing "$OUTPUT")"
|
|
|
|
MAIN_UKI=${OUTPUT}.efi # Output main UKI path
|
|
LIVE_UKI=${OUTPUT}_live.efi # Output live UKI path
|
|
DEBUG_TAR=${OUTPUT}_debug-x86-64.tar # Output debug archive path (.zst will be added)
|
|
# SUPER WARNING: Do not use the more common foo.erofs.caibx suffix. It breaks stuff!
|
|
# https://github.com/systemd/systemd/issues/38605
|
|
# We'll rename things accordingly via sysupdate.d files.
|
|
ROOTFS_CAIBX=${OUTPUT}_root-x86-64.caibx
|
|
ROOTFS_EROFS=${OUTPUT}_root-x86-64.erofs # Output erofs image path
|
|
ISO="${OUTPUT}.iso" # both a valid GPT disk image and a bootable ISO
|
|
|
|
EFI_BASE=kde-linux_${VERSION} # Base name of the UKI in the image's ESP
|
|
EFI=${EFI_BASE}+3.efi # Name of primary UKI in the image's ESP (with tries counter for installed system)
|
|
LIVE_EFI=${EFI_BASE}.efi # Name of live UKI in the ESP (no tries counter — ESP is read-only on ISO)
|
|
|
|
# Clean up old build artifacts.
|
|
rm --recursive --force kde-linux.cache/*.raw kde-linux.cache/*.iso kde-linux.cache/*.mnt
|
|
|
|
cat /etc/pacman.conf.nolinux >> mkosi.sandbox/etc/pacman.conf
|
|
|
|
# Enable multilib; we need it later for steam-devices
|
|
cat <<EOF >> mkosi.sandbox/etc/pacman.conf
|
|
[multilib]
|
|
Include = /etc/pacman.d/mirrorlist
|
|
EOF
|
|
|
|
mkdir --parents mkosi.sandbox/etc/pacman.d
|
|
# Ensure the base image does not go out of sync with the Arch snapshot used to build packages.
|
|
# WARNING: code copy in bootstrap.sh
|
|
BUILD_REPO=$(curl --fail --silent https://storage.kde.org/kde-linux-packages/testing/repo/build_repo.txt)
|
|
if [ -z "$BUILD_REPO" ]; then
|
|
echo "ERROR: Could not fetch build_repo.txt — refusing to build out-of-sync image." >&2
|
|
exit 1
|
|
fi
|
|
echo "Server = ${BUILD_REPO}/\$repo/os/\$arch" > mkosi.sandbox/etc/pacman.d/mirrorlist
|
|
# ... and make sure our cache is up to date. Second --refresh forces a refresh.
|
|
pacman --sync --refresh --refresh --noconfirm
|
|
|
|
# Make sure permissions are sound
|
|
./permission-fix.sh
|
|
|
|
cargo build --release --manifest-path btrfs-migrator/Cargo.toml
|
|
cp -v btrfs-migrator/target/release/btrfs-migrator mkosi.extra/usr/lib/
|
|
|
|
rm --recursive --force kde-linux-sysupdated
|
|
git clone https://invent.kde.org/kde-linux/kde-linux-sysupdated
|
|
DESTDIR=$PWD/mkosi.extra make --directory=kde-linux-sysupdated install
|
|
|
|
rm --recursive --force etc-factory
|
|
git clone https://invent.kde.org/kde-linux/etc-factory
|
|
DESTDIR=$PWD/mkosi.extra make --directory=etc-factory install
|
|
|
|
# Extract the KDE packages pipeline output into mkosi.extra so kde-builder built files
|
|
# are baked directly into the image instead of going through the package repo.
|
|
curl --fail https://storage.kde.org/kde-linux-packages/testing/artifacts/install.tar.zst \
|
|
-o install.tar.zst
|
|
|
|
# Generate a mkosi dropin with the packages from the packages pipeline
|
|
curl --fail https://storage.kde.org/kde-linux-packages/testing/artifacts/packages.txt \
|
|
-o packages.txt
|
|
|
|
mkdir -p mkosi.conf.d
|
|
{
|
|
echo "[Content]"
|
|
while IFS= read -r pkg; do
|
|
echo "Packages=$pkg"
|
|
done < packages.txt
|
|
} > mkosi.conf.d/40-kde-packages.conf
|
|
|
|
mkosi \
|
|
--environment="CI_COMMIT_SHORT_SHA=${CI_COMMIT_SHORT_SHA:-unknownSHA}" \
|
|
--environment="CI_COMMIT_SHA=${CI_COMMIT_SHA:-unknownSHA}" \
|
|
--environment="CI_PIPELINE_URL=${CI_PIPELINE_URL:-https://invent.kde.org}" \
|
|
--environment="VERSION_DATE=${VERSION_DATE}" \
|
|
--image-version="$VERSION" \
|
|
--extra-tree="$PWD/install.tar.zst" --extra-tree="$PWD/mkosi.extra" \
|
|
"$@"
|
|
|
|
# Adjust mtime to reduce unnecessary churn between images caused by us rebuilding repos that have possibly not changed in source or binary interfaces.
|
|
if [ -f "$PWD/.secure_files/ssh.key" ]; then
|
|
# You can use `ssh-keyscan origin.files.kde.org` to get the host key
|
|
echo "origin.files.kde.org ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILUjdH4S7otYIdLUkOZK+owIiByjNQPzGi7GQ5HOWjO6" >> ~/.ssh/known_hosts
|
|
|
|
chmod 600 "$PWD/.secure_files/ssh.key"
|
|
|
|
scp -i "$PWD/.secure_files/ssh.key" kdeos@origin.files.kde.org:/home/kdeos/mtimer.json mtimer.json
|
|
# Note: use absolute paths. since we chdir via go
|
|
go -C ./mtimer/ run . -root "$OUTPUT" -json "$PWD/mtimer.json"
|
|
scp -i "$PWD/.secure_files/ssh.key" mtimer.json kdeos@origin.files.kde.org:/home/kdeos/mtimer.json
|
|
fi
|
|
|
|
# NOTE: /efi must be empty so auto mounting can happen. As such we put our templates in a different directory
|
|
rm -rfv "${OUTPUT}/efi"
|
|
[ -d "${OUTPUT}/efi" ] || mkdir --mode 0700 "${OUTPUT}/efi"
|
|
[ -d "${OUTPUT}/usr/share/factory/boot" ] || mkdir --mode 0700 "${OUTPUT}/usr/share/factory/boot"
|
|
[ -d "${OUTPUT}/usr/share/factory/boot/EFI" ] || mkdir --mode 0700 "${OUTPUT}/usr/share/factory/boot/EFI"
|
|
[ -d "${OUTPUT}/usr/share/factory/boot/EFI/Linux" ] || mkdir --mode 0700 "${OUTPUT}/usr/share/factory/boot/EFI/Linux"
|
|
[ -d "${OUTPUT}/usr/share/factory/boot/EFI/Linux/$EFI_BASE.efi.extra.d" ] || mkdir --mode 0700 "${OUTPUT}/usr/share/factory/boot/EFI/Linux/$EFI_BASE.efi.extra.d"
|
|
|
|
# Save the main UKI (with tries counter) aside as it must NOT go into factory/boot yet
|
|
# so it doesn't end up on the live ESP.
|
|
cp -v "${OUTPUT}"/kde-linux.efi "$MAIN_UKI"
|
|
rm -v "${OUTPUT}"/kde-linux.efi
|
|
mv -v "${OUTPUT}"/erofs.addon.efi "${OUTPUT}_erofs.addon.efi"
|
|
mv -v "${OUTPUT}"/live.efi "$LIVE_UKI"
|
|
|
|
make_debug_archive
|
|
|
|
# Now let's actually build the live ESP.
|
|
# We use kde-linux.cache instead of /tmp as usual because we'll probably run out of space there.
|
|
|
|
# Only LIVE_EFI (no tries counter) goes into factory/boot for the ESP.
|
|
# The installed system UKI ($EFI with +3) is added AFTER the ESP is built.
|
|
mv "$LIVE_UKI" "${OUTPUT}/usr/share/factory/boot/EFI/Linux/$LIVE_EFI"
|
|
|
|
# Change to kde-linux.cache since we'll be working there.
|
|
cd kde-linux.cache
|
|
|
|
# Create a 280M large FAT32 filesystem inside of esp.raw.
|
|
fallocate -l 280M esp.raw
|
|
mkfs.fat -F 32 esp.raw
|
|
|
|
# Mount it to esp.raw.mnt.
|
|
mkdir -p esp.raw.mnt
|
|
mount esp.raw esp.raw.mnt
|
|
|
|
# Copy everything from /usr/share/factory/boot into esp.raw.mnt.
|
|
# At this point only LIVE_EFI is in factory/boot/EFI/Linux/ so the installed UKI (+3) is not there yet.
|
|
cp --archive --recursive "${OUTPUT}/usr/share/factory/boot/." esp.raw.mnt
|
|
|
|
# We're done, unmount esp.raw.mnt.
|
|
umount esp.raw.mnt
|
|
|
|
cd .. # and back to root
|
|
|
|
# Now add the installed system UKI (with tries counter) to factory/boot for the erofs rootfs.
|
|
# This happens AFTER the ESP build so it doesn't land on the live ESP.
|
|
cp "$MAIN_UKI" "${OUTPUT}/usr/share/factory/boot/EFI/Linux/$EFI"
|
|
|
|
# Remove the live UKI from factory as it was only needed for the ESP build.
|
|
# The erofs rootfs should only contain the installed system UKI (+3).
|
|
rm "${OUTPUT}/usr/share/factory/boot/EFI/Linux/$LIVE_EFI"
|
|
|
|
# Drop flatpak data from erofs. They are in the usr/share/factory and deployed from there.
|
|
rm -rf "$OUTPUT/var/lib/flatpak"
|
|
mkdir "$OUTPUT/var/lib/flatpak" # but keep a mountpoint around for the live session
|
|
|
|
time mkfs.erofs -zzstd -C 65536 --chunksize 65536 "$ROOTFS_EROFS" "$OUTPUT" > erofs.log 2>&1
|
|
cp --reflink=auto "$ROOTFS_EROFS" kde-linux.cache/root.raw
|
|
|
|
# Now assemble the image using systemd-repart and the definitions in mkosi.repart into $ISO.
|
|
# The resulting file is both a valid GPT disk image and a bootable El Torito ISO.
|
|
touch "$ISO"
|
|
systemd-repart \
|
|
--no-pager \
|
|
--empty=allow \
|
|
--size=auto \
|
|
--dry-run=no \
|
|
--root=kde-linux.cache \
|
|
--definitions=mkosi.repart \
|
|
--el-torito=true \
|
|
--el-torito-volume="KDE LINUX $VERSION" \
|
|
--el-torito-publisher="KDE" \
|
|
"$ISO"
|
|
|
|
# Incase the owner is root
|
|
chown -R user:user mkosi.output
|
|
|
|
# Create a torrent for the image
|
|
./torrent-create.rb "$VERSION" "$OUTPUT" "$ISO"
|
|
|
|
go install -v github.com/folbricht/desync/cmd/desync@latest
|
|
~/go/bin/desync make --print-stats --chunk-size 1024:2048:4096 "$ROOTFS_CAIBX" "$ROOTFS_EROFS"
|
|
# Be very careful with this file. It is here for backwards compat. It must not appear in SHA256SUMS.
|
|
# https://github.com/systemd/systemd/issues/38605
|
|
cp "$ROOTFS_CAIBX" "$ROOTFS_EROFS.caibx"
|
|
|
|
# Fake artifacts to keep older systems happy to upgrade to newer versions.
|
|
# Can be removed once we have started having revisions in our update trees.
|
|
tar -cf ${OUTPUT}_root-x86-64.tar -T /dev/null
|
|
zstd --threads=0 --rm ${OUTPUT}_root-x86-64.tar
|
|
|
|
# TODO before accepting new uploads perform sanity checks on the artifacts (e.g. the tar being well formed)
|
|
|
|
# efi images and torrents are 700, make them readable so the server can serve them
|
|
chmod go+r "$OUTPUT".* ./mkosi.output/*.efi ./mkosi.output/*.torrent
|
|
ls -lah
|