mirror of
https://github.com/esphome/esphome.git
synced 2025-10-21 19:23:45 +01:00
tweak
This commit is contained in:
28
.github/workflows/ci.yml
vendored
28
.github/workflows/ci.yml
vendored
@@ -564,26 +564,14 @@ jobs:
|
|||||||
|
|
||||||
echo "Compiling with test_build_components.py..."
|
echo "Compiling with test_build_components.py..."
|
||||||
|
|
||||||
# Find most recent build directory for detailed analysis
|
# Run build and extract memory with auto-detection of build directory for detailed analysis
|
||||||
build_dir=$(find ~/.esphome/build -type d -maxdepth 1 -mindepth 1 -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2- || echo "")
|
|
||||||
|
|
||||||
# Run build and extract memory, with optional detailed analysis
|
|
||||||
if [ -n "$build_dir" ]; then
|
|
||||||
python script/test_build_components.py \
|
python script/test_build_components.py \
|
||||||
-e compile \
|
-e compile \
|
||||||
-c "$component_list" \
|
-c "$component_list" \
|
||||||
-t "$platform" 2>&1 | \
|
-t "$platform" 2>&1 | \
|
||||||
python script/ci_memory_impact_extract.py \
|
python script/ci_memory_impact_extract.py \
|
||||||
--output-env \
|
--output-env \
|
||||||
--build-dir "$build_dir" \
|
|
||||||
--output-json memory-analysis-target.json
|
--output-json memory-analysis-target.json
|
||||||
else
|
|
||||||
python script/test_build_components.py \
|
|
||||||
-e compile \
|
|
||||||
-c "$component_list" \
|
|
||||||
-t "$platform" 2>&1 | \
|
|
||||||
python script/ci_memory_impact_extract.py --output-env
|
|
||||||
fi
|
|
||||||
- name: Upload memory analysis JSON
|
- name: Upload memory analysis JSON
|
||||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
with:
|
with:
|
||||||
@@ -631,26 +619,14 @@ jobs:
|
|||||||
|
|
||||||
echo "Compiling with test_build_components.py..."
|
echo "Compiling with test_build_components.py..."
|
||||||
|
|
||||||
# Find most recent build directory for detailed analysis
|
# Run build and extract memory with auto-detection of build directory for detailed analysis
|
||||||
build_dir=$(find ~/.esphome/build -type d -maxdepth 1 -mindepth 1 -printf '%T@ %p\n' 2>/dev/null | sort -rn | head -1 | cut -d' ' -f2- || echo "")
|
|
||||||
|
|
||||||
# Run build and extract memory, with optional detailed analysis
|
|
||||||
if [ -n "$build_dir" ]; then
|
|
||||||
python script/test_build_components.py \
|
python script/test_build_components.py \
|
||||||
-e compile \
|
-e compile \
|
||||||
-c "$component_list" \
|
-c "$component_list" \
|
||||||
-t "$platform" 2>&1 | \
|
-t "$platform" 2>&1 | \
|
||||||
python script/ci_memory_impact_extract.py \
|
python script/ci_memory_impact_extract.py \
|
||||||
--output-env \
|
--output-env \
|
||||||
--build-dir "$build_dir" \
|
|
||||||
--output-json memory-analysis-pr.json
|
--output-json memory-analysis-pr.json
|
||||||
else
|
|
||||||
python script/test_build_components.py \
|
|
||||||
-e compile \
|
|
||||||
-c "$component_list" \
|
|
||||||
-t "$platform" 2>&1 | \
|
|
||||||
python script/ci_memory_impact_extract.py --output-env
|
|
||||||
fi
|
|
||||||
- name: Upload memory analysis JSON
|
- name: Upload memory analysis JSON
|
||||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||||
with:
|
with:
|
||||||
|
@@ -28,8 +28,10 @@ sys.path.insert(0, str(Path(__file__).parent.parent))
|
|||||||
from script.ci_helpers import write_github_output
|
from script.ci_helpers import write_github_output
|
||||||
|
|
||||||
|
|
||||||
def extract_from_compile_output(output_text: str) -> tuple[int | None, int | None]:
|
def extract_from_compile_output(
|
||||||
"""Extract memory usage from PlatformIO compile output.
|
output_text: str,
|
||||||
|
) -> tuple[int | None, int | None, str | None]:
|
||||||
|
"""Extract memory usage and build directory from PlatformIO compile output.
|
||||||
|
|
||||||
Supports multiple builds (for component groups or isolated components).
|
Supports multiple builds (for component groups or isolated components).
|
||||||
When test_build_components.py creates multiple builds, this sums the
|
When test_build_components.py creates multiple builds, this sums the
|
||||||
@@ -39,11 +41,14 @@ def extract_from_compile_output(output_text: str) -> tuple[int | None, int | Non
|
|||||||
RAM: [==== ] 36.1% (used 29548 bytes from 81920 bytes)
|
RAM: [==== ] 36.1% (used 29548 bytes from 81920 bytes)
|
||||||
Flash: [=== ] 34.0% (used 348511 bytes from 1023984 bytes)
|
Flash: [=== ] 34.0% (used 348511 bytes from 1023984 bytes)
|
||||||
|
|
||||||
|
Also extracts build directory from lines like:
|
||||||
|
INFO Deleting /path/to/build/.esphome/build/componenttestesp8266ard/.pioenvs
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
output_text: Compile output text (may contain multiple builds)
|
output_text: Compile output text (may contain multiple builds)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple of (total_ram_bytes, total_flash_bytes) or (None, None) if not found
|
Tuple of (total_ram_bytes, total_flash_bytes, build_dir) or (None, None, None) if not found
|
||||||
"""
|
"""
|
||||||
# Find all RAM and Flash matches (may be multiple builds)
|
# Find all RAM and Flash matches (may be multiple builds)
|
||||||
ram_matches = re.findall(
|
ram_matches = re.findall(
|
||||||
@@ -54,13 +59,21 @@ def extract_from_compile_output(output_text: str) -> tuple[int | None, int | Non
|
|||||||
)
|
)
|
||||||
|
|
||||||
if not ram_matches or not flash_matches:
|
if not ram_matches or not flash_matches:
|
||||||
return None, None
|
return None, None, None
|
||||||
|
|
||||||
# Sum all builds (handles multiple component groups)
|
# Sum all builds (handles multiple component groups)
|
||||||
total_ram = sum(int(match) for match in ram_matches)
|
total_ram = sum(int(match) for match in ram_matches)
|
||||||
total_flash = sum(int(match) for match in flash_matches)
|
total_flash = sum(int(match) for match in flash_matches)
|
||||||
|
|
||||||
return total_ram, total_flash
|
# Extract build directory from ESPHome's delete messages
|
||||||
|
# Look for: INFO Deleting /path/to/build/.esphome/build/componenttest.../.pioenvs
|
||||||
|
build_dir = None
|
||||||
|
if match := re.search(
|
||||||
|
r"INFO Deleting (.+/\.esphome/build/componenttest[^/]+)/\.pioenvs", output_text
|
||||||
|
):
|
||||||
|
build_dir = match.group(1)
|
||||||
|
|
||||||
|
return total_ram, total_flash, build_dir
|
||||||
|
|
||||||
|
|
||||||
def run_detailed_analysis(build_dir: str) -> dict | None:
|
def run_detailed_analysis(build_dir: str) -> dict | None:
|
||||||
@@ -94,18 +107,31 @@ def run_detailed_analysis(build_dir: str) -> dict | None:
|
|||||||
print(f"firmware.elf not found in {build_dir}", file=sys.stderr)
|
print(f"firmware.elf not found in {build_dir}", file=sys.stderr)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Find idedata.json
|
# Find idedata.json - check multiple locations
|
||||||
device_name = build_path.name
|
device_name = build_path.name
|
||||||
idedata_path = Path.home() / ".esphome" / "idedata" / f"{device_name}.json"
|
idedata_candidates = [
|
||||||
|
# In .pioenvs for test builds
|
||||||
|
build_path / ".pioenvs" / device_name / "idedata.json",
|
||||||
|
# In .esphome/idedata for regular builds
|
||||||
|
Path.home() / ".esphome" / "idedata" / f"{device_name}.json",
|
||||||
|
# Check parent directories for .esphome/idedata (for test_build_components)
|
||||||
|
build_path.parent.parent.parent / "idedata" / f"{device_name}.json",
|
||||||
|
]
|
||||||
|
|
||||||
idedata = None
|
idedata = None
|
||||||
|
for idedata_path in idedata_candidates:
|
||||||
if idedata_path.exists():
|
if idedata_path.exists():
|
||||||
try:
|
try:
|
||||||
with open(idedata_path, encoding="utf-8") as f:
|
with open(idedata_path, encoding="utf-8") as f:
|
||||||
raw_data = json.load(f)
|
raw_data = json.load(f)
|
||||||
idedata = IDEData(raw_data)
|
idedata = IDEData(raw_data)
|
||||||
|
print(f"Loaded idedata from: {idedata_path}", file=sys.stderr)
|
||||||
|
break
|
||||||
except (json.JSONDecodeError, OSError) as e:
|
except (json.JSONDecodeError, OSError) as e:
|
||||||
print(f"Warning: Failed to load idedata: {e}", file=sys.stderr)
|
print(
|
||||||
|
f"Warning: Failed to load idedata from {idedata_path}: {e}",
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
analyzer = MemoryAnalyzer(elf_path, idedata=idedata)
|
analyzer = MemoryAnalyzer(elf_path, idedata=idedata)
|
||||||
@@ -156,20 +182,26 @@ def main() -> int:
|
|||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--build-dir",
|
"--build-dir",
|
||||||
help="Optional build directory for detailed memory analysis",
|
help="Optional build directory for detailed memory analysis (overrides auto-detection)",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--output-json",
|
"--output-json",
|
||||||
help="Optional path to save detailed analysis JSON",
|
help="Optional path to save detailed analysis JSON",
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--output-build-dir",
|
||||||
|
help="Optional path to write the detected build directory",
|
||||||
|
)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# Read compile output from stdin
|
# Read compile output from stdin
|
||||||
compile_output = sys.stdin.read()
|
compile_output = sys.stdin.read()
|
||||||
|
|
||||||
# Extract memory usage
|
# Extract memory usage and build directory
|
||||||
ram_bytes, flash_bytes = extract_from_compile_output(compile_output)
|
ram_bytes, flash_bytes, detected_build_dir = extract_from_compile_output(
|
||||||
|
compile_output
|
||||||
|
)
|
||||||
|
|
||||||
if ram_bytes is None or flash_bytes is None:
|
if ram_bytes is None or flash_bytes is None:
|
||||||
print("Failed to extract memory usage from compile output", file=sys.stderr)
|
print("Failed to extract memory usage from compile output", file=sys.stderr)
|
||||||
@@ -200,11 +232,24 @@ def main() -> int:
|
|||||||
print(f"Total RAM: {ram_bytes} bytes", file=sys.stderr)
|
print(f"Total RAM: {ram_bytes} bytes", file=sys.stderr)
|
||||||
print(f"Total Flash: {flash_bytes} bytes", file=sys.stderr)
|
print(f"Total Flash: {flash_bytes} bytes", file=sys.stderr)
|
||||||
|
|
||||||
# Run detailed analysis if build directory provided
|
# Determine which build directory to use (explicit arg overrides auto-detection)
|
||||||
|
build_dir = args.build_dir or detected_build_dir
|
||||||
|
|
||||||
|
if detected_build_dir:
|
||||||
|
print(f"Detected build directory: {detected_build_dir}", file=sys.stderr)
|
||||||
|
|
||||||
|
# Write build directory to file if requested
|
||||||
|
if args.output_build_dir and build_dir:
|
||||||
|
build_dir_path = Path(args.output_build_dir)
|
||||||
|
build_dir_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
build_dir_path.write_text(build_dir)
|
||||||
|
print(f"Wrote build directory to {args.output_build_dir}", file=sys.stderr)
|
||||||
|
|
||||||
|
# Run detailed analysis if build directory available
|
||||||
detailed_analysis = None
|
detailed_analysis = None
|
||||||
if args.build_dir:
|
if build_dir:
|
||||||
print(f"Running detailed analysis on {args.build_dir}", file=sys.stderr)
|
print(f"Running detailed analysis on {build_dir}", file=sys.stderr)
|
||||||
detailed_analysis = run_detailed_analysis(args.build_dir)
|
detailed_analysis = run_detailed_analysis(build_dir)
|
||||||
|
|
||||||
# Save JSON output if requested
|
# Save JSON output if requested
|
||||||
if args.output_json:
|
if args.output_json:
|
||||||
|
Reference in New Issue
Block a user