Skip to content
Merged
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
248 changes: 248 additions & 0 deletions .github/ci/release_checker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0

# flake8: noqa

import os
import yaml
import subprocess
from tabulate import tabulate
import re
from datetime import datetime
import wcwidth
from pathlib import Path
import pytz

repo_path = Path(".")

target_dirs = [
os.path.join(repo_path, "bsp"),
os.path.join(repo_path, "components"),
]

deprecated = [
"esp-box",
"esp-box-lite",
"esp32_azure_iot_kit",
"esp32_s2_kaluga_kit",
"hts221",

]

priority_order = {
"⛔ Yes": 0,
"⚠️ MD ": 1,
"✔️ No ": 2
}

results = []

release_commits = {}
component_paths = {}


def run_git_command(args, cwd):
result = subprocess.run(["git"] + args, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
return result.stdout.strip()


for base_dir in target_dirs:
if os.path.exists(base_dir):
for root, dirs, files in os.walk(base_dir):
if "idf_component.yml" in files:
yml_path = os.path.join(root, "idf_component.yml")
component_name = os.path.basename(root)
version = "N/A"
release_date = "?"
changes_since_version = "N/A"
commit_count = "?"

if component_name in deprecated:
continue

try:
with open(yml_path, "r") as f:
yml_data = yaml.safe_load(f)
version = yml_data.get("version", "N/A")
except Exception as e:
print(f"Chyba: {e}")

if version != "N/A":
try:
rel_yml_path = os.path.relpath(yml_path, repo_path).replace("\\", "/")
log_output = run_git_command(["log", "-p", "--", rel_yml_path], cwd=repo_path)

current_commit = None
current_date = None
old_version = None
new_version = None
commit_hash = None

lines = log_output.splitlines()
for i, line in enumerate(lines):
if line.startswith("commit "):
current_commit = line.split()[1]
old_version = None
new_version = None
elif line.startswith("Date:"):
raw_date = line.replace("Date:", "").strip()
try:
dt = datetime.strptime(raw_date, "%a %b %d %H:%M:%S %Y %z")
current_date = dt.strftime("%d.%m.%Y")
except Exception as e:
print(f"Chyba: {e}")
current_date = raw_date
elif line.startswith("-version:") and not line.startswith(" "):
match = re.match(r"-version:\s*['\"]?([\w\.\-~]+)['\"]?", line)
if match:
old_version = match.group(1)
elif line.startswith("+version:") and not line.startswith(" "):
match = re.match(r"\+version:\s*['\"]?([\w\.\-~]+)['\"]?", line)
if match:
new_version = match.group(1)

if old_version and new_version and old_version != new_version:
commit_hash = current_commit
release_date = current_date
break

if not commit_hash:
first_commit = run_git_command(["log", "--diff-filter=A", "--format=%H %aD", "--", rel_yml_path], cwd=repo_path)
if first_commit:
parts = first_commit.split()
commit_hash = parts[0]
try:
dt = datetime.strptime(" ".join(parts[1:]), "%a, %d %b %Y %H:%M:%S %z")
release_date = dt.strftime("%d.%m.%Y")
except Exception as e:
print(f"Chyba: {e}")
release_date = "?"

if commit_hash:
rel_component_path = os.path.relpath(root, repo_path).replace("\\", "/")

# Save
release_commits[component_name] = commit_hash
component_paths[component_name] = rel_component_path

diff_output = run_git_command(["diff", "--name-only", f"{commit_hash}..HEAD", "--", rel_component_path], cwd=repo_path)

extensions = {}
changed_paths = diff_output.splitlines()
if diff_output:
extensions = {os.path.splitext(path)[1] for path in changed_paths}

if extensions == {'.md'}:
changes_since_version = "⚠️ MarkDown "
elif changed_paths and all("test_apps/" in path for path in changed_paths):
changes_since_version = "🧪 Test only"
elif extensions:
changes_since_version = "⛔ Yes"
else:
changes_since_version = "✔️ No "

# count_output = run_git_command(["rev-list", f"{commit_hash}..HEAD", "--count", rel_component_path], cwd=repo_path)
commit_count = len(changed_paths) if changed_paths else "?"

except Exception as e:
print(f"Chyba: {e}")

if release_date != "?":
extension_str = ", ".join(sorted(extensions)) if extensions else " "
results.append([component_name, version, release_date, changes_since_version + f" ({commit_count})", extension_str])


def show_diff_for_component(component_name):
commit_hash = release_commits.get(component_name)
rel_path = component_paths.get(component_name)

if not commit_hash or not rel_path:
print("Commit path not found.")
return

# List of changed files
changed_files = run_git_command(["diff", "--name-only", f"{commit_hash}..HEAD", "--", rel_path], cwd=repo_path)
changed_files = [f for f in changed_files.splitlines() if not f.endswith(".md")]

if not changed_files:
print("No changes except *.md files.")
return

print(f"Changes for component '{component_name}' from last release (except *.md files):\n")
subprocess.run(["git", "diff", "--color=always", f"{commit_hash}..HEAD", "--"] + changed_files, cwd=repo_path)


# Calculate width
def visual_width(text):
return sum(wcwidth.wcwidth(c) for c in text)


# Text align
def pad_visual(text, target_width):
current_width = visual_width(text)
padding = max(0, target_width - current_width)
return text + " " * padding


def get_change_key(row):
change = row[3].strip()
extensions = row[4].split(", ")
has_code_change = any(ext in ['.c', '.h'] for ext in extensions)

if change.startswith("⛔") and has_code_change:
return 0
elif change.startswith("⛔"):
return 1
elif change.startswith("🧪"):
return 2
elif change.startswith("⚠️"):
return 3
elif change.startswith("✔️"):
return 4
return 99


# Sort by priority
results.sort(key=get_change_key)

# Column align
for row in results:
row[3] = pad_visual(row[3], 8)

# Table header
headers = ["Component", "Version", "Released", "Changed", "Files"]

tz = pytz.timezone("Europe/Prague")
last_updated = datetime.now(tz).strftime("%d.%m.%Y %H:%M:%S %Z")
if os.getenv("CI") != "true":
markdown_table = tabulate(results, headers=headers, tablefmt="github")
print("# Component/BSP release version checker")
print("This page shows all components in the BSP repository with their latest versions and indicates whether any changes have not yet been released.")
else:
markdown_table = tabulate(results, headers=headers, tablefmt="html")
deprecated_str = ", ".join(deprecated)
print("<html><head>")
print("<title>Component/BSP release version checker</title>")
print(f"""<style>
body {{ font-family: sans-serif; padding: 2em; }}
table {{ border-collapse: collapse; width: 100%; }}
th, td {{ border: 1px solid #ccc; padding: 0.5em; text-align: left; }}
th {{ background-color: #f0f0f0; }}
td:nth-child(4) {{ text-align: center; }}
td:nth-child(5) {{ font-style: italic; color: #888; }}
</style>""")
print("</head><body>")
print("<h1>Component/BSP release version checker</h1>")
print(f"<p>Last updated: {last_updated}</p>")
print("<p>This page shows all components in the BSP repository with their latest versions and indicates whether any changes have not yet been released.</p>")
print(f"<p>Deprecated components: {deprecated_str}</p>")
print("</body></html>")

print(markdown_table)

if os.getenv("CI") != "true":
while True:
component_name = input("Input the component name for diff (or type 'exit' to quit): ")
if component_name.lower() == 'exit':
break
show_diff_for_component(component_name)
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: "ESP-IDF build examples to github pages (push)"
name: Build examples for Launchpad

on:
push:
Expand Down Expand Up @@ -61,8 +61,6 @@ jobs:
- name: Upload built files to gh pages
uses: actions/upload-pages-artifact@v3
with:
path: binaries/
name: gh-pages-launchpad
path: binaries/

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
35 changes: 35 additions & 0 deletions .github/workflows/deploy_gh_pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Deploy GitHub Pages

on:
workflow_run:
workflows:
- Build examples for Launchpad
- Release Checker
types:
- completed

jobs:
merge-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Download site from launchpad examples
uses: actions/download-artifact@v3
with:
name: gh-pages-launchpad
path: ./combined-site

- name: Download site from release checker
uses: actions/download-artifact@v3
with:
name: gh-pages-release-checker
path: ./combined-site

- name: Upload combined site
uses: actions/upload-pages-artifact@v3
with:
path: ./combined-site

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

43 changes: 43 additions & 0 deletions .github/workflows/release_checker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Release Checker

on:
push:
branches:
- master
workflow_dispatch: # can be run manually


jobs:
build-and-deploy:
runs-on: ubuntu-latest

permissions:
pages: write
id-token: write

environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
fetch-depth: 0 # all git history

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Run release_checker.py
run: |
pip install requests pyyaml tabulate wcwidth pytz
mkdir site
python .github/ci/release_checker.py > site/release_checker.html

- name: Upload file to gh pages
uses: actions/upload-pages-artifact@v3
with:
name: gh-pages-release-checker
path: site
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@

# ESP-BSP: Espressif's Board Support Packages

| [HOW TO USE](docu/how_to_use.md) | [BOARDS](#supported-boards) | [EXAMPLES](#examples) | [CONTRIBUTING](docu/CONTRIBUTING.md) | [LVGL port](components/esp_lvgl_port) | [LCD drivers](docu/LCD.md) |
| :---------------------------------------: | :-------------------------: | :-------------------: | :--------------: | :-----------------------------------: | :------------------------: |
| [HOW TO USE](docu/how_to_use.md) | [BOARDS](#supported-boards) | [EXAMPLES](#examples) | [CONTRIBUTING](docu/CONTRIBUTING.md) | [LVGL port](components/esp_lvgl_port) | [LCD drivers](docu/LCD.md) | [Releases](https://espressif.github.io/esp-bsp/release_checker.html) |
| :---------------------------------------: | :-------------------------: | :-------------------: | :--------------: | :-----------------------------------: | :------------------------: | :------------------------: |

This repository provides **Board Support Packages (BSPs)** for various Espressif and M5Stack development boards. Written in **C**, each BSP offers a **unified and consistent API** to simplify the initialization and use of common onboard peripherals such as **displays, touch panels, audio codecs, SD cards, and selected sensors.** The goal is to streamline development and reduce hardware-specific boilerplate, enabling faster prototyping and cleaner application code.

Expand Down
Loading