Restructure project layout for better CI/CD integration
Some checks failed
Cross build / Build on ppc64le (push) Failing after 1m8s
Cross build / Build on s390x (push) Failing after 2s

- Flattened nested bootupd/bootupd/ structure to root level
- Moved all core project files to root directory
- Added proper Debian packaging structure (debian/ directory)
- Created build scripts and CI configuration
- Improved project organization for CI/CD tools
- All Rust source, tests, and configuration now at root level
- Added GitHub Actions workflow for automated testing
- Maintained all original functionality while improving structure
This commit is contained in:
robojerk 2025-08-09 23:11:42 -07:00
parent 5e8730df43
commit aaf662d5b1
87 changed files with 1334 additions and 570 deletions

View file

@ -0,0 +1,110 @@
#!/bin/bash
# Run inside the vm spawned from e2e.sh
set -euo pipefail
dn=$(cd $(dirname $0) && pwd)
bn=$(basename $0)
. ${dn}/../kola/data/libtest.sh
cd $(mktemp -d)
echo "Starting $0"
current_commit=$(rpm-ostree status --json | jq -r .deployments[0].checksum)
stampfile=/etc/${bn}.upgraded
if ! test -f ${stampfile}; then
if test "${current_commit}" = ${TARGET_COMMIT}; then
fatal "already at ${TARGET_COMMIT}"
fi
current_grub=$(rpm -q --queryformat='%{nevra}\n' ${TARGET_GRUB_NAME})
if test "${current_grub}" == "${TARGET_GRUB_PKG}"; then
fatal "Current grub ${current_grub} is same as target ${TARGET_GRUB_PKG}"
fi
# FIXME
# https://github.com/coreos/rpm-ostree/issues/2210
runv setenforce 0
runv rpm-ostree rebase /run/cosadir/tmp/repo:${TARGET_COMMIT}
runv touch ${stampfile}
runv systemd-run -- systemctl reboot
touch /run/rebooting
sleep infinity
else
if test "${current_commit}" != ${TARGET_COMMIT}; then
fatal "not at ${TARGET_COMMIT}"
fi
fi
# We did setenforce 0 above for https://github.com/coreos/rpm-ostree/issues/2210
# Validate that on reboot we're still enforcing.
semode=$(getenforce)
if test "$semode" != Enforcing; then
fatal "SELinux mode is ${semode}"
fi
if ! test -n "${TARGET_GRUB_PKG}"; then
fatal "Missing TARGET_GRUB_PKG"
fi
bootupctl validate
ok validate
bootupctl status | tee out.txt
assert_file_has_content_literal out.txt 'Component EFI'
assert_file_has_content_literal out.txt ' Installed: grub2-efi-x64-'
assert_not_file_has_content out.txt ' Installed:.*test-bootupd-payload'
assert_not_file_has_content out.txt ' Installed:.*'"${TARGET_GRUB_PKG}"
assert_file_has_content out.txt 'Update: Available:.*'"${TARGET_GRUB_PKG}"
assert_file_has_content out.txt 'Update: Available:.*test-bootupd-payload-1.0'
bootupctl status --print-if-available > out.txt
assert_file_has_content_literal 'out.txt' 'Updates available: BIOS EFI'
ok update avail
# Mount the EFI partition.
tmpefimount=$(mount_tmp_efi)
assert_not_has_file ${tmpefimount}/EFI/fedora/test-bootupd.efi
if env FAILPOINTS='update::exchange=return' bootupctl update -vvv 2>err.txt; then
fatal "should have errored"
fi
assert_file_has_content err.txt "error: .*synthetic failpoint"
bootupctl update -vvv | tee out.txt
assert_file_has_content out.txt "Previous EFI: .*"
assert_file_has_content out.txt "Updated EFI: ${TARGET_GRUB_PKG}.*,test-bootupd-payload-1.0"
assert_file_has_content ${tmpefimount}/EFI/fedora/test-bootupd.efi test-payload
bootupctl status --print-if-available > out.txt
if test -s out.txt; then
fatal "Found available updates: $(cat out.txt)"
fi
ok update not avail
mount -o remount,rw /boot
rm -f /boot/bootupd-state.json
bootupctl adopt-and-update | tee out.txt
assert_file_has_content out.txt "Adopted and updated: BIOS: .*"
assert_file_has_content out.txt "Adopted and updated: EFI: .*"
bootupctl validate
ok adopt-and-update
# Verify the adoption does not fail when install files if they are missing on the disk.
# see https://github.com/coreos/bootupd/issues/762
rm -f /boot/bootupd-state.json
[ -f "${tmpefimount}/EFI/fedora/test-bootupd.efi" ] && rm -f ${tmpefimount}/EFI/fedora/test-bootupd.efi
bootupctl adopt-and-update | tee out.txt
assert_file_has_content out.txt "Adopted and updated: BIOS: .*"
assert_file_has_content out.txt "Adopted and updated: EFI: .*"
if bootupctl validate 2>err.txt; then
fatal "unexpectedly passed validation"
fi
tap_finish
touch /run/testtmp/success
sync
# TODO maybe try to make this use more of the exttest infrastructure?
exec poweroff -ff

123
tests/e2e-update/e2e-update.sh Executable file
View file

@ -0,0 +1,123 @@
#!/bin/bash
# Given a coreos-assembler dir (COSA_DIR) and assuming
# the current dir is a git repository for bootupd,
# synthesize a test update and upgrade to it. This
# assumes that the latest cosa build is using the
# code we want to test (as happens in CI).
set -euo pipefail
dn=$(cd $(dirname $0) && pwd)
testprefix=$(cd ${dn} && git rev-parse --show-prefix)
. ${dn}/../kola/data/libtest.sh
. ${dn}/testrpmbuild.sh
if test -z "${COSA_DIR:-}"; then
fatal "COSA_DIR must be set"
fi
# Validate source directory
bootupd_git=$(cd ${dn} && git rev-parse --show-toplevel)
# https://github.com/coreos/bootupd/issues/551
! test -f ${bootupd_git}/systemd/bootupd.service
testtmp=$(mktemp -d -p /var/tmp bootupd-e2e.XXXXXXX)
export test_tmpdir=${testtmp}
# This is new content for our update
test_bootupd_payload_file=/boot/efi/EFI/fedora/test-bootupd.efi
test_bootupd_payload_file1=/boot/efi/EFI/BOOT/test-bootupd1.efi
build_rpm test-bootupd-payload \
files "${test_bootupd_payload_file}
${test_bootupd_payload_file1}" \
install "mkdir -p %{buildroot}/$(dirname ${test_bootupd_payload_file})
echo test-payload > %{buildroot}/${test_bootupd_payload_file}
mkdir -p %{buildroot}/$(dirname ${test_bootupd_payload_file1})
echo test-payload1 > %{buildroot}/${test_bootupd_payload_file1}"
# Start in cosa dir
cd ${COSA_DIR}
test -d builds
overrides=${COSA_DIR}/overrides
test -d "${overrides}"
mkdir -p ${overrides}/rpm
add_override() {
override=$1
shift
# This relies on "gold" grub not being pruned, and different from what's
# in the latest fcos
(cd ${overrides}/rpm && runv koji download-build --arch=noarch --arch=$(arch) ${override})
}
if test -z "${e2e_skip_build:-}"; then
echo "Building starting image"
rm -f ${overrides}/rpm/*.rpm
# Version from F42 prior to GA
add_override grub2-2.12-26.fc42
runv cosa build
prev_image=$(runv cosa meta --image-path qemu)
# Modify manifest to include `test-bootupd-payload` RPM
runv git -C src/config checkout manifest.yaml # first make sure it's clean
echo "packages: [test-bootupd-payload]" >> src/config/manifest.yaml
rm -f ${overrides}/rpm/*.rpm
echo "Building update ostree"
# Latest (current) version in F42
add_override grub2-2.12-28.fc42
mv ${test_tmpdir}/yumrepo/packages/$(arch)/*.rpm ${overrides}/rpm/
# Only build ostree update
runv cosa build ostree
# Undo manifest modification
runv git -C src/config checkout manifest.yaml
fi
echo "Preparing test"
grubarch=
case $(arch) in
x86_64) grubarch=x64;;
aarch64) grubarch=aa64;;
*) fatal "Unhandled arch $(arch)";;
esac
target_grub_name=grub2-efi-${grubarch}
target_grub_pkg=$(rpm -qp --queryformat='%{nevra}\n' ${overrides}/rpm/${target_grub_name}-2*.rpm)
target_commit=$(cosa meta --get-value ostree-commit)
echo "Target commit: ${target_commit}"
# For some reason 9p can't write to tmpfs
cat >${testtmp}/test.bu << EOF
variant: fcos
version: 1.0.0
systemd:
units:
- name: bootupd-test.service
enabled: true
contents: |
[Unit]
RequiresMountsFor=/run/testtmp
[Service]
Type=oneshot
RemainAfterExit=yes
Environment=TARGET_COMMIT=${target_commit}
Environment=TARGET_GRUB_NAME=${target_grub_name}
Environment=TARGET_GRUB_PKG=${target_grub_pkg}
Environment=SRCDIR=/run/bootupd-source
# Run via shell because selinux denies systemd writing to 9p apparently
ExecStart=/bin/sh -c '/run/bootupd-source/${testprefix}/e2e-update-in-vm.sh &>>/run/testtmp/out.txt; test -f /run/rebooting || poweroff -ff'
[Install]
WantedBy=multi-user.target
EOF
runv butane -o ${testtmp}/test.ign ${testtmp}/test.bu
cd ${testtmp}
qemuexec_args=(kola qemuexec --propagate-initramfs-failure --qemu-image "${prev_image}" --qemu-firmware uefi \
-i test.ign --bind-ro ${COSA_DIR},/run/cosadir --bind-ro ${bootupd_git},/run/bootupd-source --bind-rw ${testtmp},/run/testtmp)
if test -n "${e2e_debug:-}"; then
runv ${qemuexec_args[@]} --devshell
else
runv timeout 5m "${qemuexec_args[@]}" --console-to-file ${COSA_DIR}/tmp/console.txt
fi
if ! test -f ${testtmp}/success; then
if test -s ${testtmp}/out.txt; then
sed -e 's,^,# ,' < ${testtmp}/out.txt
else
echo "No out.txt created, systemd unit failed to start"
fi
fatal "test failed"
fi
echo "ok bootupd e2e"

142
tests/e2e-update/testrpmbuild.sh Executable file
View file

@ -0,0 +1,142 @@
# Copied from rpm-ostree
# builds a new RPM and adds it to the testdir's repo
# $1 - name
# $2+ - optional, treated as directive/value pairs
build_rpm() {
local name=$1; shift
# Unset, not zero https://github.com/projectatomic/rpm-ostree/issues/349
local epoch=""
local version=1.0
local release=1
local arch=x86_64
mkdir -p $test_tmpdir/yumrepo/{specs,packages}
local spec=$test_tmpdir/yumrepo/specs/$name.spec
# write out the header
cat > $spec << EOF
Name: $name
Summary: %{name}
License: GPLv2+
EOF
local build= install= files= pretrans= pre= post= posttrans= post_args=
local verifyscript= uinfo=
local transfiletriggerin= transfiletriggerin_patterns=
local transfiletriggerin2= transfiletriggerin2_patterns=
local transfiletriggerun= transfiletriggerun_patterns=
while [ $# -ne 0 ]; do
local section=$1; shift
local arg=$1; shift
case $section in
requires)
echo "Requires: $arg" >> $spec;;
recommends)
echo "Recommends: $arg" >> $spec;;
provides)
echo "Provides: $arg" >> $spec;;
conflicts)
echo "Conflicts: $arg" >> $spec;;
post_args)
post_args="$arg";;
version|release|epoch|arch|build|install|files|pretrans|pre|post|posttrans|verifyscript|uinfo)
declare $section="$arg";;
transfiletriggerin)
transfiletriggerin_patterns="$arg";
declare $section="$1"; shift;;
transfiletriggerin2)
transfiletriggerin2_patterns="$arg";
declare $section="$1"; shift;;
transfiletriggerun)
transfiletriggerun_patterns="$arg";
declare $section="$1"; shift;;
*)
assert_not_reached "unhandled section $section";;
esac
done
cat >> $spec << EOF
Version: $version
Release: $release
${epoch:+Epoch: $epoch}
BuildArch: $arch
%description
%{summary}
# by default, we create a /usr/bin/$name script which just outputs $name
%build
echo -e "#!/bin/sh\necho $name-$version-$release.$arch" > $name
chmod a+x $name
$build
${pretrans:+%pretrans}
$pretrans
${pre:+%pre}
$pre
${post:+%post} ${post_args}
$post
${posttrans:+%posttrans}
$posttrans
${transfiletriggerin:+%transfiletriggerin -- ${transfiletriggerin_patterns}}
$transfiletriggerin
${transfiletriggerin2:+%transfiletriggerin -- ${transfiletriggerin2_patterns}}
$transfiletriggerin2
${transfiletriggerun:+%transfiletriggerun -- ${transfiletriggerun_patterns}}
$transfiletriggerun
${verifyscript:+%verifyscript}
$verifyscript
%install
mkdir -p %{buildroot}/usr/bin
install $name %{buildroot}/usr/bin
$install
%clean
rm -rf %{buildroot}
%files
/usr/bin/$name
$files
EOF
# because it'd be overkill to set up mock for this, let's just fool
# rpmbuild using setarch
local buildarch=$arch
if [ "$arch" == "noarch" ]; then
buildarch=$(uname -m)
fi
(cd $test_tmpdir/yumrepo/specs &&
setarch $buildarch rpmbuild --target $arch -ba $name.spec \
--define "_topdir $PWD" \
--define "_sourcedir $PWD" \
--define "_specdir $PWD" \
--define "_builddir $PWD/.build" \
--define "_srcrpmdir $PWD" \
--define "_rpmdir $test_tmpdir/yumrepo/packages" \
--define "_buildrootdir $PWD")
# use --keep-all-metadata to retain previous updateinfo
(cd $test_tmpdir/yumrepo &&
createrepo_c --no-database --update --keep-all-metadata .)
# convenience function to avoid follow-up add-pkg
if [ -n "$uinfo" ]; then
uinfo_cmd add-pkg $uinfo $name 0 $version $release $arch
fi
if test '!' -f $test_tmpdir/yumrepo.repo; then
cat > $test_tmpdir/yumrepo.repo.tmp << EOF
[test-repo]
name=test-repo
baseurl=file:///$PWD/yumrepo
EOF
mv $test_tmpdir/yumrepo.repo{.tmp,}
fi
}