Coverage for src/pytribeam/cicd/badge_lint.py: 83%
53 statements
« prev ^ index » next coverage.py v7.5.1, created at 2026-07-23 00:29 +0000
« prev ^ index » next coverage.py v7.5.1, created at 2026-07-23 00:29 +0000
1"""
2Generates the Lint badge (SVG) and metadata (JSON) for CI/CD.
3"""
5import argparse
6import os
7import re
8import sys
9from datetime import datetime, timezone
10from pathlib import Path
12from pytribeam.cicd.utilities import (
13 add_badge_args,
14 badge_image_download,
15 badge_metadata_json_write,
16 get_score_color_lint,
17)
20def extract_score(input_file: str) -> float:
21 """Extracts the lint score from the output text file."""
22 pattern = re.compile(r"Your code has been rated at (\d+\.\d+)/10")
23 try:
24 with open(input_file, "r", encoding="utf-8") as f:
25 content = f.read()
26 match = pattern.search(content)
27 if match:
28 return float(match.group(1))
29 except (FileNotFoundError, IOError, ValueError) as e:
30 print(f"[!] Error reading lint output: {e}")
31 return 0.0
34def export_to_github_env(color: str):
35 """Exports the badge color to GITHUB_ENV if available."""
36 env_path = os.environ.get("GITHUB_ENV")
37 if env_path: 37 ↛ exitline 37 didn't return from function 'export_to_github_env', because the condition on line 37 was always true
38 with open(env_path, "a", encoding="utf-8") as f:
39 f.write(f"BADGE_COLOR={color}\n")
40 print(f" [C] Exported BADGE_COLOR={color} to GITHUB_ENV")
43def main():
44 """Main method for creating the badge."""
45 parser = argparse.ArgumentParser(description="Generate Lint badge and metadata.")
46 parser.add_argument("--input_file", help="Lint text output file (to extract score)")
47 parser.add_argument("--score", type=float, help="Lint score (direct input)")
48 parser.add_argument(
49 "--export_env", action="store_true", help="Export color to GITHUB_ENV"
50 )
52 # Add common badge arguments from utilities
53 add_badge_args(parser)
55 args = parser.parse_args()
57 # Determine the score
58 if args.score is not None: 58 ↛ 59line 58 didn't jump to line 59, because the condition on line 58 was never true
59 score = args.score
60 elif args.input_file: 60 ↛ 63line 60 didn't jump to line 63, because the condition on line 60 was always true
61 score = extract_score(args.input_file)
62 else:
63 print("[X] Error: Must provide either --input_file or --score")
64 sys.exit(1)
66 color = get_score_color_lint(str(score))
68 # Optional export to GITHUB_ENV
69 if args.export_env: 69 ↛ 73line 69 didn't jump to line 73, because the condition on line 69 was always true
70 export_to_github_env(color)
72 # If output_dir is provided, generate SVG and JSON
73 if args.output_dir: 73 ↛ 101line 73 didn't jump to line 101, because the condition on line 73 was always true
74 os.makedirs(args.output_dir, exist_ok=True)
76 # Download SVG badge
77 badge_url = f"https://img.shields.io/badge/lint-{score}-{color}.svg"
78 output_svg = str(Path(args.output_dir) / "lint.svg")
79 if badge_image_download(url=badge_url, output_path=output_svg): 79 ↛ 83line 79 didn't jump to line 83, because the condition on line 79 was always true
80 print(f"[OK] Lint SVG badge saved to {args.output_dir}")
82 # Generate JSON metadata if other required args are present
83 if all([args.github_repo, args.deploy_subdir, args.run_id]): 83 ↛ 101line 83 didn't jump to line 101, because the condition on line 83 was always true
84 owner, repo = args.github_repo.split("/")
85 metadata = {
86 "score": str(score),
87 "color": color,
88 "pages_url": f"https://{owner}.github.io/{repo}/{args.deploy_subdir}/reports/lint/",
89 "workflow_url": (
90 f"{args.github_server_url}/{args.github_repo}/"
91 "actions/workflows/ci.yml"
92 ),
93 "run_id": args.run_id,
94 "timestamp": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
95 }
97 output_json = str(Path(args.output_dir) / "lint-info.json")
98 badge_metadata_json_write(metadata=metadata, output_path=output_json)
99 print(f"[OK] Lint JSON metadata saved to {args.output_dir}")
101 print(f"Lint badge processing complete: Score={score}, Color={color}")
104if __name__ == "__main__":
105 main()