Skip to content
Draft
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
62 changes: 28 additions & 34 deletions .github/actions/enhanced-diff/check_changes.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,7 @@
def run_git_command(cmd):
"""Run a git command and return the output."""
try:
result = subprocess.run(
cmd,
shell=True,
capture_output=True,
text=True,
check=True
)
result = subprocess.run(cmd, shell=True, capture_output=True, text=True, check=True)
return result.stdout.strip()
except subprocess.CalledProcessError as e:
print(f"Error running git command '{cmd}': {e}", file=sys.stderr)
Expand All @@ -34,61 +28,61 @@ def get_changed_files():
output = run_git_command("git status --porcelain")
if not output:
return []

changed_files = []
for line in output.split('\n'):
for line in output.split("\n"):
if line.strip():
# Extract filename from git status output (remove status indicators)
filename = line[3:].strip() # Skip the first 3 characters (status indicators and space)
changed_files.append(filename)

return changed_files


def categorize_files(files):
"""Categorize files into JSON and non-JSON files."""
json_files = []
non_json_files = []

for file in files:
if file.lower().endswith('.json'):
if file.lower().endswith(".json"):
json_files.append(file)
else:
non_json_files.append(file)

return json_files, non_json_files


def set_github_output(key, value):
"""Set GitHub Actions output variable."""
github_output = os.getenv('GITHUB_OUTPUT')
github_output = os.getenv("GITHUB_OUTPUT")
if github_output:
with open(github_output, 'a', encoding='utf-8') as f:
with open(github_output, "a", encoding="utf-8") as f:
f.write(f"{key}={value}\n")
else:
print(f"::set-output name={key}::{value}")


def set_github_summary(content):
"""Set GitHub Actions step summary."""
github_step_summary = os.getenv('GITHUB_STEP_SUMMARY')
github_step_summary = os.getenv("GITHUB_STEP_SUMMARY")
if github_step_summary:
with open(github_step_summary, 'a', encoding='utf-8') as f:
with open(github_step_summary, "a", encoding="utf-8") as f:
f.write(f"{content}\n")


def main():
"""Main function to check for changes and determine commit behavior."""
verbose = os.getenv('VERBOSE', 'false').lower() in ('true', '1', 'yes')
verbose = os.getenv("VERBOSE", "false").lower() in ("true", "1", "yes")

if verbose:
print("::group::Enhanced diff check")
print(f"Current working directory: {os.getcwd()}")

# Get all changed files
changed_files = get_changed_files()
total_count = len(changed_files)

if total_count == 0:
if verbose:
print("No changes detected.")
Expand All @@ -99,39 +93,39 @@ def main():
if verbose:
print("::endgroup::")
return

# Categorize files
json_files, non_json_files = categorize_files(changed_files)
json_count = len(json_files)
non_json_count = len(non_json_files)

# Decision logic: commit only if there are non-JSON file changes
should_commit = non_json_count > 0

# Set outputs
set_github_output("changed", "true" if should_commit else "false")
set_github_output("count", str(total_count))
set_github_output("json_count", str(json_count))
set_github_output("non_json_count", str(non_json_count))

# Create summary
if should_commit:
summary_content = f"### Detected {total_count} changed files - Commit will proceed :rocket:\n"
summary_content += f"- Non-JSON files: {non_json_count} (triggers commit)\n"
summary_content += f"- JSON files: {json_count} (included in commit)\n\n"

if non_json_files:
summary_content += "**Non-JSON files changed:**\n"
for file in non_json_files:
summary_content += f"- {file}\n"

if json_files:
summary_content += "\n**JSON files changed (included in commit):**\n"
for file in json_files:
summary_content += f"- {file}\n"

set_github_summary(summary_content)

if verbose:
print(f"### Commit will proceed - {non_json_count} non-JSON file(s) changed")
print("Non-JSON files:")
Expand All @@ -141,26 +135,26 @@ def main():
print("JSON files (included in commit):")
for file in json_files:
print(f" - {file}")

else:
summary_content = f"### Detected {total_count} changed files - No commit needed\n"
summary_content += f"- Only JSON files changed: {json_count}\n"
summary_content += "- Non-JSON files: 0 (commit not triggered)\n\n"
summary_content += "**JSON files changed (commit skipped):**\n"
for file in json_files:
summary_content += f"- {file}\n"

set_github_summary(summary_content)

if verbose:
print(f"### No commit needed - only {json_count} JSON file(s) changed")
print("JSON files (no commit triggered):")
for file in json_files:
print(f" - {file}")

if verbose:
print("::endgroup::")


if __name__ == "__main__":
main()
main()
65 changes: 24 additions & 41 deletions .github/actions/enhanced-diff/test_enhanced_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,46 +20,46 @@
def test_categorize_files():
"""Test the file categorization logic."""
print("Testing file categorization...")

# Test case 1: Mixed files
files = ["stub.py", "config.json", "module.pyi", "data.json", "README.md"]
json_files, non_json_files = categorize_files(files)

expected_json = ["config.json", "data.json"]
expected_non_json = ["stub.py", "module.pyi", "README.md"]

assert json_files == expected_json, f"Expected {expected_json}, got {json_files}"
assert non_json_files == expected_non_json, f"Expected {expected_non_json}, got {non_json_files}"
print("✓ Mixed files test passed")

# Test case 2: Only JSON files
files = ["config.json", "package.json"]
json_files, non_json_files = categorize_files(files)

assert json_files == ["config.json", "package.json"]
assert non_json_files == []
print("✓ JSON-only files test passed")

# Test case 3: Only non-JSON files
files = ["main.py", "utils.py", "README.md"]
json_files, non_json_files = categorize_files(files)

assert json_files == []
assert non_json_files == ["main.py", "utils.py", "README.md"]
print("✓ Non-JSON-only files test passed")

# Test case 4: Empty list
files = []
json_files, non_json_files = categorize_files(files)

assert json_files == []
assert non_json_files == []
print("✓ Empty files test passed")

# Test case 5: Case insensitive JSON detection
files = ["CONFIG.JSON", "data.Json", "mixed.JSON"]
json_files, non_json_files = categorize_files(files)

assert json_files == ["CONFIG.JSON", "data.Json", "mixed.JSON"]
assert non_json_files == []
print("✓ Case insensitive JSON test passed")
Expand All @@ -68,50 +68,33 @@ def test_categorize_files():
def simulate_git_status_scenarios():
"""Simulate different git status scenarios to show decision logic."""
print("\nSimulating different change scenarios...")

scenarios = [
{
"name": "Only JSON files changed",
"files": ["config.json", "package.json"],
"should_commit": False
},
{
"name": "Only non-JSON files changed",
"files": ["main.py", "README.md"],
"should_commit": True
},
{
"name": "Mixed files changed",
"files": ["main.py", "config.json", "utils.py"],
"should_commit": True
},
{
"name": "No files changed",
"files": [],
"should_commit": False
}
{"name": "Only JSON files changed", "files": ["config.json", "package.json"], "should_commit": False},
{"name": "Only non-JSON files changed", "files": ["main.py", "README.md"], "should_commit": True},
{"name": "Mixed files changed", "files": ["main.py", "config.json", "utils.py"], "should_commit": True},
{"name": "No files changed", "files": [], "should_commit": False},
]

for scenario in scenarios:
print(f"\nScenario: {scenario['name']}")
files = scenario['files']
files = scenario["files"]
json_files, non_json_files = categorize_files(files)

should_commit = len(non_json_files) > 0

print(f" Files: {files}")
print(f" JSON files: {json_files}")
print(f" Non-JSON files: {non_json_files}")
print(f" Should commit: {should_commit}")

assert should_commit == scenario['should_commit'], \
f"Expected should_commit={scenario['should_commit']}, got {should_commit}"

assert should_commit == scenario["should_commit"], f"Expected should_commit={scenario['should_commit']}, got {should_commit}"
print(" ✓ Decision logic correct")


if __name__ == "__main__":
print("Running enhanced diff checker tests...\n")

try:
test_categorize_files()
simulate_git_status_scenarios()
Expand All @@ -121,4 +104,4 @@ def simulate_git_status_scenarios():
sys.exit(1)
except Exception as e:
print(f"\n💥 Unexpected error: {e}")
sys.exit(1)
sys.exit(1)
23 changes: 13 additions & 10 deletions .github/actions/get-mpversions/list_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
The module also includes a main block that generates a matrix of versions based on command-line arguments and environment variables.
The matrix is printed as JSON and can be optionally written to a file if running in a GitHub Actions workflow.
"""

import argparse
import json
import os
Expand All @@ -17,9 +18,10 @@

# Token with no permissions to avoid throttling
# https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2022-11-28#getting-a-higher-rate-limit
PAT_NO_ACCESS = "github_pat_"+"11AAHPVFQ0G4NTaQ73Bw5J"+"_fAp7K9sZ1qL8VFnI9g78eUlCdmOXHB3WzSdj2jtEYb4XF3N7PDJBl32qIxq"
PAT_NO_ACCESS = "github_pat_" + "11AAHPVFQ0G4NTaQ73Bw5J" + "_fAp7K9sZ1qL8VFnI9g78eUlCdmOXHB3WzSdj2jtEYb4XF3N7PDJBl32qIxq"
PAT = os.environ.get("GITHUB_TOKEN") or PAT_NO_ACCESS


@lru_cache()
def micropython_versions(start="v1.10"):
g = Github(auth=Auth.Token(PAT))
Expand All @@ -32,6 +34,7 @@ def micropython_versions(start="v1.10"):
tags = ["preview", "stable"]
return tags


def major_minor(versions):
"""create a list of the most recent version for each major.minor"""
mm_groups = {}
Expand All @@ -45,11 +48,12 @@ def major_minor(versions):
mm_groups[major_minor].append(v)
return [max(v) for v in mm_groups.values()]


def main():
matrix = {}

parser = argparse.ArgumentParser()
parser.add_argument("--stable", "--latest","-s", action=argparse.BooleanOptionalAction,default=True, help="Add latest version")
parser.add_argument("--stable", "--latest", "-s", action=argparse.BooleanOptionalAction, default=True, help="Add latest version")
parser.add_argument("--preview", "-p", action=argparse.BooleanOptionalAction, default=False, help="Add preview version")
parser.add_argument("--max", "-m", type=int, default=3, help="Maximum number of versions")

Expand All @@ -58,24 +62,23 @@ def main():
# only run latests when running in ACT locally for testing
if os.environ.get("ACT"):
args.max = 1
matrix["version"] = major_minor(micropython_versions(start="v1.20"))[1:args.max]

matrix["version"] = major_minor(micropython_versions(start="v1.20"))[1 : args.max]

# print(args)
if args.stable:
matrix["version"].insert(0, "stable")
if args.preview:
matrix["version"].insert(0, "preview")
matrix["version"]=matrix["version"][:args.max]
matrix["version"] = matrix["version"][: args.max]
# GITHUB_OUTPUT is set by github actions
if os.getenv('GITHUB_OUTPUT'):
with open(os.getenv('GITHUB_OUTPUT'), 'a') as file: # type: ignore
if os.getenv("GITHUB_OUTPUT"):
with open(os.getenv("GITHUB_OUTPUT"), "a") as file: # type: ignore
file.write(f"versions={json.dumps(matrix)}\n")
file.write(f'mp_versions={json.dumps(matrix["version"])}\n')
file.write(f"mp_versions={json.dumps(matrix['version'])}\n")
else:
print(json.dumps(matrix, indent=4))


# sourcery skip: assign-if-exp, merge-dict-assign
if __name__ == "__main__":
main()

Loading
Loading