Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
13 changes: 12 additions & 1 deletion .github/scripts/sketch_utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -396,14 +396,25 @@ function count_sketches { # count_sketches <path> [target] [ignore-requirements]
local sketchdirname
local sketchname
local has_requirements
local parent_dir

sketchdir=$(dirname "$sketch")
sketchdirname=$(basename "$sketchdir")
sketchname=$(basename "$sketch")
parent_dir=$(dirname "$sketchdir")

if [[ "$sketchdirname.ino" != "$sketchname" ]]; then
continue
elif [[ -n $target ]] && [[ -f $sketchdir/ci.yml ]]; then
# Skip sketches that are part of multi-device tests (they are built separately)
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment on line 408 says "Skip sketches that are part of multi-device tests (they are built separately)" but the conditional check and logic span multiple lines (408-415). The comment placement could be clearer by placing it directly before the elif statement on line 409, or by adding it as a block comment explaining the entire section.

Suggested change
# Skip sketches that are part of multi-device tests (they are built separately)
#
# Skip sketches that are part of multi-device tests (they are built separately).
# This block checks if the parent directory contains a ci.yml file with a 'multi_device' key.
# If so, these sketches are built separately and should be skipped here.
#

Copilot uses AI. Check for mistakes.
elif [[ -f "$parent_dir/ci.yml" ]]; then
local has_multi_device
has_multi_device=$(yq eval '.multi_device' "$parent_dir/ci.yml" 2>/dev/null)
if [[ "$has_multi_device" != "null" && "$has_multi_device" != "" ]]; then
continue
fi
fi

if [[ -n $target ]] && [[ -f $sketchdir/ci.yml ]]; then
# If the target is listed as false, skip the sketch. Otherwise, include it.
is_target=$(yq eval ".targets.${target}" "$sketchdir"/ci.yml 2>/dev/null)
if [[ "$is_target" == "false" ]]; then
Expand Down
190 changes: 182 additions & 8 deletions .github/scripts/tests_build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,90 @@ function clean {
find tests/ -name 'result_*.json' -exec rm -rf "{}" \+
}

# Check if a test is a multi-device test
function is_multi_device_test {
local test_dir=$1
local has_multi_device
if [ -f "$test_dir/ci.yml" ]; then
has_multi_device=$(yq eval '.multi_device' "$test_dir/ci.yml" 2>/dev/null)
if [[ "$has_multi_device" != "null" && "$has_multi_device" != "" ]]; then
echo "1"
return
fi
fi
echo "0"
}

# Build a single sketch for multi-device tests
function build_multi_device_sketch {
local test_name=$1
local sketch_path=$2
local target=$3
shift 3
local build_args=("$@")
local sketch_dir
local sketch_name
local test_dir
local build_dir

sketch_dir=$(dirname "$sketch_path")
sketch_name=$(basename "$sketch_dir")
test_dir=$(dirname "$sketch_dir")

# Override build directory to use <test_name>_<sketch_name> pattern
build_dir="$HOME/.arduino/tests/$target/${test_name}_${sketch_name}/build.tmp"

echo "Building multi-device sketch $sketch_name for test $test_name"

# Call sketch_utils.sh build function with custom build directory
ARDUINO_BUILD_DIR="$build_dir" ${SCRIPTS_DIR}/sketch_utils.sh build "${build_args[@]}" -s "$sketch_dir"
return $?
}

# Build all sketches for a multi-device test
function build_multi_device_test {
local test_dir=$1
local target=$2
shift 2
local build_args=("$@")
local test_name
local devices

test_name=$(basename "$test_dir")

echo "Building multi-device test $test_name"

# Get the list of devices from ci.yml
devices=$(yq eval '.multi_device | keys | .[]' "$test_dir/ci.yml" 2>/dev/null)

if [[ -z "$devices" ]]; then
echo "ERROR: No devices found in multi_device configuration for $test_name"
return 1
fi

local result=0
local sketch_name
local sketch_path
for device in $devices; do
sketch_name=$(yq eval ".multi_device.$device" "$test_dir/ci.yml" 2>/dev/null)
sketch_path="$test_dir/$sketch_name/$sketch_name.ino"

if [ ! -f "$sketch_path" ]; then
echo "ERROR: Sketch not found: $sketch_path"
return 1
fi

build_multi_device_sketch "$test_name" "$sketch_path" "$target" "${build_args[@]}"
result=$?
if [ $result -ne 0 ]; then
echo "ERROR: Failed to build sketch $sketch_name for test $test_name"
return $result
fi
done

return 0
}

SCRIPTS_DIR="./.github/scripts"
BUILD_CMD=""

Expand Down Expand Up @@ -58,10 +142,25 @@ args=("-ai" "$ARDUINO_IDE_PATH" "-au" "$ARDUINO_USR_PATH")

if [[ $test_type == "all" ]] || [[ -z $test_type ]]; then
if [ -n "$sketch" ]; then
tmp_sketch_path=$(find tests -name "$sketch".ino)
test_type=$(basename "$(dirname "$(dirname "$tmp_sketch_path")")")
# For multi-device tests, we need to find the test directory, not the device sketch directory
# First, try to find a test directory with this name
if [ -d "tests/validation/$sketch" ] && [ -f "tests/validation/$sketch/ci.yml" ]; then
test_type="validation"
test_folder="$PWD/tests/$test_type"
elif [ -d "tests/performance/$sketch" ] && [ -f "tests/performance/$sketch/ci.yml" ]; then
test_type="performance"
test_folder="$PWD/tests/$test_type"
else
# Fall back to finding by .ino file (for regular tests)
tmp_sketch_path=$(find tests -name "$sketch".ino | head -1)
if [ -z "$tmp_sketch_path" ]; then
echo "ERROR: Sketch $sketch not found"
exit 1
fi
test_type=$(basename "$(dirname "$(dirname "$tmp_sketch_path")")")
test_folder="$PWD/tests/$test_type"
fi
echo "Sketch $sketch test type: $test_type"
test_folder="$PWD/tests/$test_type"
else
test_folder="$PWD/tests"
fi
Expand All @@ -70,11 +169,86 @@ else
fi

if [ $chunk_build -eq 1 ]; then
# For chunk builds, we need to handle multi-device tests separately
# First, build all multi-device tests, then build regular tests

# Extract target from remaining arguments
target=""
remaining_args=()
while [ -n "$1" ]; do
case $1 in
-t )
shift
target=$1
remaining_args+=("-t" "$target")
;;
* )
remaining_args+=("$1")
;;
esac
shift
done

if [ -z "$target" ]; then
echo "ERROR: Target (-t) is required for chunk builds"
exit 1
fi

# Find and build all multi-device tests in the test folder
multi_device_error=0
if [ -d "$test_folder" ]; then
for test_dir in "$test_folder"/*; do
if [ -d "$test_dir" ] && [ "$(is_multi_device_test "$test_dir")" -eq 1 ]; then
build_multi_device_test "$test_dir" "$target" "${args[@]}" "${remaining_args[@]}"
result=$?
if [ $result -ne 0 ]; then
multi_device_error=$result
fi
fi
done
fi

# Now build regular (non-multi-device) tests using chunk_build
BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh chunk_build"
args+=("-p" "$test_folder" "-i" "0" "-m" "1")
args+=("-p" "$test_folder")
${BUILD_CMD} "${args[@]}" "${remaining_args[@]}"
regular_error=$?

# Return error if either multi-device or regular builds failed
if [ $multi_device_error -ne 0 ]; then
exit $multi_device_error
fi
exit $regular_error
else
BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh build"
args+=("-s" "$test_folder/$sketch")
fi
# Check if this is a multi-device test
test_dir="$test_folder/$sketch"
if [ -d "$test_dir" ] && [ "$(is_multi_device_test "$test_dir")" -eq 1 ]; then
# Extract target from remaining arguments
target=""
remaining_args=()
while [ -n "$1" ]; do
case $1 in
-t )
shift
target=$1
remaining_args+=("-t" "$target")
;;
* )
remaining_args+=("$1")
;;
esac
shift
done
Comment on lines +176 to +241
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code duplicates the target extraction logic (lines 176-190 and lines 226-241). This duplication could be avoided by extracting this logic into a separate function that returns the target and remaining arguments, improving maintainability.

Copilot uses AI. Check for mistakes.

${BUILD_CMD} "${args[@]}" "$@"
if [ -z "$target" ]; then
echo "ERROR: Target (-t) is required for multi-device tests"
exit 1
fi

build_multi_device_test "$test_dir" "$target" "${args[@]}" "${remaining_args[@]}"
else
BUILD_CMD="${SCRIPTS_DIR}/sketch_utils.sh build"
args+=("-s" "$test_folder/$sketch")
${BUILD_CMD} "${args[@]}" "$@"
fi
fi
Loading
Loading