lint fixes
Some checks failed
Continuous Integration / Code Formatting (pull_request) Successful in 27s
Continuous Integration / Code Quality Check (pull_request) Successful in 29s
Continuous Integration / Test Execution (pull_request) Failing after 33s
Continuous Integration / CI Summary (pull_request) Failing after 5s
Some checks failed
Continuous Integration / Code Formatting (pull_request) Successful in 27s
Continuous Integration / Code Quality Check (pull_request) Successful in 29s
Continuous Integration / Test Execution (pull_request) Failing after 33s
Continuous Integration / CI Summary (pull_request) Failing after 5s
This commit is contained in:
622
tools/run_development.py
Normal file
622
tools/run_development.py
Normal file
@@ -0,0 +1,622 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Development workflow runner for the Skelly Godot project.
|
||||
|
||||
Runs code quality checks (linting, formatting, testing) individually or together.
|
||||
Provides colored output and error reporting.
|
||||
|
||||
Usage examples:
|
||||
python tools/run_development.py # Run all steps
|
||||
python tools/run_development.py --lint # Only linting
|
||||
python tools/run_development.py --steps lint test # Custom workflow
|
||||
|
||||
NOTE: Handles "successful but noisy" linter output such as
|
||||
"Success: no problems found" - treats these as clean instead of warnings.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import warnings
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Tuple
|
||||
|
||||
# Suppress pkg_resources deprecation warning from gdtoolkit
|
||||
warnings.filterwarnings("ignore", message="pkg_resources is deprecated", category=UserWarning)
|
||||
|
||||
|
||||
class Colors:
|
||||
"""ANSI color codes for terminal output."""
|
||||
# Basic colors
|
||||
RED = '\033[91m'
|
||||
GREEN = '\033[92m'
|
||||
YELLOW = '\033[93m'
|
||||
BLUE = '\033[94m'
|
||||
MAGENTA = '\033[95m'
|
||||
CYAN = '\033[96m'
|
||||
WHITE = '\033[97m'
|
||||
|
||||
# Styles
|
||||
BOLD = '\033[1m'
|
||||
UNDERLINE = '\033[4m'
|
||||
|
||||
# Reset
|
||||
RESET = '\033[0m'
|
||||
|
||||
@staticmethod
|
||||
def colorize(text: str, color: str) -> str:
|
||||
"""Add color to text if terminal supports it."""
|
||||
if os.getenv('NO_COLOR') or not sys.stdout.isatty():
|
||||
return text
|
||||
return f"{color}{text}{Colors.RESET}"
|
||||
|
||||
|
||||
def print_header(title: str) -> None:
|
||||
"""Print a formatted header."""
|
||||
separator = Colors.colorize("=" * 48, Colors.CYAN)
|
||||
colored_title = Colors.colorize(title, Colors.BOLD + Colors.WHITE)
|
||||
print(separator)
|
||||
print(colored_title)
|
||||
print(separator)
|
||||
print()
|
||||
|
||||
|
||||
def print_summary(title: str, stats: Dict[str, int]) -> None:
|
||||
"""Print a formatted summary."""
|
||||
separator = Colors.colorize("=" * 48, Colors.CYAN)
|
||||
colored_title = Colors.colorize(title, Colors.BOLD + Colors.WHITE)
|
||||
print(separator)
|
||||
print(colored_title)
|
||||
print(separator)
|
||||
for key, value in stats.items():
|
||||
colored_key = Colors.colorize(key, Colors.BLUE)
|
||||
colored_value = Colors.colorize(str(value), Colors.BOLD + Colors.WHITE)
|
||||
print(f"{colored_key}: {colored_value}")
|
||||
|
||||
|
||||
def run_command(cmd: List[str], cwd: Path, timeout: int = 30) -> subprocess.CompletedProcess:
|
||||
"""
|
||||
Execute a shell command with error handling and output filtering.
|
||||
|
||||
Filters out gdtoolkit's pkg_resources deprecation warnings.
|
||||
|
||||
Args:
|
||||
cmd: Command and arguments to execute
|
||||
cwd: Working directory for command execution
|
||||
timeout: Maximum execution time in seconds (default: 30s)
|
||||
|
||||
Returns:
|
||||
CompletedProcess with filtered stdout/stderr
|
||||
"""
|
||||
# Suppress pkg_resources deprecation warnings in subprocesses
|
||||
env = os.environ.copy()
|
||||
env['PYTHONWARNINGS'] = 'ignore::UserWarning:pkg_resources'
|
||||
result = subprocess.run(cmd, capture_output=True, text=True, cwd=cwd, timeout=timeout, env=env)
|
||||
|
||||
# Filter out pkg_resources deprecation warnings from the output
|
||||
def filter_warnings(text: str) -> str:
|
||||
if not text:
|
||||
return text
|
||||
lines = text.split('\n')
|
||||
filtered_lines = []
|
||||
skip_next = False
|
||||
|
||||
for line in lines:
|
||||
if skip_next:
|
||||
skip_next = False
|
||||
continue
|
||||
if 'pkg_resources is deprecated' in line:
|
||||
skip_next = True # Skip the next line which contains "import pkg_resources"
|
||||
continue
|
||||
if 'import pkg_resources' in line:
|
||||
continue
|
||||
filtered_lines.append(line)
|
||||
|
||||
return '\n'.join(filtered_lines)
|
||||
|
||||
# Create a new result with filtered output
|
||||
result.stdout = filter_warnings(result.stdout)
|
||||
result.stderr = filter_warnings(result.stderr)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def should_skip_file(file_path: Path) -> bool:
|
||||
"""Check if file should be skipped."""
|
||||
return file_path.name == "TestHelper.gd"
|
||||
|
||||
|
||||
def print_skip_message(tool: str) -> None:
|
||||
"""Print skip message for TestHelper.gd."""
|
||||
message = f"⚠️ Skipped (static var syntax not supported by {tool})"
|
||||
colored_message = Colors.colorize(message, Colors.YELLOW)
|
||||
print(f" {colored_message}")
|
||||
|
||||
|
||||
def print_result(success: bool, output: str = "") -> None:
|
||||
"""Print command result."""
|
||||
if success:
|
||||
if not output:
|
||||
message = "✅ Clean"
|
||||
colored_message = Colors.colorize(message, Colors.GREEN)
|
||||
else:
|
||||
message = "⚠️ WARNINGS found:"
|
||||
colored_message = Colors.colorize(message, Colors.YELLOW)
|
||||
print(f" {colored_message}")
|
||||
if output:
|
||||
# Indent and color the output
|
||||
for line in output.split('\n'):
|
||||
if line.strip():
|
||||
colored_line = Colors.colorize(line, Colors.YELLOW)
|
||||
print(f" {colored_line}")
|
||||
else:
|
||||
message = "❌ ERRORS found:"
|
||||
colored_message = Colors.colorize(message, Colors.RED)
|
||||
print(f" {colored_message}")
|
||||
if output:
|
||||
# Indent and color the output
|
||||
for line in output.split('\n'):
|
||||
if line.strip():
|
||||
colored_line = Colors.colorize(line, Colors.RED)
|
||||
print(f" {colored_line}")
|
||||
|
||||
|
||||
def get_gd_files(project_root: Path) -> List[Path]:
|
||||
"""Get all .gd files in the project."""
|
||||
return list(project_root.rglob("*.gd"))
|
||||
|
||||
|
||||
def format_test_name(filename: str) -> str:
|
||||
"""Convert test_filename to readable test name."""
|
||||
return filename.replace("test_", "").replace("_", " ")
|
||||
|
||||
|
||||
def _is_successful_linter_output(output: str) -> bool:
|
||||
"""Interpret noisy but-successful linter output as clean.
|
||||
|
||||
Some linters print friendly messages even when they exit with 0. Treat
|
||||
those as clean rather than "warnings". This function centralizes the
|
||||
heuristics.
|
||||
"""
|
||||
if not output or not output.strip():
|
||||
return True
|
||||
|
||||
# Common success patterns to treat as clean. Case-insensitive.
|
||||
success_patterns = [
|
||||
r"no problems found",
|
||||
r"0 problems",
|
||||
r"no issues found",
|
||||
r"success: no problems found",
|
||||
r"all good",
|
||||
r"ok$",
|
||||
]
|
||||
|
||||
text = output.lower()
|
||||
for pat in success_patterns:
|
||||
if re.search(pat, text):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def run_lint(project_root: Path) -> Tuple[bool, Dict]:
|
||||
"""Run gdlint on all GDScript files."""
|
||||
print_header("🔍 GDScript Linter")
|
||||
|
||||
gd_files = get_gd_files(project_root)
|
||||
count_msg = f"Found {len(gd_files)} GDScript files to lint."
|
||||
colored_count = Colors.colorize(count_msg, Colors.BLUE)
|
||||
print(f"{colored_count}\n")
|
||||
|
||||
clean_files = warning_files = error_files = 0
|
||||
failed_paths = []
|
||||
|
||||
for gd_file in gd_files:
|
||||
relative_path = gd_file.relative_to(project_root)
|
||||
file_msg = f"📄 Linting: {relative_path.name}"
|
||||
colored_file = Colors.colorize(file_msg, Colors.CYAN)
|
||||
print(colored_file)
|
||||
|
||||
if should_skip_file(gd_file):
|
||||
print_skip_message("gdlint")
|
||||
clean_files += 1
|
||||
print()
|
||||
continue
|
||||
|
||||
try:
|
||||
result = run_command(["gdlint", str(gd_file)], project_root)
|
||||
output = (result.stdout + result.stderr).strip()
|
||||
|
||||
if result.returncode == 0:
|
||||
# If output is "no problems" (or similar), treat as clean.
|
||||
if _is_successful_linter_output(output):
|
||||
clean_files += 1
|
||||
print_result(True, "")
|
||||
else:
|
||||
warning_files += 1
|
||||
print_result(True, output)
|
||||
else:
|
||||
error_files += 1
|
||||
failed_paths.append(str(relative_path))
|
||||
print_result(False, output)
|
||||
|
||||
except FileNotFoundError:
|
||||
print(" ❌ ERROR: gdlint not found")
|
||||
return False, {}
|
||||
except Exception as e:
|
||||
print(f" ❌ ERROR: {e}")
|
||||
error_files += 1
|
||||
failed_paths.append(str(relative_path))
|
||||
|
||||
print()
|
||||
|
||||
# Summary
|
||||
stats = {
|
||||
"Total files": len(gd_files),
|
||||
"Clean files": clean_files,
|
||||
"Files with warnings": warning_files,
|
||||
"Files with errors": error_files
|
||||
}
|
||||
print_summary("Linting Summary", stats)
|
||||
|
||||
success = error_files == 0
|
||||
print()
|
||||
if not success:
|
||||
msg = "❌ Linting FAILED - Please fix the errors above"
|
||||
colored_msg = Colors.colorize(msg, Colors.RED + Colors.BOLD)
|
||||
print(colored_msg)
|
||||
elif warning_files > 0:
|
||||
msg = "⚠️ Linting PASSED with warnings - Consider fixing them"
|
||||
colored_msg = Colors.colorize(msg, Colors.YELLOW + Colors.BOLD)
|
||||
print(colored_msg)
|
||||
else:
|
||||
msg = "✅ All GDScript files passed linting!"
|
||||
colored_msg = Colors.colorize(msg, Colors.GREEN + Colors.BOLD)
|
||||
print(colored_msg)
|
||||
|
||||
return success, {**stats, "failed_paths": failed_paths}
|
||||
|
||||
|
||||
# rest of file unchanged (format, tests, workflow runner) -- copied verbatim
|
||||
|
||||
def run_format(project_root: Path) -> Tuple[bool, Dict]:
|
||||
"""Run gdformat on all GDScript files."""
|
||||
print_header("🎨 GDScript Formatter")
|
||||
|
||||
gd_files = get_gd_files(project_root)
|
||||
count_msg = f"Found {len(gd_files)} GDScript files to format."
|
||||
colored_count = Colors.colorize(count_msg, Colors.BLUE)
|
||||
print(f"{colored_count}\n")
|
||||
|
||||
formatted_files = failed_files = 0
|
||||
failed_paths = []
|
||||
|
||||
for gd_file in gd_files:
|
||||
relative_path = gd_file.relative_to(project_root)
|
||||
file_msg = f"🎯 Formatting: {relative_path.name}"
|
||||
colored_file = Colors.colorize(file_msg, Colors.CYAN)
|
||||
print(colored_file)
|
||||
|
||||
if should_skip_file(gd_file):
|
||||
print_skip_message("gdformat")
|
||||
formatted_files += 1
|
||||
print()
|
||||
continue
|
||||
|
||||
try:
|
||||
result = run_command(["gdformat", str(gd_file)], project_root)
|
||||
|
||||
if result.returncode == 0:
|
||||
success_msg = "✅ Success"
|
||||
colored_success = Colors.colorize(success_msg, Colors.GREEN)
|
||||
print(f" {colored_success}")
|
||||
formatted_files += 1
|
||||
else:
|
||||
fail_msg = f"❌ FAILED: {relative_path}"
|
||||
colored_fail = Colors.colorize(fail_msg, Colors.RED)
|
||||
print(f" {colored_fail}")
|
||||
output = (result.stdout + result.stderr).strip()
|
||||
if output:
|
||||
colored_output = Colors.colorize(output, Colors.RED)
|
||||
print(f" {colored_output}")
|
||||
failed_files += 1
|
||||
failed_paths.append(str(relative_path))
|
||||
|
||||
except FileNotFoundError:
|
||||
print(" ❌ ERROR: gdformat not found")
|
||||
return False, {}
|
||||
except Exception as e:
|
||||
print(f" ❌ ERROR: {e}")
|
||||
failed_files += 1
|
||||
failed_paths.append(str(relative_path))
|
||||
|
||||
print()
|
||||
|
||||
# Summary
|
||||
stats = {
|
||||
"Total files": len(gd_files),
|
||||
"Successfully formatted": formatted_files,
|
||||
"Failed": failed_files
|
||||
}
|
||||
print_summary("Formatting Summary", stats)
|
||||
|
||||
success = failed_files == 0
|
||||
print()
|
||||
if not success:
|
||||
msg = "⚠️ WARNING: Some files failed to format"
|
||||
colored_msg = Colors.colorize(msg, Colors.YELLOW + Colors.BOLD)
|
||||
print(colored_msg)
|
||||
else:
|
||||
msg = "✅ All GDScript files formatted successfully!"
|
||||
colored_msg = Colors.colorize(msg, Colors.GREEN + Colors.BOLD)
|
||||
print(colored_msg)
|
||||
|
||||
return success, {**stats, "failed_paths": failed_paths}
|
||||
|
||||
|
||||
def discover_test_files(project_root: Path) -> List[Tuple[Path, str]]:
|
||||
"""Discover all test files with their prefixes."""
|
||||
test_dirs = [
|
||||
("tests", ""),
|
||||
("tests/unit", "Unit: "),
|
||||
("tests/integration", "Integration: ")
|
||||
]
|
||||
|
||||
test_files = []
|
||||
for test_dir, prefix in test_dirs:
|
||||
test_path = project_root / test_dir
|
||||
if test_path.exists():
|
||||
for test_file in test_path.glob("test_*.gd"):
|
||||
test_files.append((test_file, prefix))
|
||||
|
||||
return test_files
|
||||
|
||||
|
||||
def run_tests(project_root: Path) -> Tuple[bool, Dict]:
|
||||
"""Run Godot tests."""
|
||||
print_header("🧪 GDScript Test Runner")
|
||||
|
||||
test_files = discover_test_files(project_root)
|
||||
|
||||
scan_msg = "🔍 Scanning for test files in tests\\ directory..."
|
||||
colored_scan = Colors.colorize(scan_msg, Colors.BLUE)
|
||||
print(colored_scan)
|
||||
|
||||
discover_msg = "\n📋 Discovered test files:"
|
||||
colored_discover = Colors.colorize(discover_msg, Colors.CYAN)
|
||||
print(colored_discover)
|
||||
|
||||
for test_file, prefix in test_files:
|
||||
test_name = format_test_name(test_file.stem)
|
||||
file_info = f" {prefix}{test_name}: {test_file}"
|
||||
colored_file_info = Colors.colorize(file_info, Colors.MAGENTA)
|
||||
print(colored_file_info)
|
||||
|
||||
start_msg = "\n🚀 Starting test execution...\n"
|
||||
colored_start = Colors.colorize(start_msg, Colors.BLUE + Colors.BOLD)
|
||||
print(colored_start)
|
||||
|
||||
total_tests = failed_tests = 0
|
||||
test_results = []
|
||||
|
||||
for test_file, prefix in test_files:
|
||||
test_name = format_test_name(test_file.stem)
|
||||
full_test_name = f"{prefix}{test_name}"
|
||||
|
||||
header_msg = f"=== {full_test_name} ==="
|
||||
colored_header = Colors.colorize(header_msg, Colors.CYAN + Colors.BOLD)
|
||||
print(f"\n{colored_header}")
|
||||
|
||||
running_msg = f"🎯 Running: {test_file}"
|
||||
colored_running = Colors.colorize(running_msg, Colors.BLUE)
|
||||
print(colored_running)
|
||||
|
||||
try:
|
||||
result = run_command(
|
||||
["godot", "--headless", "--script", str(test_file)],
|
||||
project_root,
|
||||
timeout=60
|
||||
)
|
||||
|
||||
if result.returncode == 0:
|
||||
pass_msg = f"✅ PASSED: {full_test_name}"
|
||||
colored_pass = Colors.colorize(pass_msg, Colors.GREEN + Colors.BOLD)
|
||||
print(colored_pass)
|
||||
test_results.append((full_test_name, True, ""))
|
||||
else:
|
||||
fail_msg = f"❌ FAILED: {full_test_name}"
|
||||
colored_fail = Colors.colorize(fail_msg, Colors.RED + Colors.BOLD)
|
||||
print(colored_fail)
|
||||
failed_tests += 1
|
||||
error_msg = (result.stderr + result.stdout).strip() or "Unknown error"
|
||||
test_results.append((full_test_name, False, error_msg))
|
||||
|
||||
total_tests += 1
|
||||
|
||||
except subprocess.TimeoutExpired:
|
||||
timeout_msg = f"⏰ FAILED: {full_test_name} (TIMEOUT)"
|
||||
colored_timeout = Colors.colorize(timeout_msg, Colors.RED + Colors.BOLD)
|
||||
print(colored_timeout)
|
||||
failed_tests += 1
|
||||
test_results.append((full_test_name, False, "Test timed out"))
|
||||
total_tests += 1
|
||||
except FileNotFoundError:
|
||||
error_msg = "❌ ERROR: Godot not found"
|
||||
colored_error = Colors.colorize(error_msg, Colors.RED + Colors.BOLD)
|
||||
print(colored_error)
|
||||
return False, {}
|
||||
except Exception as e:
|
||||
exc_msg = f"💥 FAILED: {full_test_name} (ERROR: {e})"
|
||||
colored_exc = Colors.colorize(exc_msg, Colors.RED + Colors.BOLD)
|
||||
print(colored_exc)
|
||||
failed_tests += 1
|
||||
test_results.append((full_test_name, False, str(e)))
|
||||
total_tests += 1
|
||||
|
||||
print()
|
||||
|
||||
# Summary
|
||||
passed_tests = total_tests - failed_tests
|
||||
stats = {
|
||||
"Total Tests Run": total_tests,
|
||||
"Tests Passed": passed_tests,
|
||||
"Tests Failed": failed_tests
|
||||
}
|
||||
print_summary("Test Execution Summary", stats)
|
||||
|
||||
success = failed_tests == 0
|
||||
print()
|
||||
if success:
|
||||
msg = "🎉 ALL TESTS PASSED!"
|
||||
colored_msg = Colors.colorize(msg, Colors.GREEN + Colors.BOLD)
|
||||
print(colored_msg)
|
||||
else:
|
||||
msg = f"💥 {failed_tests} TEST(S) FAILED"
|
||||
colored_msg = Colors.colorize(msg, Colors.RED + Colors.BOLD)
|
||||
print(colored_msg)
|
||||
|
||||
return success, {**stats, "results": test_results}
|
||||
|
||||
|
||||
def run_workflow(project_root: Path, steps: List[str]) -> bool:
|
||||
"""
|
||||
Execute development workflow steps in sequence.
|
||||
|
||||
Runs format, lint, and test steps. Continues executing all steps even if some fail.
|
||||
|
||||
Args:
|
||||
project_root: Path to the project root directory
|
||||
steps: List of workflow steps to execute ('format', 'lint', 'test')
|
||||
|
||||
Returns:
|
||||
bool: True if all steps completed successfully, False if any failed
|
||||
"""
|
||||
print_header("🔄 Development Workflow Runner")
|
||||
|
||||
workflow_steps = {
|
||||
"lint": ("🔍 Code linting (gdlint)", run_lint),
|
||||
"format": ("🎨 Code formatting (gdformat)", run_format),
|
||||
"test": ("🧪 Test execution (godot tests)", run_tests)
|
||||
}
|
||||
|
||||
intro_msg = "🚀 This script will run the development workflow:"
|
||||
colored_intro = Colors.colorize(intro_msg, Colors.BLUE + Colors.BOLD)
|
||||
print(colored_intro)
|
||||
|
||||
for i, step in enumerate(steps, 1):
|
||||
step_name = workflow_steps[step][0]
|
||||
step_msg = f"{i}. {step_name}"
|
||||
colored_step = Colors.colorize(step_msg, Colors.CYAN)
|
||||
print(colored_step)
|
||||
print()
|
||||
|
||||
start_time = time.time()
|
||||
results = {}
|
||||
|
||||
for step in steps:
|
||||
step_name, step_func = workflow_steps[step]
|
||||
separator = Colors.colorize("-" * 48, Colors.MAGENTA)
|
||||
print(separator)
|
||||
|
||||
running_msg = f"⚡ Running {step_name}"
|
||||
colored_running = Colors.colorize(running_msg, Colors.BLUE + Colors.BOLD)
|
||||
print(colored_running)
|
||||
print(separator)
|
||||
|
||||
success, step_results = step_func(project_root)
|
||||
results[step] = step_results
|
||||
|
||||
if not success:
|
||||
fail_msg = f"❌ {step.upper()} FAILED - Continuing with remaining steps"
|
||||
colored_fail = Colors.colorize(fail_msg, Colors.RED + Colors.BOLD)
|
||||
print(f"\n{colored_fail}")
|
||||
|
||||
warning_msg = "⚠️ Issues found, but continuing to provide complete feedback"
|
||||
colored_warning = Colors.colorize(warning_msg, Colors.YELLOW)
|
||||
print(colored_warning)
|
||||
|
||||
status_msg = f"✅ {step_name} completed {'successfully' if success else 'with issues'}"
|
||||
colored_status = Colors.colorize(status_msg, Colors.GREEN if success else Colors.YELLOW)
|
||||
print(colored_status)
|
||||
print()
|
||||
|
||||
# Final summary
|
||||
elapsed_time = time.time() - start_time
|
||||
print_header("📊 Workflow Summary")
|
||||
|
||||
all_success = True
|
||||
any_failures = False
|
||||
for step in steps:
|
||||
step_success = results[step].get("Tests Failed", results[step].get("Failed", 0)) == 0
|
||||
status_emoji = "✅" if step_success else "❌"
|
||||
status_text = "PASSED" if step_success else "FAILED"
|
||||
status_color = Colors.GREEN if step_success else Colors.RED
|
||||
|
||||
step_emoji = {"lint": "🔍", "format": "🎨", "test": "🧪"}.get(step, "📋")
|
||||
colored_status = Colors.colorize(f"{status_text}", status_color + Colors.BOLD)
|
||||
print(f"{step_emoji} {step.capitalize()}: {status_emoji} {colored_status}")
|
||||
|
||||
if not step_success:
|
||||
any_failures = True
|
||||
all_success = False
|
||||
|
||||
print()
|
||||
if all_success:
|
||||
success_msg = "🎉 ALL WORKFLOW STEPS COMPLETED SUCCESSFULLY!"
|
||||
colored_success = Colors.colorize(success_msg, Colors.GREEN + Colors.BOLD)
|
||||
print(colored_success)
|
||||
|
||||
commit_msg = "🚀 Your code is ready for commit."
|
||||
colored_commit = Colors.colorize(commit_msg, Colors.CYAN)
|
||||
print(colored_commit)
|
||||
else:
|
||||
fail_msg = "❌ WORKFLOW COMPLETED WITH FAILURES"
|
||||
colored_fail = Colors.colorize(fail_msg, Colors.RED + Colors.BOLD)
|
||||
print(colored_fail)
|
||||
|
||||
review_msg = "🔧 Please fix the issues above before committing."
|
||||
colored_review = Colors.colorize(review_msg, Colors.RED)
|
||||
print(colored_review)
|
||||
|
||||
time_msg = f"⏱️ Elapsed time: {elapsed_time:.1f} seconds"
|
||||
colored_time = Colors.colorize(time_msg, Colors.MAGENTA)
|
||||
print(f"\n{colored_time}")
|
||||
return all_success
|
||||
|
||||
|
||||
def main():
|
||||
"""Main entry point."""
|
||||
parser = argparse.ArgumentParser(description="Run development workflow for Skelly Godot project")
|
||||
parser.add_argument("--steps", nargs="+", choices=["lint", "format", "test"],
|
||||
default=["format", "lint", "test"], help="Workflow steps to run")
|
||||
parser.add_argument("--lint", action="store_true", help="Run linting")
|
||||
parser.add_argument("--format", action="store_true", help="Run formatting")
|
||||
parser.add_argument("--test", action="store_true", help="Run tests")
|
||||
|
||||
args = parser.parse_args()
|
||||
project_root = Path(__file__).parent.parent
|
||||
|
||||
# Determine steps to run
|
||||
if args.lint:
|
||||
steps = ["lint"]
|
||||
elif args.format:
|
||||
steps = ["format"]
|
||||
elif args.test:
|
||||
steps = ["test"]
|
||||
else:
|
||||
steps = args.steps
|
||||
|
||||
# Run workflow or individual step
|
||||
if len(steps) == 1:
|
||||
step_funcs = {"lint": run_lint, "format": run_format, "test": run_tests}
|
||||
success, _ = step_funcs[steps[0]](project_root)
|
||||
else:
|
||||
success = run_workflow(project_root, steps)
|
||||
|
||||
sys.exit(0 if success else 1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user