prplos/.gitlab/testbed.yml
Petr Štetiar 26895230f7 ci: cram: add component split jobs behind CRAM_COMPONENTS
The hardware cram jobs currently run each board's complete suite. Every
automatic pipeline therefore consumes coverage that can be selected more
cheaply by component.

Add a runtime component template so test collection happens in cram's
checkout and environment. Replace each legacy board job with four static
full, prplmesh, lcm, and prplos jobs selected through the
comma-separated CRAM_COMPONENTS variable.

Name each job `cram <board> [<component>]` and include the selected
component in the expandable test-execution section title.

Move the MXL-specific cram skip from the legacy job-name token. Use the
stable DUT board identifier instead.

Preserve skip behavior under the compact OSPv2 name.

Default automatic pipelines to prplos. Start the full jobs
automatically in prplware release tag pipelines, whose build jobs also
run automatically. Keep cram jobs out of scheduled pipelines entirely,
as with the legacy suite: schedules never create the build jobs these
jobs need, so any selected cram job would fail scheduled pipeline
creation with an unsatisfiable needs reference. Keep the test command,
post suite, timeout, run_check, and JUnit filenames unchanged.

Assisted-by: codex:gpt-5
Assisted-by: claude:fable-5
References: CI-7
Signed-off-by: Petr Štetiar <petr.stetiar@prplfoundation.org>
2026-08-19 10:14:27 +00:00

247 lines
9.6 KiB
YAML

.testbed:
stage: run
image: "registry.gitlab.com/prpl-foundation/prplos/ci/containers/testbed/testbed:v1.3.0@sha256:7f50dde2279c201542569b7f31e965d43a308e245a4ec973df52d581560b0c28"
timeout: 87 minutes
variables:
DUT_WAN_INTERFACE: eth1
TESTBED_MNG_INTERFACE: enp1s0
TESTBED_LAN_INTERFACE: enp2s0
TESTBED_WAN_INTERFACE: enp3s0
TESTBED_TFTP_PATH: /var/lib/tftpboot
TFTP_IMAGE_PATH: bin/targets/$DUT_TARGET/$DUT_SUBTARGET
PACKAGE_DIR: bin/packages
DUT_ARCH_PACKAGES_PATH: $PACKAGE_DIR/${DUT_ARCH}_${DUT_CPU_TYPE}_${DUT_CPU_SUBTYPE}
TARGET_LAN_IP: 192.168.1.1
TARGET_LAN_TEST_HOST: 192.168.1.2
DUT_SLEEP_AFTER_BOOT: 90
DUT_SSH_CONNECT_TIMEOUT: 30
DUT_SSH_CONNECT_ATTEMPTS: 3
DUT_TR181_WAN_INTERFACE: Device.Ethernet.Link.2.
DUT_TR181_LAN_INTERFACE: Device.Ethernet.Link.3.
DUT_OBUSPA_VERBOSE_LEVEL: ''
DUT_OBUSPA_PROTOCOL_TRACE: ''
TEST_SETUP_TEARDOWN_DURATION: 360
CRAM_REMOTE_COMMAND: ssh -n root@$TARGET_LAN_IP
CRAM_REMOTE_COPY: scp -O -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null
CRAM_TEST_SUITE: |
.gitlab/tests/cram/generic/acceleration-plan-components
.gitlab/tests/cram/$DUT_BOARD/acceleration-plan-components
.gitlab/tests/cram/generic/lcm
.gitlab/tests/cram/generic
.gitlab/tests/cram/$DUT_BOARD
CRAM_TEST_SUITE_POST: |
.gitlab/tests/cram/post/generic
DUT_INIT_SCRIPTS: |
.gitlab/scripts/dut-init/dut-change-fail-action-to-restart.sh
before_script:
- source .gitlab/scripts/helpers.sh
- section_start "cdrouter-cleanup" "CDRouter Cleanup" "collapsed"
- >
if echo "$CI_RUNNER_DESCRIPTION" | grep -q testbed-02; then
export CDROUTER_API_TOKEN="$CDROUTER_API_TOKEN_TESTBED_02"
fi
- .gitlab/scripts/testbed-cdrouter.py check_connectivity
- .gitlab/scripts/testbed-cdrouter.py package_stop
- section_end "cdrouter-cleanup"
- section_start "testbed-setup" "Testbed Setup" "collapsed"
- touch .run_failed
- sudo ip link set $TESTBED_LAN_INTERFACE up 2> /dev/null
- sudo ip link set $TESTBED_WAN_INTERFACE up 2> /dev/null
- sleep 10
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- |
for f in ${TFTP_IMAGE_FILENAMES:-$TFTP_IMAGE_FILENAME}; do
echo "Using firmware image $TFTP_IMAGE_PATH/$f"
cp "$TFTP_IMAGE_PATH/$f" "$TESTBED_TFTP_PATH"
done
if [ -n "$TFTP_IMAGE_UNPACK_COMMAND" ]; then
echo "Running $TFTP_IMAGE_UNPACK_COMMAND"
eval "$TFTP_IMAGE_UNPACK_COMMAND"
fi
- >
if echo "$CI_RUNNER_DESCRIPTION" | grep -q testbed-02; then
export TB_CONFIG=".testbed/labgrid/testbed-02.yaml"
fi
- section_end "testbed-setup"
- section_start "dut-bringup" "DUT Bringup" "collapsed"
- .gitlab/scripts/testbed-device.py --target $LABGRID_TARGET boot_into shell
- >
.gitlab/scripts/testbed-device.py
--target $LABGRID_TARGET check_network
--network lan
--remote-host $TARGET_LAN_TEST_HOST
- sleep $DUT_SLEEP_AFTER_BOOT
- section_end "dut-bringup"
- section_start "dut-system-info" "DUT System Information" "collapsed"
- echo "Waiting for SSH connection availability with ${DUT_SSH_CONNECT_TIMEOUT}sec timeout, with $DUT_SSH_CONNECT_ATTEMPTS attempts..."
- time ssh -o BatchMode=yes -o StrictHostKeyChecking=no -o ConnectionAttempts=$DUT_SSH_CONNECT_ATTEMPTS -o ConnectTimeout=$DUT_SSH_CONNECT_TIMEOUT root@$TARGET_LAN_IP 'exit 0'
- ssh-keyscan $TARGET_LAN_IP >> ~/.ssh/known_hosts 2> /dev/null
- >
if [ -n "${DUT_OBUSPA_VERBOSE_LEVEL:-}" ] ||
[ -n "${DUT_OBUSPA_PROTOCOL_TRACE:-}" ]; then
.gitlab/scripts/dut-init/dut-configure-obuspa-logging.sh;
fi
- ssh root@$TARGET_LAN_IP 'logger -t CI -p local0.info "System accessible over SSH, $(uptime -p)"' || true
- ssh root@$TARGET_LAN_IP "cat /var/log/messages" > syslog-$LABGRID_TARGET.txt 2> /dev/null || true
- ssh root@$TARGET_LAN_IP "ubus call system board" | tee system-$LABGRID_TARGET.json
- >
for dut_init_script in $DUT_INIT_SCRIPTS;
do echo "Running $dut_init_script"; "${CI_PROJECT_DIR}/$dut_init_script";
done
- section_end "dut-system-info"
script:
- source .gitlab/scripts/helpers.sh
- section_start "test-execution" "Test Execution${COMPONENT:+ [$COMPONENT]}" "expanded"
- |
TEST_CUTOFF_TIMEOUT=$((CI_JOB_TIMEOUT - DUT_SLEEP_AFTER_BOOT - TEST_SETUP_TEARDOWN_DURATION))
echo "Job timeout: $CI_JOB_TIMEOUT seconds, test cutoff timeout: $TEST_CUTOFF_TIMEOUT seconds"
- |
rm -fr .run_check_failed
run_check() {
"$@" || {
local statuses=("${PIPESTATUS[@]}")
for status in "${statuses[@]}"; do
if [ "$status" -ne 0 ]; then
log_error "run_check: $* | FAILED! (status: $status)" | tee -a .run_check_failed
fi
done
}
}
run_check ssh root@$TARGET_LAN_IP 'f=$(logread | grep "procd.*init complete"); echo "${f:-Warning: init is not complete yet,} $(uptime -p)"'
run_check ssh root@$TARGET_LAN_IP 'logger -t CI -p local0.info "Testing starts, $(uptime -p)"'
run_check \
timeout --kill-after=10s --verbose ${TEST_CUTOFF_TIMEOUT}s \
python3 -m cram --xunit-file=cram-result-$LABGRID_TARGET.xunit.xml --verbose $CRAM_TEST_SUITE $CRAM_TEST_SUITE_EXTRA | tee cram-result-$LABGRID_TARGET.txt
run_check python3 -m cram --xunit-file=cram-result-post-$LABGRID_TARGET.xunit.xml --verbose $CRAM_TEST_SUITE_POST | tee --append cram-result-$LABGRID_TARGET.txt
run_check ssh root@$TARGET_LAN_IP 'logger -t CI -p local0.info "Testing finished, $(uptime -p)"'
- section_end "test-execution"
- |
[ -f .run_check_failed ] && cat .run_check_failed && exit 1
rm .run_failed
after_script:
- >-
curl --fail \
--output .gitlab/scripts/cram-xunit-merger.py \
https://gitlab.com/prpl-foundation/tooling/cram-xunit-merger/-/raw/9bc14318ab88c2a024ad0ff8bf09c21d048e1e3b/cram-xunit-merger.py
- python3 .gitlab/scripts/cram-xunit-merger.py \
--output "${CI_PROJECT_DIR}/cram-result-$LABGRID_TARGET.junit.xml" \
"${CI_PROJECT_DIR}/cram-result-$LABGRID_TARGET.xunit.xml" \
"${CI_PROJECT_DIR}/cram-result-post-$LABGRID_TARGET.xunit.xml" || true
- >
[ "$TMATE_ENABLE_SHELL" = "YES" ] && {
echo "Starting tmate session..."
tmate -n "${TMATE_SESSION_TOKEN}-$CI_JOB_ID" -k "$TMATE_API_KEY" -F new "ssh root@$TARGET_LAN_IP" > /tmp/tmate-session.log 2>&1
true
}
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
- >
if echo "$CI_RUNNER_DESCRIPTION" | grep -q testbed-02; then
export TB_CONFIG=".testbed/labgrid/testbed-02.yaml"
fi
- >
ssh -o BatchMode=yes -o StrictHostKeyChecking=no -o ConnectTimeout=15 root@$TARGET_LAN_IP 'exit 0' || {
.gitlab/scripts/testbed-device.py --target $LABGRID_TARGET console_dump_system_state
.gitlab/scripts/testbed-device.py --target $LABGRID_TARGET console_recover_ssh_access
} || true
- ssh-keyscan $TARGET_LAN_IP >> ~/.ssh/known_hosts 2> /dev/null
- >
ssh root@$TARGET_LAN_IP exit && {
ssh root@$TARGET_LAN_IP ps > processes-$LABGRID_TARGET.txt
ssh root@$TARGET_LAN_IP dmesg > dmesg-$LABGRID_TARGET.txt
ssh root@$TARGET_LAN_IP "cat /var/log/messages" > syslog-$LABGRID_TARGET.txt
ssh root@$TARGET_LAN_IP opkg list > opkg_list-$LABGRID_TARGET.txt
script --quiet --command "ssh -t root@$TARGET_LAN_IP /bin/getDebugInformation --all"
scp -O -r root@${TARGET_LAN_IP}:/tmp/debug-*_all.tar.gz . > /dev/null
scp -O -r root@${TARGET_LAN_IP}:/etc etc > /dev/null
scp -O -r root@${TARGET_LAN_IP}:/tmp/beerocks/logs prplmesh_beerocks_logs > /dev/null
} || true
- .gitlab/scripts/testbed-device.py --target $LABGRID_TARGET power off
- tar xzf debug-*_all.tar.gz || true
- mv debug-*.txt debug-information-$LABGRID_TARGET.txt || true
- ( [ $(tar -tf coredumps_all.tar.gz | wc -l) -eq 0 ] && rm coredumps_all.tar.gz || true ) 2>/dev/null
- mv coredumps_all.tar.gz coredumps-$LABGRID_TARGET.tar.gz 2> /dev/null || true
- mv console_$LABGRID_TARGET console_$LABGRID_TARGET.txt || true
artifacts:
expire_in: 1 month
when: always
paths:
- .gitlab/tests/cram/**/*.t.err
- .gitlab/tests/cram/**/*.actual
- .gitlab/tests/cram/**/*.diff
- etc
- prplmesh_beerocks_logs
- debug-information-$LABGRID_TARGET.txt
- processes-$LABGRID_TARGET.txt
- dmesg-$LABGRID_TARGET.txt
- syslog-$LABGRID_TARGET.txt
- system-$LABGRID_TARGET.json
- console_$LABGRID_TARGET.txt
- cram-result-*
- opkg_list-$LABGRID_TARGET.txt
- coredumps-$LABGRID_TARGET.tar.gz
reports:
junit: cram-result-$LABGRID_TARGET.junit.xml
.cram_component:
extends: .testbed
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
when: never
- if: '$CI_COMMIT_TAG =~ /^prplware-v[0-9]+\.[0-9]+\.[0-9]+.*$/ && $COMPONENT == "full"'
- if: '$COMPONENT == "full" && $CRAM_COMPONENTS =~ /(^|,)full($|,)/'
- if: '$COMPONENT == "prplmesh" && $CRAM_COMPONENTS =~ /(^|,)prplmesh($|,)/'
- if: '$COMPONENT == "lcm" && $CRAM_COMPONENTS =~ /(^|,)lcm($|,)/'
- if: '$COMPONENT == "prplos" && $CRAM_COMPONENTS =~ /(^|,)prplos($|,)/'
variables:
COMPONENT: prplos
script:
- |
CRAM_TEST_SUITE="$(
.gitlab/tests/cram/scripts/resolve-component-tests.py \
--test-root .gitlab/tests/cram \
--manifest components.yml \
--board "$DUT_BOARD" \
--component "$COMPONENT"
)"
export CRAM_TEST_SUITE
- !reference [.testbed, script]
.testbed true.cz:
extends: .cram_component