Skip to content

Commit be5a8a0

Browse files
committed
Merge branch 'ci/fixes'
2 parents b20655a + a906d01 commit be5a8a0

File tree

503 files changed

+1214
-1827
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

503 files changed

+1214
-1827
lines changed

.github/CODEOWNERS

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
/libraries/ESP_SR/ @me-no-dev
6060
/libraries/ESPmDNS/ @me-no-dev
6161
/libraries/Ethernet/ @me-no-dev
62+
/libraries/Hash/ @lucasssvaz
6263
/libraries/Matter/ @SuGlider
6364
/libraries/NetBIOS/ @me-no-dev
6465
/libraries/Network/ @me-no-dev
@@ -72,9 +73,9 @@
7273
/libraries/Wire/ @me-no-dev
7374
/libraries/Zigbee/ @P-R-O-C-H-Y
7475

75-
# CI JSON
76+
# CI YAML
7677
# Keep this after other libraries and tests to avoid being overridden.
77-
**/ci.json @lucasssvaz
78+
**/ci.yml @lucasssvaz
7879

7980
# The CODEOWNERS file should be owned by the developers of the ESP32 Arduino Core.
8081
# Leave this entry as the last one to avoid being overridden.

.github/scripts/get_affected.py

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
Build file patterns
6464
--------------------
6565
- **build_files**: Core Arduino build system files (platform.txt, variants/**, etc.)
66-
- **sketch_build_files**: Sketch-specific files (ci.json, *.csv in example directories)
66+
- **sketch_build_files**: Sketch-specific files (ci.yml, *.csv in example directories)
6767
- **idf_build_files**: Core IDF build system files (CMakeLists.txt, idf_component.yml, etc.)
6868
- **idf_project_files**: Project-specific IDF files (per-example CMakeLists.txt, sdkconfig, etc.)
6969
@@ -128,7 +128,7 @@
128128
# Files that are used by the sketch build system.
129129
# If any of these files change, the sketch should be recompiled.
130130
sketch_build_files = [
131-
"libraries/*/examples/**/ci.json",
131+
"libraries/*/examples/**/ci.yml",
132132
"libraries/*/examples/**/*.csv",
133133
]
134134

@@ -150,7 +150,7 @@
150150
# If any of these files change, the example that uses them should be recompiled.
151151
idf_project_files = [
152152
"idf_component_examples/*/CMakeLists.txt",
153-
"idf_component_examples/*/ci.json",
153+
"idf_component_examples/*/ci.yml",
154154
"idf_component_examples/*/*.csv",
155155
"idf_component_examples/*/sdkconfig*",
156156
"idf_component_examples/*/main/*",
@@ -358,6 +358,59 @@ def build_qname_from_tag(tag: dict) -> str:
358358
qname = "::".join([p for p in qparts if p])
359359
return f"{qname}{signature}"
360360

361+
def find_impl_files_for_qname(qname: str, defs_by_qname: dict[str, set[str]], header_path: str = None) -> set[str]:
362+
"""
363+
Find implementation files for a qualified name, handling namespace mismatches.
364+
365+
Ctags may capture different namespace scopes in headers vs implementations.
366+
For example:
367+
- Header: fs::SDFS::begin(...)
368+
- Implementation: SDFS::begin(...)
369+
370+
This happens when implementations use "using namespace" directives.
371+
372+
Strategy:
373+
1. Try exact match first
374+
2. If no match and qname has namespaces, try stripping ONLY outer namespace prefixes
375+
(keep at least Class::method structure intact)
376+
3. If header_path provided, prefer implementations from same directory
377+
"""
378+
# Try exact match first
379+
impl_files = defs_by_qname.get(qname, set())
380+
if impl_files:
381+
return impl_files
382+
383+
# If no exact match and the qname contains namespaces (::), try stripping them
384+
if "::" in qname:
385+
parts = qname.split("::")
386+
# Only strip outer namespaces, not the class/method structure
387+
# For "ns1::ns2::Class::method(...)", we want to try:
388+
# - "ns2::Class::method(...)" (strip 1 level)
389+
# - "Class::method(...)" (strip 2 levels)
390+
# But NOT "method(...)" alone (too ambiguous)
391+
392+
# Only allow stripping if we have more than 2 parts (namespace::Class::method)
393+
# If we only have 2 parts (Class::method), don't strip as it would leave just "method"
394+
if len(parts) > 2:
395+
# Keep at least 2 parts (Class::method) to avoid false positives
396+
max_strip = len(parts) - 2
397+
398+
for i in range(1, max_strip + 1):
399+
shorter_qname = "::".join(parts[i:])
400+
impl_files = defs_by_qname.get(shorter_qname, set())
401+
402+
if impl_files:
403+
# If we have the header path, prefer implementations from same directory
404+
if header_path:
405+
header_dir = os.path.dirname(header_path)
406+
same_dir_files = {f for f in impl_files if os.path.dirname(f) == header_dir}
407+
if same_dir_files:
408+
return same_dir_files
409+
410+
return impl_files
411+
412+
return set()
413+
361414
def run_ctags_and_index(paths: list[str]) -> tuple[dict[str, set[str]], dict[str, set[str]], str]:
362415
"""
363416
Run Universal Ctags over given paths (relative to project_root) and build:
@@ -582,8 +635,10 @@ def build_dependencies_graph() -> None:
582635
if qnames:
583636
impl_files = set()
584637
for qn in qnames:
585-
# For each qualified name, get the implementation files
586-
impl_files |= ctags_defs_by_qname.get(qn, set())
638+
# For each qualified name, find implementation files
639+
# This handles namespace mismatches (e.g., fs::SDFS vs SDFS)
640+
# Pass header_path to prefer implementations from same directory
641+
impl_files |= find_impl_files_for_qname(qn, ctags_defs_by_qname, header_path)
587642
for impl in impl_files:
588643
# Skip .ino files - they should never be dependencies of other files
589644
if impl.endswith('.ino'):

.github/scripts/on-push-idf.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ fi
1717

1818
for example in $affected_examples; do
1919
example_path="$PWD/components/arduino-esp32/$example"
20-
if [ -f "$example_path/ci.json" ]; then
20+
if [ -f "$example_path/ci.yml" ]; then
2121
# If the target is listed as false, skip the sketch. Otherwise, include it.
22-
is_target=$(jq -r --arg target "$IDF_TARGET" '.targets[$target]' "$example_path/ci.json")
22+
is_target=$(yq eval ".targets.${IDF_TARGET}" "$example_path/ci.yml" 2>/dev/null)
2323
if [[ "$is_target" == "false" ]]; then
2424
printf "\n\033[93mSkipping %s for target %s\033[0m\n\n" "$example" "$IDF_TARGET"
2525
continue

.github/scripts/sketch_utils.sh

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ function check_requirements { # check_requirements <sketchdir> <sdkconfig_path>
1515
local requirements
1616
local requirements_or
1717

18-
if [ ! -f "$sdkconfig_path" ] || [ ! -f "$sketchdir/ci.json" ]; then
19-
echo "WARNING: sdkconfig or ci.json not found. Assuming requirements are met." 1>&2
18+
if [ ! -f "$sdkconfig_path" ] || [ ! -f "$sketchdir/ci.yml" ]; then
19+
echo "WARNING: sdkconfig or ci.yml not found. Assuming requirements are met." 1>&2
2020
# Return 1 on error to force the sketch to be built and fail. This way the
2121
# CI will fail and the user will know that the sketch has a problem.
2222
else
2323
# Check if the sketch requires any configuration options (AND)
24-
requirements=$(jq -r '.requires[]? // empty' "$sketchdir/ci.json")
24+
requirements=$(yq eval '.requires[]' "$sketchdir/ci.yml" 2>/dev/null)
2525
if [[ "$requirements" != "null" && "$requirements" != "" ]]; then
2626
for requirement in $requirements; do
2727
requirement=$(echo "$requirement" | xargs)
@@ -33,7 +33,7 @@ function check_requirements { # check_requirements <sketchdir> <sdkconfig_path>
3333
fi
3434

3535
# Check if the sketch requires any configuration options (OR)
36-
requirements_or=$(jq -r '.requires_any[]? // empty' "$sketchdir/ci.json")
36+
requirements_or=$(yq eval '.requires_any[]' "$sketchdir/ci.yml" 2>/dev/null)
3737
if [[ "$requirements_or" != "null" && "$requirements_or" != "" ]]; then
3838
local found=false
3939
for requirement in $requirements_or; do
@@ -122,13 +122,13 @@ function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [ext
122122
# precedence. Note that the following logic also falls to the default
123123
# parameters if no arguments were passed and no file was found.
124124

125-
if [ -z "$options" ] && [ -f "$sketchdir"/ci.json ]; then
125+
if [ -z "$options" ] && [ -f "$sketchdir"/ci.yml ]; then
126126
# The config file could contain multiple FQBNs for one chip. If
127127
# that's the case we build one time for every FQBN.
128128

129-
len=$(jq -r --arg target "$target" '.fqbn[$target] | length' "$sketchdir"/ci.json)
129+
len=$(yq eval ".fqbn.${target} | length" "$sketchdir"/ci.yml 2>/dev/null || echo 0)
130130
if [ "$len" -gt 0 ]; then
131-
fqbn=$(jq -r --arg target "$target" '.fqbn[$target] | sort' "$sketchdir"/ci.json)
131+
fqbn=$(yq eval ".fqbn.${target} | sort | @json" "$sketchdir"/ci.yml)
132132
fi
133133
fi
134134

@@ -138,8 +138,8 @@ function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [ext
138138

139139
len=1
140140

141-
if [ -f "$sketchdir"/ci.json ]; then
142-
fqbn_append=$(jq -r '.fqbn_append' "$sketchdir"/ci.json)
141+
if [ -f "$sketchdir"/ci.yml ]; then
142+
fqbn_append=$(yq eval '.fqbn_append' "$sketchdir"/ci.yml 2>/dev/null)
143143
if [ "$fqbn_append" == "null" ]; then
144144
fqbn_append=""
145145
fi
@@ -229,9 +229,9 @@ function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [ext
229229
sketchname=$(basename "$sketchdir")
230230
local has_requirements
231231

232-
if [ -f "$sketchdir"/ci.json ]; then
232+
if [ -f "$sketchdir"/ci.yml ]; then
233233
# If the target is listed as false, skip the sketch. Otherwise, include it.
234-
is_target=$(jq -r --arg target "$target" '.targets[$target]' "$sketchdir"/ci.json)
234+
is_target=$(yq eval ".targets.${target}" "$sketchdir"/ci.yml 2>/dev/null)
235235
if [[ "$is_target" == "false" ]]; then
236236
echo "Skipping $sketchname for target $target"
237237
exit 0
@@ -244,7 +244,7 @@ function build_sketch { # build_sketch <ide_path> <user_path> <path-to-ino> [ext
244244
fi
245245
fi
246246

247-
# Install libraries from ci.json if they exist
247+
# Install libraries from ci.yml if they exist
248248
install_libs -ai "$ide_path" -s "$sketchdir"
249249
install_result=$?
250250
if [ $install_result -ne 0 ]; then
@@ -394,9 +394,9 @@ function count_sketches { # count_sketches <path> [target] [ignore-requirements]
394394

395395
if [[ "$sketchdirname.ino" != "$sketchname" ]]; then
396396
continue
397-
elif [[ -n $target ]] && [[ -f $sketchdir/ci.json ]]; then
397+
elif [[ -n $target ]] && [[ -f $sketchdir/ci.yml ]]; then
398398
# If the target is listed as false, skip the sketch. Otherwise, include it.
399-
is_target=$(jq -r --arg target "$target" '.targets[$target]' "$sketchdir"/ci.json)
399+
is_target=$(yq eval ".targets.${target}" "$sketchdir"/ci.yml 2>/dev/null)
400400
if [[ "$is_target" == "false" ]]; then
401401
continue
402402
fi
@@ -637,38 +637,38 @@ function install_libs { # install_libs <ide_path> <sketchdir> [-v]
637637
return 1
638638
fi
639639

640-
if [ ! -f "$sketchdir/ci.json" ]; then
641-
[ "$verbose" = true ] && echo "No ci.json found in $sketchdir, skipping library installation"
640+
if [ ! -f "$sketchdir/ci.yml" ]; then
641+
[ "$verbose" = true ] && echo "No ci.yml found in $sketchdir, skipping library installation"
642642
return 0
643643
fi
644-
if ! jq -e . "$sketchdir/ci.json" >/dev/null 2>&1; then
645-
echo "ERROR: $sketchdir/ci.json is not valid JSON" >&2
644+
if ! yq eval '.' "$sketchdir/ci.yml" >/dev/null 2>&1; then
645+
echo "ERROR: $sketchdir/ci.yml is not valid YAML" >&2
646646
return 1
647647
fi
648648

649649
local libs_type
650-
libs_type=$(jq -r '.libs | type' "$sketchdir/ci.json" 2>/dev/null)
650+
libs_type=$(yq eval '.libs | type' "$sketchdir/ci.yml" 2>/dev/null)
651651
if [ -z "$libs_type" ] || [ "$libs_type" = "null" ]; then
652-
[ "$verbose" = true ] && echo "No libs field found in ci.json, skipping library installation"
652+
[ "$verbose" = true ] && echo "No libs field found in ci.yml, skipping library installation"
653653
return 0
654-
elif [ "$libs_type" != "array" ]; then
655-
echo "ERROR: libs field in ci.json must be an array, found: $libs_type" >&2
654+
elif [ "$libs_type" != "!!seq" ]; then
655+
echo "ERROR: libs field in ci.yml must be an array, found: $libs_type" >&2
656656
return 1
657657
fi
658658

659659
local libs_count
660-
libs_count=$(jq -r '.libs | length' "$sketchdir/ci.json" 2>/dev/null)
660+
libs_count=$(yq eval '.libs | length' "$sketchdir/ci.yml" 2>/dev/null)
661661
if [ "$libs_count" -eq 0 ]; then
662-
[ "$verbose" = true ] && echo "libs array is empty in ci.json, skipping library installation"
662+
[ "$verbose" = true ] && echo "libs array is empty in ci.yml, skipping library installation"
663663
return 0
664664
fi
665665

666-
echo "Installing $libs_count libraries from $sketchdir/ci.json"
666+
echo "Installing $libs_count libraries from $sketchdir/ci.yml"
667667

668668
local needs_unsafe=false
669669
local original_unsafe_setting=""
670670
local libs
671-
libs=$(jq -r '.libs[]? // empty' "$sketchdir/ci.json")
671+
libs=$(yq eval '.libs[]' "$sketchdir/ci.yml" 2>/dev/null)
672672

673673
# Detect any git-like URL (GitHub/GitLab/Bitbucket/self-hosted/ssh)
674674
for lib in $libs; do
@@ -749,7 +749,7 @@ Available commands:
749749
build: Build a sketch.
750750
chunk_build: Build a chunk of sketches.
751751
check_requirements: Check if target meets sketch requirements.
752-
install_libs: Install libraries from ci.json file.
752+
install_libs: Install libraries from ci.yml file.
753753
"
754754

755755
cmd=$1

.github/scripts/tests_matrix.sh

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,25 @@ if [[ $IS_PR != 'true' ]] || [[ $PERFORMANCE_ENABLED == 'true' ]]; then
1212
#qemu_types+=",'performance'"
1313
fi
1414

15-
targets="'esp32','esp32s2','esp32s3','esp32c3','esp32c6','esp32h2','esp32p4'"
15+
hw_targets="'esp32','esp32s2','esp32s3','esp32c3','esp32c5','esp32c6','esp32h2','esp32p4'"
16+
wokwi_targets="'esp32','esp32s2','esp32s3','esp32c3','esp32c6','esp32h2','esp32p4'"
17+
qemu_targets="'esp32','esp32c3'"
1618

1719
mkdir -p info
1820

19-
echo "[$wokwi_types]" > info/wokwi_types.txt
21+
echo "[$hw_targets]" > info/hw_targets.txt
2022
echo "[$hw_types]" > info/hw_types.txt
21-
echo "[$targets]" > info/targets.txt
23+
echo "[$wokwi_targets]" > info/wokwi_targets.txt
24+
echo "[$wokwi_types]" > info/wokwi_types.txt
25+
echo "[$qemu_targets]" > info/qemu_targets.txt
26+
echo "[$qemu_types]" > info/qemu_types.txt
2227

2328
{
2429
echo "build-types=[$build_types]"
30+
echo "hw_targets=[$hw_targets]"
2531
echo "hw-types=[$hw_types]"
32+
echo "wokwi_targets=[$wokwi_targets]"
2633
echo "wokwi-types=[$wokwi_types]"
34+
echo "qemu_targets=[$qemu_targets]"
2735
echo "qemu-types=[$qemu_types]"
28-
echo "targets=[$targets]"
2936
} >> "$GITHUB_OUTPUT"

.github/scripts/tests_run.sh

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ function run_test {
1717
sketchname=$(basename "$sketchdir")
1818
test_type=$(basename "$(dirname "$sketchdir")")
1919

20-
if [ "$options" -eq 0 ] && [ -f "$sketchdir"/ci.json ]; then
21-
len=$(jq -r --arg target "$target" '.fqbn[$target] | length' "$sketchdir"/ci.json)
20+
if [ "$options" -eq 0 ] && [ -f "$sketchdir"/ci.yml ]; then
21+
len=$(yq eval ".fqbn.${target} | length" "$sketchdir"/ci.yml 2>/dev/null || echo 0)
2222
if [ "$len" -eq 0 ]; then
2323
len=1
2424
fi
@@ -32,10 +32,10 @@ function run_test {
3232
sdkconfig_path="$HOME/.arduino/tests/$target/$sketchname/build0.tmp/sdkconfig"
3333
fi
3434

35-
if [ -f "$sketchdir"/ci.json ]; then
35+
if [ -f "$sketchdir"/ci.yml ]; then
3636
# If the target or platform is listed as false, skip the sketch. Otherwise, include it.
37-
is_target=$(jq -r --arg target "$target" '.targets[$target]' "$sketchdir"/ci.json)
38-
selected_platform=$(jq -r --arg platform "$platform" '.platforms[$platform]' "$sketchdir"/ci.json)
37+
is_target=$(yq eval ".targets.${target}" "$sketchdir"/ci.yml 2>/dev/null)
38+
selected_platform=$(yq eval ".platforms.${platform}" "$sketchdir"/ci.yml 2>/dev/null)
3939

4040
if [[ $is_target == "false" ]] || [[ $selected_platform == "false" ]]; then
4141
printf "\033[93mSkipping %s test for %s, platform: %s\033[0m\n" "$sketchname" "$target" "$platform"
@@ -68,11 +68,11 @@ function run_test {
6868
fqbn="Default"
6969

7070
if [ "$len" -ne 1 ]; then
71-
fqbn=$(jq -r --arg target "$target" --argjson i "$i" '.fqbn[$target] | sort | .[$i]' "$sketchdir"/ci.json)
72-
elif [ -f "$sketchdir"/ci.json ]; then
73-
has_fqbn=$(jq -r --arg target "$target" '.fqbn[$target]' "$sketchdir"/ci.json)
71+
fqbn=$(yq eval ".fqbn.${target} | sort | .[${i}]" "$sketchdir"/ci.yml 2>/dev/null)
72+
elif [ -f "$sketchdir"/ci.yml ]; then
73+
has_fqbn=$(yq eval ".fqbn.${target}" "$sketchdir"/ci.yml 2>/dev/null)
7474
if [ "$has_fqbn" != "null" ]; then
75-
fqbn=$(jq -r --arg target "$target" '.fqbn[$target] | .[0]' "$sketchdir"/ci.json)
75+
fqbn=$(yq eval ".fqbn.${target} | .[0]" "$sketchdir"/ci.yml 2>/dev/null)
7676
fi
7777
fi
7878

.github/workflows/docs_deploy.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ permissions:
1919
jobs:
2020
deploy-prod-docs:
2121
name: Deploy Documentation on Production
22+
if: github.repository == 'espressif/arduino-esp32'
2223
runs-on: ubuntu-22.04
2324
defaults:
2425
run:

.github/workflows/push.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ on:
2929
- "libraries/**/*.c"
3030
- "libraries/**/*.h"
3131
- "libraries/**/*.ino"
32-
- "libraries/**/ci.json"
32+
- "libraries/**/ci.yml"
3333
- "package/**"
3434
- "tools/get.*"
3535
- "platform.txt"

.github/workflows/tests.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,9 @@ jobs:
5454
runs-on: ubuntu-latest
5555
outputs:
5656
build-types: ${{ steps.set-matrix.outputs.build-types }}
57-
hw-types: ${{ steps.set-matrix.outputs.hw-types }}
58-
wokwi-types: ${{ steps.set-matrix.outputs.wokwi-types }}
57+
hw-targets: ${{ steps.set-matrix.outputs.hw-targets }}
5958
qemu-types: ${{ steps.set-matrix.outputs.qemu-types }}
60-
targets: ${{ steps.set-matrix.outputs.targets }}
59+
qemu-targets: ${{ steps.set-matrix.outputs.qemu-targets }}
6160
env:
6261
IS_PR: ${{ github.event.pull_request.number != null }}
6362
PERFORMANCE_ENABLED: ${{ contains(github.event.pull_request.labels.*.name, 'perf_test') }}
@@ -84,7 +83,7 @@ jobs:
8483
strategy:
8584
matrix:
8685
type: ${{ fromJson(needs.gen-matrix.outputs.build-types) }}
87-
chip: ${{ fromJson(needs.gen-matrix.outputs.targets) }}
86+
chip: ${{ fromJson(needs.gen-matrix.outputs.hw-targets) }}
8887
with:
8988
type: ${{ matrix.type }}
9089
chip: ${{ matrix.chip }}
@@ -99,7 +98,7 @@ jobs:
9998
fail-fast: false
10099
matrix:
101100
type: ${{ fromJson(needs.gen-matrix.outputs.qemu-types) }}
102-
chip: ["esp32", "esp32c3"]
101+
chip: ${{ fromJson(needs.gen-matrix.outputs.qemu-targets) }}
103102
with:
104103
type: ${{ matrix.type }}
105104
chip: ${{ matrix.chip }}

0 commit comments

Comments
 (0)