Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
e197ac0
Dev
DawidWesierski4 Jul 28, 2026
dad1418
Dev3
DawidWesierski4 Aug 10, 2026
b1e785b
Dev1
DawidWesierski4 Aug 10, 2026
c1b41cd
dev5
DawidWesierski4 Aug 10, 2026
f2e2eea
Dev6
DawidWesierski4 Aug 10, 2026
e8ee675
Dev7
DawidWesierski4 Aug 10, 2026
2389b29
test2
DawidWesierski4 Aug 10, 2026
5d97555
Ci: Harden dependency cache contracts
DawidWesierski4 Aug 10, 2026
18f95b8
Ci: Add production PR validation
DawidWesierski4 Aug 11, 2026
988d5f9
Ci: Harden production check diagnostics
DawidWesierski4 Aug 11, 2026
c50e34d
Ci: Bound production failure output
DawidWesierski4 Aug 11, 2026
6636d57
Ci: Report omitted failure lines
DawidWesierski4 Aug 11, 2026
f213ccf
Style: Apply CI production formatters
DawidWesierski4 Aug 11, 2026
4fbabaf
Ci: Mark shell entrypoints executable
DawidWesierski4 Aug 11, 2026
ab0038c
Ci: Fix manager XDP cross-compile
DawidWesierski4 Aug 11, 2026
466412f
Test: Run production CI tool regressions
DawidWesierski4 Aug 11, 2026
e2257aa
Fix: Preserve log fallback at annotation cap
DawidWesierski4 Aug 11, 2026
11401da
Style: Avoid late MCP test import
DawidWesierski4 Aug 11, 2026
b674812
CI: Build ICE on validation fleet
DawidWesierski4 Aug 11, 2026
f12916f
CI: Parse task contracts structurally
DawidWesierski4 Aug 11, 2026
727bd92
CI: Select dedicated ICE producer
DawidWesierski4 Aug 11, 2026
f6ef1e9
CI: Fix hardware test preparation
DawidWesierski4 Aug 11, 2026
8d78e72
Ci: Extend bare-metal build wait
DawidWesierski4 Aug 11, 2026
e9fa7fa
Fix: Exclude build queue from wait budget
DawidWesierski4 Aug 11, 2026
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
23 changes: 8 additions & 15 deletions .github/actions/build/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ runs:
using: composite
steps:
- uses: ./.github/actions/cleanup
- name: Install Task
uses: arduino/setup-task@b91d5d2c96a56797b48ac1e0e89220bf64044611 # v2.0.0
- name: Setup environment and build
shell: bash
env:
Expand All @@ -35,23 +37,14 @@ runs:
# Capture PHC is disciplined to TAI at runtime via phc2sys -O
# <live_offset>, so the kernel TAI offset is left untouched.
TOOLS_RUN_SET_TAI_OFFSET: '0'
run: |
bash .github/scripts/setup_environment.sh
if [ -n "${{ inputs.remote_host }}" ]; then
BRANCH="${{ inputs.remote_branch }}"
BRANCH="${BRANCH#refs/heads/}"
ENV_FILE="${{ inputs.remote_env_file }}"
ENV_FILE="${ENV_FILE/#\~/$HOME}"
{
[ -f "$ENV_FILE" ] && cat "$ENV_FILE" \
|| echo "::warning::No env file at $ENV_FILE — using defaults"
cat .github/scripts/remote_build.sh
} | ssh -o StrictHostKeyChecking=no "${{ inputs.remote_host }}" \
bash -s -- "${{ inputs.remote_mtl_path }}" "${BRANCH}"
fi
REMOTE_HOST: ${{ inputs.remote_host }}
REMOTE_MTL_PATH: ${{ inputs.remote_mtl_path }}
REMOTE_BRANCH: ${{ inputs.remote_branch }}
REMOTE_ENV_FILE: ${{ inputs.remote_env_file }}
run: task ci:build-action
- name: Upload build artifacts
if: ${{ always() && inputs.remote_host == '' }}
uses: actions/upload-artifact@v7
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: build-${{ github.sha }}
path: |
Expand Down
35 changes: 35 additions & 0 deletions .github/actions/check-ebpf/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Check eBPF/XDP prerequisites
description: >
Assert that the runner can build and run MTL's eBPF/XDP paths before the job
spends any time on it. Wraps script/build_ebpf_xdp.sh --check, so a local
`task ebpf:check` and a CI run execute the same code.

Place it as the first step of a job: a missing prerequisite fails here in
seconds instead of surfacing minutes later as an unrelated pkg-config error.

inputs:
mode:
description: What to verify -- build, runtime or all.
required: false
default: 'all'
strict:
description: Fail the job when a required prerequisite is missing.
required: false
default: 'true'
require_xdp:
description: >
Treat xdp-tools/libbpf as mandatory and demand the exact versions pinned
in versions.env. Enable on hosts provisioned for AF_XDP.
required: false
default: 'false'

runs:
using: composite
steps:
- name: 'ebpf: check prerequisites'
shell: bash
env:
MODE: ${{ inputs.mode }}
STRICT: ${{ inputs.strict }}
REQUIRE_XDP: ${{ inputs.require_xdp }}
run: bash "$GITHUB_ACTION_PATH/../../scripts/ci/check-ebpf-action.sh"
14 changes: 1 addition & 13 deletions .github/actions/cleanup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,4 @@ runs:
steps:
- name: Cleanup processes
shell: bash
run: |
echo "Killing any running DPDK or MTL related processes..."
sudo killall -SIGKILL gtest.sh || true
sudo killall -SIGKILL KahawaiTest || true
sudo killall -SIGKILL ffmpeg || true
sudo killall -SIGKILL RxTxApp || true
echo "Clenaup of the supporting processes..."
sudo killall -SIGINT pytest || true
sudo killall -SIGINT MtlManager || true
sudo killall -SIGINT phc2sys || true
sudo killall -SIGINT ptp4l || true
sudo killall -SIGINT netsniff-ng || true
sleep 2
run: bash "$GITHUB_ACTION_PATH/../../scripts/ci/cleanup.sh"
19 changes: 10 additions & 9 deletions .github/actions/source-checksums/action.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
name: Source Checksums
description: >
Compute deterministic SHA-256 hashes for each component group.
Waterfall: dpdk → mtl → {ffmpeg, gstreamer, plugins}.
A parent change forces all children to rehash automatically.
description: Compute deterministic SHA-256 hashes for CI dependency caches.

outputs:
dpdk:
Expand All @@ -11,6 +8,12 @@ outputs:
mtl:
description: 'Hash for MTL sources (includes DPDK hash)'
value: ${{ steps.compute.outputs.mtl }}
jpegxs:
description: 'Hash for JPEG XS bundle sources (includes MTL hash)'
value: ${{ steps.compute.outputs.jpegxs }}
ice:
description: 'Hash for patched ICE driver sources'
value: ${{ steps.compute.outputs.ice }}
ffmpeg:
description: 'Hash for FFmpeg plugin sources (includes MTL hash)'
value: ${{ steps.compute.outputs.ffmpeg }}
Expand All @@ -24,10 +27,8 @@ outputs:
runs:
using: composite
steps:
- name: Install Task
uses: arduino/setup-task@b91d5d2c96a56797b48ac1e0e89220bf64044611 # v2.0.0
- id: compute
shell: bash
run: |
set -euo pipefail
echo "::group::Source Checksums"
"${{ github.workspace }}/script/hash_sources.sh" -o "$GITHUB_OUTPUT"
echo "::endgroup::"
run: task ci:hash-dependencies -- -o "$GITHUB_OUTPUT"
174 changes: 73 additions & 101 deletions .github/actions/validate-host/action.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
name: Validate Host
description: >
Prepare a bare-metal test host: compute local source checksums,
restore build components from cache into .local_install/,
untar them, make binaries executable, and configure environment
so that subsequent steps can run MTL tests without system-wide installation.
Optionally sync .local_install/ to a shadow host via SSH.
description: Restore and validate cached dependencies, then idempotently align the host.

inputs:
shadow_host:
description: Path to a file defining IP and USER for the shadow host. If empty, shadow sync is skipped.
description: Path to a file defining IP and USER for the shadow host.
required: false
default: ''

Expand All @@ -23,143 +18,120 @@ outputs:
runs:
using: composite
steps:
- name: 'system: Check eBPF/XDP prerequisites'
uses: ./.github/actions/check-ebpf
with:
mode: all
strict: 'true'

- uses: ./.github/actions/cleanup

- name: Compute local source checksums
id: local-checksums
uses: ./.github/actions/source-checksums

- name: Compute exact cache keys
id: keys
shell: bash
env:
HASH_DPDK: ${{ steps.local-checksums.outputs.dpdk }}
HASH_MTL: ${{ steps.local-checksums.outputs.mtl }}
HASH_JPEGXS: ${{ steps.local-checksums.outputs.jpegxs }}
HASH_ICE: ${{ steps.local-checksums.outputs.ice }}
HASH_FFMPEG: ${{ steps.local-checksums.outputs.ffmpeg }}
HASH_GSTREAMER: ${{ steps.local-checksums.outputs.gstreamer }}
HASH_PLUGINS: ${{ steps.local-checksums.outputs.plugins }}
run: task ci:cache-keys

- name: 'cache: Restore DPDK'
uses: actions/cache/restore@v4
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
key: stash-dpdk-${{ steps.local-checksums.outputs.dpdk }}
key: ${{ steps.keys.outputs.dpdk_key }}
path: .local_install/dpdk
fail-on-cache-miss: true

- name: 'cache: Restore MTL'
uses: actions/cache/restore@v4
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
key: stash-mtl-${{ steps.local-checksums.outputs.mtl }}
key: ${{ steps.keys.outputs.mtl_key }}
path: .local_install/mtl
fail-on-cache-miss: true

- name: 'cache: Restore JPEG XS'
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
key: ${{ steps.keys.outputs.jpegxs_key }}
path: .local_install/jpegxs
fail-on-cache-miss: true

- name: 'cache: Restore FFmpeg'
uses: actions/cache/restore@v4
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
key: stash-ffmpeg-${{ steps.local-checksums.outputs.ffmpeg }}
key: ${{ steps.keys.outputs.ffmpeg_key }}
path: .local_install/ffmpeg
fail-on-cache-miss: true

- name: 'cache: Restore GStreamer'
uses: actions/cache/restore@v4
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
key: stash-gstreamer-${{ steps.local-checksums.outputs.gstreamer }}
key: ${{ steps.keys.outputs.gstreamer_key }}
path: .local_install/gstreamer
fail-on-cache-miss: true

- name: 'cache: Restore plugins'
uses: actions/cache/restore@v4
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
key: stash-plugins-${{ steps.local-checksums.outputs.plugins }}
key: ${{ steps.keys.outputs.plugins_key }}
path: .local_install/plugins
# Non-fatal: a missing/failed st22 plugin build only disables the codec
# tests (they skip via require_encoder); it must not abort validation.
fail-on-cache-miss: false
fail-on-cache-miss: true

- name: Make artifacts executable
shell: bash
run: |
find .local_install -type f \( -name '*.so*' -o -path '*/bin/*' \) -exec chmod +x {} + 2>/dev/null || true
- name: 'cache: Restore ICE'
uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
with:
key: ${{ steps.keys.outputs.ice_key }}
path: .local_install/ice
fail-on-cache-miss: true

- name: 'kahawai: Generate CI plugin registry from cache'
shell: bash
run: |
# Build a CI-owned kahawai.json that points at the cached st22 avcodec
# plugin under .local_install/plugins -- no system install. MTL loads it
# via KAHAWAI_CFG_PATH (exported below). The plugin .so itself is built
# by the build workflow and restored from the `plugins` cache above.
# The template reproduces the runner plugin set: jpegxs/sample stay at
# their /usr/local install paths (a missing .so is a non-fatal dlopen
# warning), only avcodec is sourced from the cache.
set -euo pipefail
WS="${{ github.workspace }}"
template="${WS}/.github/workflows/kahawai_template.json"
cfg="${RUNNER_TEMP:-/tmp}/kahawai_ci.json"
plugin_dir="$(find "${WS}/.local_install/plugins" -name 'libst_plugin_st22_avcodec.so' -printf '%h\n' -quit 2>/dev/null || true)"
if [ -z "${plugin_dir}" ]; then
echo "::warning::st22 avcodec plugin not found in .local_install/plugins; H264 st22p tests will skip"
plugin_dir="${WS}/.local_install/plugins/lib/x86_64-linux-gnu"
fi
cp -f "${template}" "${cfg}"
sed -i "s+REPLACE_BY_CICD_PLUGIN_DIR+${plugin_dir}+g" "${cfg}"
echo "KAHAWAI_CFG_PATH=${cfg}" >> "$GITHUB_ENV"
echo "::notice::CI kahawai registry ${cfg} (avcodec from ${plugin_dir})"

- name: 'installation: Auto-align host components (ICE driver & SVT-JPEG-XS)'
- name: Validate restored dependencies
shell: bash
env:
MTL_INSTALL_PREFIX: ${{ github.workspace }}/.local_install/mtl
PKG_CONFIG_PATH: ${{ github.workspace }}/.local_install/dpdk/lib/x86_64-linux-gnu/pkgconfig:${{ github.workspace }}/.local_install/mtl/lib/x86_64-linux-gnu/pkgconfig
LD_LIBRARY_PATH: ${{ github.workspace }}/.local_install/dpdk/lib/x86_64-linux-gnu:${{ github.workspace }}/.local_install/mtl/lib/x86_64-linux-gnu
run: |
export SETUP_BUILD_AND_INSTALL_ICE_DRIVER=1
export PLUGIN_BUILD_AND_INSTALL_JPEGXS=1
bash ${{ github.workspace }}/.github/scripts/setup_environment.sh

- name: Configure LD_LIBRARY_PATH, PATH, GST_PLUGIN_PATH
shell: bash
run: |
WS="${{ github.workspace }}"
LI="${WS}/.local_install"

# Shared libraries: DPDK + MTL + FFmpeg
echo "LD_LIBRARY_PATH=${LI}/dpdk/lib/x86_64-linux-gnu:${LI}/mtl/lib/x86_64-linux-gnu:${LI}/ffmpeg/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" >> "$GITHUB_ENV"
ICE_REQUIRE_SECURE_BOOT_PROBE: '1'
run: task ci:validate-dependencies

# Binaries on PATH
echo "${LI}/mtl/bin" >> "$GITHUB_PATH"
echo "${LI}/ffmpeg/bin" >> "$GITHUB_PATH"
echo "${LI}/dpdk/bin" >> "$GITHUB_PATH"
- name: Make cached artifacts executable
shell: bash
run: task ci:configure-host -- make-executable

# GStreamer plugins
echo "GST_PLUGIN_PATH=${LI}/gstreamer/gstreamer-1.0${GST_PLUGIN_PATH:+:$GST_PLUGIN_PATH}" >> "$GITHUB_ENV"
- name: Generate CI plugin registry
shell: bash
run: task ci:configure-host -- registry

# pkg-config for downstream tools
echo "PKG_CONFIG_PATH=${LI}/dpdk/lib/x86_64-linux-gnu/pkgconfig:${LI}/mtl/lib/x86_64-linux-gnu/pkgconfig" >> "$GITHUB_ENV"
- name: Preserve Task path for privileged activation
shell: bash
run: echo "TASK_BIN=$(command -v task)" >> "$GITHUB_ENV"

# Refresh linker cache (best-effort)
sudo ldconfig 2>/dev/null || true
- name: Activate ICE if required
shell: bash
env:
ICE_REQUIRE_SECURE_BOOT_PROBE: '1'
run: sudo -E "$TASK_BIN" ci:activate-ice

echo "::notice::Host environment configured for .local_install/{dpdk,mtl,ffmpeg,gstreamer,plugins}"
- name: Configure dependency environment
shell: bash
run: task ci:configure-host -- environment

- name: Read shadow host credentials
id: shadow-creds
if: inputs.shadow_host != ''
shell: bash
run: |
source "${{ inputs.shadow_host }}"
echo "ip=${IP}" >> "$GITHUB_OUTPUT"
echo "user=${USER}" >> "$GITHUB_OUTPUT"
env:
SHADOW_HOST_FILE: ${{ inputs.shadow_host }}
run: task ci:configure-host -- shadow-credentials

- name: Sync .local_install to shadow host
- name: Sync caches to shadow host
if: steps.shadow-creds.outputs.ip != ''
shell: bash
run: |
IP="${{ steps.shadow-creds.outputs.ip }}"
USER="${{ steps.shadow-creds.outputs.user }}"
SSH_OPTS=(-o StrictHostKeyChecking=accept-new -o BatchMode=yes -o ConnectTimeout=30)
echo "::group::Syncing .local_install/ to ${USER}@${IP}"
ssh "${SSH_OPTS[@]}" "${USER}@${IP}" "mkdir -p ${{ github.workspace }}/.local_install ${{ github.workspace }}/script ${{ github.workspace }}/tests"
rsync -az --delete \
-e "ssh ${SSH_OPTS[*]}" \
"${{ github.workspace }}/.local_install/" \
"${USER}@${IP}:${{ github.workspace }}/.local_install/"
rsync -az --delete \
-e "ssh ${SSH_OPTS[*]}" \
"${{ github.workspace }}/script/" \
"${USER}@${IP}:${{ github.workspace }}/script/"
rsync -az --delete \
-e "ssh ${SSH_OPTS[*]}" \
"${{ github.workspace }}/tests/" \
"${USER}@${IP}:${{ github.workspace }}/tests/"
echo "::endgroup::"
echo "::notice::Synced .local_install/, script/, and tests/ to shadow host ${IP}"
env:
SHADOW_HOST_IP: ${{ steps.shadow-creds.outputs.ip }}
SHADOW_HOST_USER: ${{ steps.shadow-creds.outputs.user }}
run: task ci:configure-host -- shadow-sync
Loading
Loading