Skip to content

Commit 466b932

Browse files
committed
Merge branch 'ci/post_memory_numbers' into 'main'
.gitlab-ci.yml: Post the build numbers on gitlab MR See merge request app-frameworks/esp-matter!992
2 parents f89603b + f8b1d24 commit 466b932

File tree

3 files changed

+145
-0
lines changed

3 files changed

+145
-0
lines changed

.gitlab-ci.yml

+14
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,12 @@ build_esp_matter_examples_pytest_H2_idf_v5_1:
297297
- cd ${ESP_MATTER_PATH}
298298
- pip install -r tools/ci/requirements-build.txt
299299
- python tools/ci/build_apps.py ./examples --pytest_h2
300+
- |
301+
if [ "$CI_PIPELINE_SOURCE" == "merge_request_event" ]; then
302+
python tools/ci/post_results.py --chip esp32h2 --job_name "build_esp_matter_examples_pytest_H2_idf_v5_1" --ref_map_file light_mr_base.map --example "light"
303+
else
304+
echo "Not a Merge Request pipeline. Skipping post_results.py."
305+
fi
300306
301307
build_esp_matter_examples_pytest_C2_idf_v5_1:
302308
extends:
@@ -319,7 +325,14 @@ build_esp_matter_examples_pytest_C2_idf_v5_1:
319325
script:
320326
- cd ${ESP_MATTER_PATH}
321327
- pip install -r tools/ci/requirements-build.txt
328+
- echo "${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA}"
322329
- python tools/ci/build_apps.py ./examples --pytest_c2
330+
- |
331+
if [ "$CI_PIPELINE_SOURCE" == "merge_request_event" ]; then
332+
python tools/ci/post_results.py --chip esp32c2 --job_name "build_esp_matter_examples_pytest_C2_idf_v5_1" --ref_map_file light_mr_base.map --example "light"
333+
else
334+
echo "Not a Merge Request pipeline. Skipping post_results.py."
335+
fi
323336
324337
build_ext_plat_c6_thread_controller_examples:
325338
extends:
@@ -344,6 +357,7 @@ build_esp_matter_examples:
344357
- "examples/**/build*/size.json"
345358
- "examples/**/build*/build_log.txt"
346359
- "examples/**/build*/*.bin"
360+
- "examples/**/build*/*.map"
347361
- "examples/**/build*/flasher_args.json"
348362
- "examples/**/build*/config/sdkconfig.json"
349363
- "examples/**/build*/bootloader/*.bin"

tools/ci/post_results.py

+129
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
2+
3+
# SPDX-License-Identifier: CC0-1.0
4+
5+
import os
6+
import subprocess
7+
import requests
8+
import glob
9+
import argparse
10+
import logging
11+
12+
# Gitlab Configurations
13+
gitlab_api_url = os.getenv("CI_API_V4_URL")
14+
gitlab_token = os.getenv("GITLAB_MR_COMMENT_TOKEN")
15+
ci_project_id = os.getenv("CI_PROJECT_ID")
16+
ci_merge_request_iid = os.getenv("CI_MERGE_REQUEST_IID")
17+
18+
# Fetch the id of the pipeline for a branch with the specified commit id (default main branch)
19+
def fetch_pipeline_for_commit(commit_sha, branch_name="main"):
20+
url = f"{gitlab_api_url}/projects/{ci_project_id}/pipelines"
21+
headers = {"PRIVATE-TOKEN": gitlab_token}
22+
params = {"ref": branch_name, "sha": commit_sha}
23+
response = requests.get(url, headers=headers, params=params)
24+
response.raise_for_status()
25+
pipelines = response.json()
26+
if not pipelines:
27+
raise ValueError(f"No pipeline found for commit: {commit_sha} on branch: {branch_name}")
28+
return pipelines[0]['id']
29+
30+
# Fetch the versions for the gitlab MR.
31+
def fetch_merge_request_diff_versions():
32+
url = f"{gitlab_api_url}/projects/{ci_project_id}/merge_requests/{ci_merge_request_iid}/versions"
33+
headers = {"PRIVATE-TOKEN": gitlab_token}
34+
response = requests.get(url, headers=headers)
35+
response.raise_for_status()
36+
return response.json()
37+
38+
# Fetch the jobs specific to a pipeline id.
39+
def fetch_pipeline_jobs(pipeline_id):
40+
url = f"{gitlab_api_url}/projects/{ci_project_id}/pipelines/{pipeline_id}/jobs"
41+
headers = {"PRIVATE-TOKEN": gitlab_token}
42+
response = requests.get(url, headers=headers)
43+
response.raise_for_status()
44+
return response.json()
45+
46+
# Download the reference map file for the MR base commit.
47+
def download_ref_map_file(chip_name, job_id, output_file):
48+
ref_artifact_path = f"examples/light/build_{chip_name}_default/light.map"
49+
url = f"{gitlab_api_url}/projects/{ci_project_id}/jobs/{job_id}/artifacts/{ref_artifact_path}"
50+
headers = {"PRIVATE-TOKEN": gitlab_token}
51+
with requests.get(url, headers=headers, stream=True) as response:
52+
response.raise_for_status()
53+
with open(output_file, 'wb') as f:
54+
for chunk in response.iter_content(chunk_size=8192):
55+
f.write(chunk)
56+
57+
# Locate the map file artifact for the current pipeline.
58+
def locate_current_map_file(example):
59+
pattern = f"examples/{example}/build*/{example}.map"
60+
artifact_file_paths = glob.glob(pattern, recursive=True)
61+
if not artifact_file_paths:
62+
raise FileNotFoundError("No map file found!")
63+
return artifact_file_paths[0]
64+
65+
# Execute esp_idf_size diff command to find increase/decrease in firmware size.
66+
def execute_idf_size_command(old_file_path, new_file_path):
67+
try:
68+
result = subprocess.run(
69+
["python", "-m", "esp_idf_size", "--diff", old_file_path, new_file_path],
70+
capture_output=True,
71+
text=True,
72+
check=True,
73+
)
74+
return result.stdout
75+
except subprocess.CalledProcessError as e:
76+
raise
77+
78+
# Post the results to gitlab MR.
79+
def post_results_to_gitlab_mr(output, chip_name, example):
80+
if not all([gitlab_api_url, gitlab_token, ci_project_id, ci_merge_request_iid]):
81+
print("Missing required environment variables. Results not posted.")
82+
return
83+
84+
markdown_output = f"<details open><summary><b>Static Memory Footprint for target: {chip_name}, example: {example}</b></summary>\n\n```\n{output}\n```\n</details>"
85+
url = f"{gitlab_api_url}/projects/{ci_project_id}/merge_requests/{ci_merge_request_iid}/notes"
86+
headers = {"PRIVATE-TOKEN": gitlab_token}
87+
data = {"body": markdown_output}
88+
response = requests.post(url, headers=headers, json=data)
89+
if response.status_code == 201:
90+
print("Successfully posted results to GitLab MR.")
91+
else:
92+
print("Failed to post results to GitLab MR.")
93+
94+
def main():
95+
96+
logging.basicConfig(level=logging.WARNING, format="%(asctime)s - %(levelname)s - %(message)s")
97+
parser = argparse.ArgumentParser(description="Process build results and post to GitLab.")
98+
parser.add_argument("--chip", required=True, help="Specify the chip name (e.g., C2, H2)")
99+
parser.add_argument("--ref_map_file", required=True, help="Specify the reference main branch map file")
100+
parser.add_argument("--job_name", required=True, help = "Specify the job name for the job id search")
101+
parser.add_argument("--example", required=True, help = "Specify the example name for the memory footprint")
102+
args = parser.parse_args()
103+
104+
try:
105+
diff_versions = fetch_merge_request_diff_versions()
106+
base_version = diff_versions[0]
107+
base_commit_sha = base_version["base_commit_sha"]
108+
109+
base_commit_pipeline_id = fetch_pipeline_for_commit(base_commit_sha, branch_name="main")
110+
jobs = fetch_pipeline_jobs(base_commit_pipeline_id)
111+
112+
target_job_id = next((job["id"] for job in jobs if job["name"] == args.job_name), None)
113+
if not target_job_id:
114+
raise ValueError("Target job not found.")
115+
116+
download_ref_map_file(args.chip, target_job_id, args.ref_map_file)
117+
current_map_file = locate_current_map_file(args.example)
118+
119+
size_diff_output = execute_idf_size_command(args.ref_map_file, current_map_file)
120+
post_results_to_gitlab_mr(size_diff_output, args.chip, args.example)
121+
except FileNotFoundError as e:
122+
logging.error(f"Error occurred while posting results to GitLab MR: File not found {e}")
123+
except Exception as e:
124+
logging.error(f"Error occurred while posting results to GitLab MR: An Unexpected error occurred:{e}")
125+
126+
if __name__ == "__main__":
127+
main()
128+
129+

tools/ci/requirements-build.txt

+2
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
idf_build_apps
2+
requests
3+
argparse

0 commit comments

Comments
 (0)