mirror of
https://github.com/kevinveenbirkenbach/homepage.veen.world.git
synced 2026-04-07 05:12:19 +00:00
- Replace requirements.txt with pyproject.toml for modern Python packaging - Add unit, integration, lint and security test suites under tests/ - Add utils/export_runtime_requirements.py and utils/check_hadolint_sarif.py - Split monolithic CI into reusable lint.yml, security.yml and tests.yml - Refactor ci.yml to orchestrate reusable workflows; publish on semver tag only - Modernize Dockerfile: pin python:3.12-slim, install via pyproject.toml - Expand Makefile with lint, security, test and CI targets - Add test-e2e via act with portfolio container stop/start around run - Fix navbar_logo_visibility.spec.js: win.fullscreen() → win.enterFullscreen() - Set use_reloader=False in app.run() to prevent double-start in CI - Add app/core.* and build artifacts to .gitignore - Fix apt-get → sudo apt-get in tests.yml e2e job - Fix pip install --ignore-installed to handle stale act cache Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
80 lines
2.2 KiB
Python
Executable File
80 lines
2.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
main.py - Proxy to Makefile targets for managing the Portfolio CMS Docker application.
|
|
Automatically generates CLI commands based on the Makefile definitions.
|
|
"""
|
|
|
|
import argparse
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
MAKEFILE_PATH = Path(__file__).resolve().parent / "Makefile"
|
|
|
|
|
|
def load_targets(makefile_path):
|
|
"""
|
|
Parse the Makefile to extract targets and their help comments.
|
|
Assumes each target is defined as 'name:' and the following line that starts
|
|
with '\t#' provides its help text.
|
|
"""
|
|
targets = []
|
|
pattern = re.compile(r"^([A-Za-z0-9_\-]+):")
|
|
with open(makefile_path, "r", encoding="utf-8") as handle:
|
|
lines = handle.readlines()
|
|
for idx, line in enumerate(lines):
|
|
m = pattern.match(line)
|
|
if m:
|
|
name = m.group(1)
|
|
help_text = ""
|
|
if idx + 1 < len(lines):
|
|
next_line = lines[idx + 1].lstrip()
|
|
if next_line.startswith("#"):
|
|
help_text = next_line.lstrip("# ").strip()
|
|
targets.append((name, help_text))
|
|
return targets
|
|
|
|
|
|
def run_command(command, dry_run=False):
|
|
"""Utility to run shell commands."""
|
|
print(f"Executing: {' '.join(command)}")
|
|
if dry_run:
|
|
print("Dry run enabled: command not executed.")
|
|
return
|
|
try:
|
|
subprocess.check_call(command)
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"Error: Command failed with exit code {e.returncode}")
|
|
sys.exit(e.returncode)
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description="CLI proxy to Makefile targets for Portfolio CMS Docker app"
|
|
)
|
|
parser.add_argument(
|
|
"--dry-run",
|
|
action="store_true",
|
|
help="Print the generated Make command without executing it.",
|
|
)
|
|
|
|
subparsers = parser.add_subparsers(
|
|
title="Available commands",
|
|
dest="command",
|
|
required=True,
|
|
)
|
|
|
|
targets = load_targets(MAKEFILE_PATH)
|
|
for name, help_text in targets:
|
|
sp = subparsers.add_parser(name, help=help_text)
|
|
sp.set_defaults(target=name)
|
|
|
|
args = parser.parse_args()
|
|
cmd = ["make", args.target]
|
|
run_command(cmd, dry_run=args.dry_run)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|