mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
misc/github: Post firmware stats after PRs.
This commit is contained in:
parent
a110f5c478
commit
c77ef7f96a
61
.github/workflows/firmware.yml
vendored
61
.github/workflows/firmware.yml
vendored
@ -65,13 +65,72 @@ jobs:
|
||||
run: source tools/ci.sh && ci_build_target ${{ matrix.target }}
|
||||
|
||||
- name: '⬆ Upload artifacts'
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.target }}
|
||||
path: ${{ matrix.target }}
|
||||
if-no-files-found: error
|
||||
|
||||
post-stats:
|
||||
needs: build-firmware
|
||||
runs-on: ubuntu-22.04
|
||||
if: github.event_name == 'pull_request'
|
||||
steps:
|
||||
- name: '⏳ Checkout repository'
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: false
|
||||
|
||||
- name: '♻ Caching dependencies'
|
||||
uses: actions/cache@v4.0.2
|
||||
id: cache
|
||||
with:
|
||||
path: ~/cache/gcc
|
||||
key: 'arm-gnu-toolchain-13.2.rel1'
|
||||
|
||||
- name: '🐍 Install Python'
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
cache: 'pip'
|
||||
python-version: "3.12.4"
|
||||
|
||||
- name: '🛠 Install dependencies'
|
||||
run: |
|
||||
pip install tabulate==0.9.0
|
||||
|
||||
- name: '🤌 Download artifacts'
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: new_firmware
|
||||
merge-multiple: false
|
||||
|
||||
- name: '🤌 Download release'
|
||||
uses: robinraju/release-downloader@v1
|
||||
with:
|
||||
repository: 'openmv/openmv'
|
||||
tag: 'development'
|
||||
fileName: '*.zip'
|
||||
extract: false
|
||||
out-file-path: 'old_firmware'
|
||||
|
||||
- name: '📝 Generate report'
|
||||
run: |
|
||||
TOOLCHAIN_PATH=${HOME}/cache/gcc
|
||||
export PATH=${TOOLCHAIN_PATH}/bin:${PATH}
|
||||
python tools/gen_stats.py > ${GITHUB_WORKSPACE}/stats.txt
|
||||
cat ${GITHUB_WORKSPACE}/stats.txt
|
||||
if [ -s ./stats.txt ]; then
|
||||
echo "report=true" >> $GITHUB_ENV
|
||||
else
|
||||
echo "report=false" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: '📝 Post report'
|
||||
if: env.report == 'true'
|
||||
uses: thollander/actions-comment-pull-request@v2
|
||||
with:
|
||||
filePath: ./stats.txt
|
||||
|
||||
stable-release:
|
||||
needs: build-firmware
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
1
.github/workflows/requirements.txt
vendored
1
.github/workflows/requirements.txt
vendored
@ -1,3 +1,4 @@
|
||||
flake8==6.0.0
|
||||
pytest==7.4.0
|
||||
ethos-u-vela==3.12.0
|
||||
tabulate==0.9.0
|
||||
|
||||
108
tools/gen_stats.py
Normal file
108
tools/gen_stats.py
Normal file
@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env python
|
||||
# This file is part of the OpenMV project.
|
||||
#
|
||||
# Copyright (c) 2024 Ibrahim Abdelkader <iabdalkader@openmv.io>
|
||||
# Copyright (c) 2024 Kwabena W. Agyeman <kwagyeman@openmv.io>
|
||||
#
|
||||
# This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
import os
|
||||
import sys
|
||||
import zipfile
|
||||
import subprocess
|
||||
from operator import itemgetter
|
||||
from tabulate import tabulate
|
||||
|
||||
|
||||
def extract_zip_files(directory):
|
||||
for item in os.listdir(directory):
|
||||
if item.endswith(".zip"):
|
||||
with zipfile.ZipFile(os.path.join(directory, item), "r") as zip_ref:
|
||||
name = os.path.splitext(item.strip())[0].split("firmware_")[1]
|
||||
extract_directory = os.path.join(directory, name)
|
||||
if not os.path.exists(extract_directory):
|
||||
os.makedirs(extract_directory)
|
||||
zip_ref.extractall(extract_directory)
|
||||
|
||||
|
||||
def find_elf_files(directory):
|
||||
elf_files = []
|
||||
for root, _, files in os.walk(directory):
|
||||
for file in files:
|
||||
if file.endswith(".elf"):
|
||||
elf_files.append(os.path.join(root, file))
|
||||
return elf_files
|
||||
|
||||
|
||||
def get_relative_path(full_path, base_dir):
|
||||
return os.path.relpath(full_path, base_dir)
|
||||
|
||||
|
||||
def get_firmware_sizes(path):
|
||||
try:
|
||||
output = subprocess.check_output(["arm-none-eabi-size", path], text=True)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(e.stderr, file=sys.stderr)
|
||||
raise e
|
||||
return [int(s) for s in output.split() if s.isdigit()][0:3]
|
||||
|
||||
|
||||
def main():
|
||||
new_firmware_dir = "new_firmware"
|
||||
old_firmware_dir = "old_firmware"
|
||||
|
||||
# Extract zip files
|
||||
extract_zip_files(old_firmware_dir)
|
||||
extract_zip_files(new_firmware_dir)
|
||||
|
||||
# Find ELF files and their relative paths
|
||||
new_elf_files = find_elf_files(new_firmware_dir)
|
||||
old_elf_files = find_elf_files(old_firmware_dir)
|
||||
|
||||
new_elf_paths = { get_relative_path(path, new_firmware_dir): path for path in new_elf_files }
|
||||
old_elf_paths = { get_relative_path(path, old_firmware_dir): path for path in old_elf_files }
|
||||
|
||||
# Find common ELF files based on relative paths
|
||||
common_paths = set(new_elf_paths.keys()).intersection(old_elf_paths.keys())
|
||||
# List of common ELF files with their paths
|
||||
common_elf_files = [(new_elf_paths[rel_path], old_elf_paths[rel_path]) for rel_path in common_paths]
|
||||
common_elf_files = sorted(common_elf_files, key=lambda x: x[0].split(os.sep)[1])
|
||||
|
||||
# Prepare the header
|
||||
headers = ["Firmware", "Text Diff", "Data Diff", "BSS Diff"]
|
||||
|
||||
# Prepare the data
|
||||
data = []
|
||||
for new_path, old_path in common_elf_files:
|
||||
new_sizes = get_firmware_sizes(new_path)
|
||||
old_sizes = get_firmware_sizes(old_path)
|
||||
|
||||
text_diff = new_sizes[0] - old_sizes[0]
|
||||
data_diff = new_sizes[1] - old_sizes[1]
|
||||
bss_diff = new_sizes[2] - old_sizes[2]
|
||||
|
||||
if not any([text_diff, data_diff, bss_diff]):
|
||||
continue
|
||||
|
||||
text_percent = (((new_sizes[0] - old_sizes[0]) / old_sizes[0]) * 100 if old_sizes[0] != 0 else 0)
|
||||
data_percent = (((new_sizes[1] - old_sizes[1]) / old_sizes[1]) * 100 if old_sizes[1] != 0 else 0)
|
||||
bss_percent = (((new_sizes[2] - old_sizes[2]) / old_sizes[2]) * 100 if old_sizes[2] != 0 else 0)
|
||||
|
||||
text_emoji = "🔺" if text_percent > 0 else "🔻" if text_percent < 0 else "➖"
|
||||
data_emoji = "🔺" if data_percent > 0 else "🔻" if data_percent < 0 else "➖"
|
||||
bss_emoji = "🔺" if bss_percent > 0 else "🔻" if bss_percent < 0 else "➖"
|
||||
|
||||
text_diff_str = f"{text_emoji}{text_percent:.2f}% ({text_diff:+})"
|
||||
data_diff_str = f"{data_emoji}{data_percent:.2f}% ({data_diff:+})"
|
||||
bss_diff_str = f"{bss_emoji}{bss_percent:.2f}% ({bss_diff:+})"
|
||||
|
||||
board_name = "_".join(old_path.split(os.sep)[1].split("_")[0:3])
|
||||
file_name = os.sep.join([board_name, old_path.split(os.sep)[-1]])
|
||||
data.append([file_name, text_diff_str, data_diff_str, bss_diff_str])
|
||||
|
||||
if data:
|
||||
# Print the table
|
||||
print("Code Size Report:")
|
||||
print(tabulate(data, headers=headers, tablefmt="github", colalign=("left", "left", "left", "left")))
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Loading…
Reference in New Issue
Block a user