Skip to content

Build LKL (nightly)

Build LKL (nightly) #6

Workflow file for this run

# Build prebuilt liblkl.a and publish to lkl-nightly release.
#
# Schedule: nightly at 00:30 UTC (08:30 TST) so results land by start
# of Taiwan workday during GitHub Actions off-peak (US evening).
# Skips build if upstream LKL HEAD has not changed since the last
# successful publish.
#
# The lkl-nightly release on sysprog21/kbox always contains exactly
# one x86_64 and one aarch64 tarball (the latest build).
name: Build LKL (nightly)
on:
schedule:
- cron: '30 0 * * *'
workflow_dispatch:
inputs:
force:
description: 'Force rebuild even if upstream is unchanged'
type: boolean
default: false
concurrency:
group: lkl-nightly
cancel-in-progress: false
env:
LKL_UPSTREAM: lkl/linux
KBOX_REPO: ${{ github.repository }}
NIGHTLY_TAG: lkl-nightly
jobs:
# ---- Check whether upstream LKL has new commits ----
check-upstream:
runs-on: ubuntu-24.04
permissions:
contents: read
outputs:
lkl_commit: ${{ steps.head.outputs.commit }}
needs_build: ${{ steps.compare.outputs.needs_build }}
steps:
- name: Get upstream LKL HEAD
id: head
run: |
COMMIT=$(git ls-remote "https://github.com/${{ env.LKL_UPSTREAM }}.git" HEAD | awk '{print $1}')
if [ -z "$COMMIT" ]; then
echo "::error::Failed to resolve upstream LKL HEAD"
exit 1
fi
echo "commit=${COMMIT}" >> "$GITHUB_OUTPUT"
echo "Upstream LKL HEAD: ${COMMIT}"
- name: Compare with last published build
id: compare
env:
GH_TOKEN: ${{ github.token }}
run: |
if [ "${{ inputs.force }}" = "true" ]; then
echo "needs_build=true" >> "$GITHUB_OUTPUT"
echo "Forced rebuild requested."
exit 0
fi
# Fetch BUILD_INFO from existing nightly release.
LAST_COMMIT=$(gh release view "${{ env.NIGHTLY_TAG }}" \
--repo "${{ env.KBOX_REPO }}" \
--json body --jq '.body' 2>/dev/null \
| grep -oP 'commit=\K[0-9a-f]+' | head -1) || LAST_COMMIT=""
CURRENT="${{ steps.head.outputs.commit }}"
if [ "$LAST_COMMIT" = "$CURRENT" ]; then
echo "needs_build=false" >> "$GITHUB_OUTPUT"
echo "Upstream unchanged (${CURRENT}). Skipping build."
else
echo "needs_build=true" >> "$GITHUB_OUTPUT"
echo "New upstream commit: ${CURRENT} (was: ${LAST_COMMIT:-none})"
fi
# ---- Build x86_64 and aarch64 in parallel ----
build:
needs: check-upstream
if: needs.check-upstream.outputs.needs_build == 'true'
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include:
- arch: x86_64
runner: ubuntu-24.04
- arch: aarch64
runner: ubuntu-24.04-arm
runs-on: ${{ matrix.runner }}
timeout-minutes: 30
steps:
- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential flex bison bc libelf-dev
- name: Shallow-fetch LKL at pinned commit
run: |
git init lkl && cd lkl
git remote add origin "https://github.com/${{ env.LKL_UPSTREAM }}.git"
git fetch --depth=1 origin ${{ needs.check-upstream.outputs.lkl_commit }}
git checkout FETCH_HEAD
- name: Configure LKL
working-directory: lkl
run: |
make ARCH=lkl defconfig
./scripts/config --enable CONFIG_DEVTMPFS
./scripts/config --enable CONFIG_DEVTMPFS_MOUNT
./scripts/config --enable CONFIG_DEVPTS_FS
./scripts/config --enable CONFIG_DEBUG_INFO
./scripts/config --set-val CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT y
./scripts/config --enable CONFIG_GDB_SCRIPTS
./scripts/config --enable CONFIG_SCHED_DEBUG
./scripts/config --enable CONFIG_PROC_SYSCTL
./scripts/config --enable CONFIG_PRINTK
./scripts/config --enable CONFIG_TRACEPOINTS
./scripts/config --enable CONFIG_FTRACE
./scripts/config --enable CONFIG_DEBUG_FS
./scripts/config --disable CONFIG_MODULES
./scripts/config --disable CONFIG_SOUND
./scripts/config --disable CONFIG_USB_SUPPORT
./scripts/config --disable CONFIG_INPUT
./scripts/config --disable CONFIG_NFS_FS
./scripts/config --disable CONFIG_CIFS
make ARCH=lkl olddefconfig
- name: Build LKL kernel
working-directory: lkl
run: make ARCH=lkl -j$(nproc)
- name: Build liblkl.a
working-directory: lkl
run: make -C tools/lkl -j$(nproc)
- name: Verify symbols
working-directory: lkl
run: |
test -f tools/lkl/liblkl.a || { echo "liblkl.a not found"; exit 1; }
for sym in lkl_init lkl_start_kernel lkl_cleanup lkl_syscall \
lkl_strerror lkl_disk_add lkl_mount_dev \
lkl_host_ops lkl_dev_blk_ops; do
if ! nm tools/lkl/liblkl.a 2>/dev/null | awk -v s="$sym" \
'$3 == s && $2 ~ /^[TtDdBbRr]$/ {found=1} END {exit !found}'; then
echo "MISSING symbol: ${sym}"; exit 1
fi
done
- name: Package
working-directory: lkl
run: |
mkdir -p pkg
cp tools/lkl/liblkl.a pkg/
cp tools/lkl/include/lkl.h pkg/ 2>/dev/null || true
cp tools/lkl/include/lkl/autoconf.h pkg/ 2>/dev/null || true
cp scripts/gdb/vmlinux-gdb.py pkg/ 2>/dev/null || true
echo "commit=$(git rev-parse HEAD)" > pkg/BUILD_INFO
echo "date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> pkg/BUILD_INFO
echo "arch=${{ matrix.arch }}" >> pkg/BUILD_INFO
cd pkg && sha256sum ./* > sha256sums.txt
cd .. && tar czf liblkl-${{ matrix.arch }}.tar.gz -C pkg .
- name: Upload artifact
uses: actions/upload-artifact@v7
with:
name: lkl-${{ matrix.arch }}
path: lkl/liblkl-${{ matrix.arch }}.tar.gz
retention-days: 3
# ---- Publish: replace lkl-nightly release with latest artifacts ----
publish-nightly:
needs: [check-upstream, build]
if: needs.check-upstream.outputs.needs_build == 'true'
runs-on: ubuntu-24.04
permissions:
contents: write
steps:
- name: Download artifacts
uses: actions/download-artifact@v8
with:
path: dist/
merge-multiple: true
- name: Publish nightly release
env:
GH_TOKEN: ${{ github.token }}
run: |
LKL_COMMIT="${{ needs.check-upstream.outputs.lkl_commit }}"
BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
cat > /tmp/release-notes.md <<EOF
Nightly prebuilt liblkl.a for kbox.
commit=${LKL_COMMIT}
date=${BUILD_DATE}
upstream=https://github.com/${{ env.LKL_UPSTREAM }}/commit/${LKL_COMMIT}
Contains: liblkl-x86_64.tar.gz, liblkl-aarch64.tar.gz
Each tarball includes: liblkl.a, lkl.h, autoconf.h, vmlinux-gdb.py,
BUILD_INFO, sha256sums.txt
EOF
# Delete-then-create is atomic enough: both build jobs succeeded,
# and the concurrency group prevents overlapping runs.
gh release delete "${{ env.NIGHTLY_TAG }}" \
--repo "${{ env.KBOX_REPO }}" \
--yes --cleanup-tag 2>/dev/null || true
gh release create "${{ env.NIGHTLY_TAG }}" \
--repo "${{ env.KBOX_REPO }}" \
--title "LKL nightly (${BUILD_DATE})" \
--notes-file /tmp/release-notes.md \
--prerelease \
dist/liblkl-x86_64.tar.gz \
dist/liblkl-aarch64.tar.gz