-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathreport.py
More file actions
122 lines (97 loc) · 4.18 KB
/
Copy pathreport.py
File metadata and controls
122 lines (97 loc) · 4.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#!/usr/bin/env python3
"""CLI entry point for the GitHub Weekly Activity Report Bot.
Usage:
python report.py run
python report.py run --repo owner/name --days 14
python report.py test-delivery
"""
from __future__ import annotations
import logging
import sys
import click
from app.aggregator import build_report_data
from app.config import ConfigError, load_config
from app.delivery import DeliveryError, deliver_report
from app.github_client import GitHubAPIError, GitHubClient, since_days_ago
from app.logging_setup import setup_logging
from app.report_generator import render_html, render_text, save_report_to_file
logger = setup_logging()
def _collect_repo_data(client: GitHubClient, repos: list[str], since) -> dict:
per_repo_raw = {}
for repo in repos:
logger.info("Fetching activity for %s ...", repo)
commits = client.get_commits(repo, since)
pull_requests = client.get_pull_requests(repo, since)
issues = client.get_issues(repo, since)
per_repo_raw[repo] = {
"commits": commits,
"pull_requests": pull_requests,
"issues": issues,
}
logger.info(
" %s: %d commits, %d PRs, %d issues fetched",
repo, len(commits), len(pull_requests), len(issues),
)
return per_repo_raw
@click.group()
def cli():
"""GitHub Weekly Activity Report Bot."""
@cli.command()
@click.option("--config", "config_path", default="config.yaml", help="Path to config.yaml")
@click.option("--repo", "repo_override", default=None, help="Override: single repo owner/name")
@click.option("--days", "days_override", default=None, type=int, help="Override: time window in days")
@click.option("--no-delivery", is_flag=True, help="Generate the report but skip email/Slack delivery")
def run(config_path: str, repo_override: str | None, days_override: int | None, no_delivery: bool):
"""Fetch activity, generate the report, and deliver it."""
try:
config = load_config(config_path)
except ConfigError as exc:
logger.error("Configuration error: %s", exc)
sys.exit(1)
repos = [repo_override] if repo_override else config.repos
days = days_override or config.days
since = since_days_ago(days)
client = GitHubClient(token=config.github_token)
try:
per_repo_raw = _collect_repo_data(client, repos, since)
except GitHubAPIError as exc:
logger.error("GitHub API error: %s", exc)
sys.exit(1)
report_data = build_report_data(since=since, days=days, per_repo_raw=per_repo_raw)
html_path, text_path = save_report_to_file(report_data)
logger.info("Report saved to %s and %s", html_path, text_path)
if no_delivery:
logger.info("--no-delivery set, skipping email/Slack delivery.")
return
html_body = render_html(report_data)
text_body = render_text(report_data)
subject = f"Weekly GitHub Activity Report — {report_data.since.strftime('%Y-%m-%d')}"
try:
delivered = deliver_report(config, subject, html_body, text_body)
if delivered:
logger.info("Report delivered via: %s", ", ".join(delivered))
else:
logger.info("No delivery channel configured (delivery.method = 'none').")
except DeliveryError as exc:
logger.error("Report delivery failed: %s", exc)
sys.exit(1)
@cli.command("test-delivery")
@click.option("--config", "config_path", default="config.yaml", help="Path to config.yaml")
def test_delivery(config_path: str):
"""Send a small test message to verify email/Slack config works."""
try:
config = load_config(config_path)
except ConfigError as exc:
logger.error("Configuration error: %s", exc)
sys.exit(1)
subject = "GitHub Report Bot — Test Delivery"
text_body = "This is a test message confirming your delivery configuration works."
html_body = f"<p>{text_body}</p>"
try:
delivered = deliver_report(config, subject, html_body, text_body)
logger.info("Test delivery succeeded via: %s", ", ".join(delivered) or "none configured")
except DeliveryError as exc:
logger.error("Test delivery failed: %s", exc)
sys.exit(1)
if __name__ == "__main__":
cli()