gh-weekly-updates 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sahan Serasinghe <sahan.serasinghe@gmail.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,181 @@
1
+ Metadata-Version: 2.4
2
+ Name: gh-weekly-updates
3
+ Version: 0.1.0
4
+ Summary: Automatically discover and summarise your weekly GitHub impact
5
+ License: MIT
6
+ Project-URL: Homepage, https://github.com/sahansera/gh-weekly-updates
7
+ Project-URL: Repository, https://github.com/sahansera/gh-weekly-updates
8
+ Project-URL: Issues, https://github.com/sahansera/gh-weekly-updates/issues
9
+ Keywords: github,weekly,impact,summary,engineering
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Programming Language :: Python :: 3.13
17
+ Classifier: Topic :: Software Development
18
+ Requires-Python: >=3.11
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: click>=8.1
22
+ Requires-Dist: httpx>=0.27
23
+ Requires-Dist: pydantic>=2.0
24
+ Requires-Dist: pyyaml>=6.0
25
+ Requires-Dist: rich>=13.0
26
+ Requires-Dist: openai>=1.30
27
+ Provides-Extra: dev
28
+ Requires-Dist: ruff>=0.4; extra == "dev"
29
+ Requires-Dist: pytest>=8.0; extra == "dev"
30
+ Dynamic: license-file
31
+
32
+ # gh-weekly-updates
33
+
34
+ > Automatically discover and summarise your weekly GitHub impact using AI.
35
+
36
+ `gh-weekly-updates` collects your GitHub activity — pull requests authored & reviewed, issues created & commented on, discussions — and generates a structured Markdown summary using [GitHub Models](https://github.com/marketplace/models).
37
+
38
+ ## Features
39
+
40
+ - **Auto-discover repos** via the GitHub GraphQL Contributions API, or provide an explicit list
41
+ - **Collect detailed activity**: PRs, reviews, issues, issue comments, discussions
42
+ - **AI-powered summarisation** via GitHub Models (`openai/gpt-4.1` by default)
43
+ - **Structured output**: Wins / Strategic Influence / Challenges with inline links
44
+ - **Push to a repo**: automatically commit summaries to a GitHub repo for sharing
45
+ - **Fully configurable**: org, repos, model, prompt — via YAML config or CLI flags
46
+ - **Custom prompts**: tailor the AI summary to your team's format
47
+
48
+ ## Installation
49
+
50
+ ```bash
51
+ pip install gh-weekly-updates
52
+ ```
53
+
54
+ ### Requirements
55
+
56
+ - Python 3.11+
57
+ - A GitHub personal access token (PAT) **or** the [GitHub CLI](https://cli.github.com/) (`gh`) authenticated
58
+ - Required scopes: `repo`, `read:org`
59
+ - The token also needs access to [GitHub Models](https://github.com/marketplace/models) for AI summarisation
60
+
61
+ ## Quick start
62
+
63
+ ```bash
64
+ # Authenticate with the GitHub CLI (easiest)
65
+ gh auth login
66
+
67
+ # Run with defaults — covers the past week
68
+ gh-weekly-updates
69
+
70
+ # Or specify a date range
71
+ gh-weekly-updates --since 2025-06-01 --until 2025-06-07
72
+ ```
73
+
74
+ ## Configuration
75
+
76
+ Create a `config.yaml` (see [config.example.yaml](config.example.yaml)):
77
+
78
+ ```yaml
79
+ # GitHub org to scope repo discovery to
80
+ org: my-org
81
+
82
+ # Explicit repo list (skips auto-discovery)
83
+ repos:
84
+ - my-org/api-service
85
+ - my-org/web-app
86
+
87
+ # GitHub Model for summarisation
88
+ model: openai/gpt-4.1
89
+
90
+ # Push summary to a repo under weekly-updates/
91
+ push_repo: my-user/my-updates
92
+
93
+ # Custom system prompt (inline)
94
+ prompt: |
95
+ You are an engineering manager writing a concise weekly summary...
96
+
97
+ # Or load prompt from a file
98
+ # prompt_file: my-prompt.txt
99
+ ```
100
+
101
+ ## CLI reference
102
+
103
+ ```
104
+ Usage: gh-weekly-updates [OPTIONS]
105
+
106
+ Options:
107
+ --config PATH Path to YAML config file. Default: ./config.yaml
108
+ --since TEXT Start date (ISO 8601). Default: previous Monday.
109
+ --until TEXT End date (ISO 8601). Default: now.
110
+ --user TEXT GitHub username. Default: authenticated user.
111
+ --repos TEXT Comma-separated list of repos (owner/name).
112
+ --org TEXT GitHub org to scope repo discovery to.
113
+ --output PATH Write summary to a file instead of stdout.
114
+ --push TEXT Push summary to a GitHub repo (owner/name).
115
+ --model TEXT GitHub Model to use. Default: openai/gpt-4.1.
116
+ --verbose Enable debug logging.
117
+ --help Show this message and exit.
118
+ ```
119
+
120
+ ## Authentication
121
+
122
+ `gh-weekly-updates` resolves a GitHub token in this order:
123
+
124
+ 1. `GITHUB_TOKEN` environment variable
125
+ 2. `gh auth token` (GitHub CLI)
126
+
127
+ For GitHub Enterprise with SSO, ensure the token is authorised for your org.
128
+
129
+ ## Using with GitHub Actions
130
+
131
+ You can run `gh-weekly-updates` on a schedule in a GitHub Actions workflow:
132
+
133
+ ```yaml
134
+ name: Weekly Impact Summary
135
+
136
+ on:
137
+ schedule:
138
+ - cron: '0 9 * * 1' # Every Monday at 9am UTC
139
+ workflow_dispatch:
140
+
141
+ jobs:
142
+ summarise:
143
+ runs-on: ubuntu-latest
144
+ steps:
145
+ - uses: actions/checkout@v4
146
+
147
+ - uses: actions/setup-python@v5
148
+ with:
149
+ python-version: '3.12'
150
+
151
+ - name: Install gh-weekly-updates
152
+ run: pip install gh-weekly-updates
153
+
154
+ - name: Generate summary
155
+ env:
156
+ GITHUB_TOKEN: ${{ secrets.GH_PAT }}
157
+ run: |
158
+ gh-weekly-updates \
159
+ --config config.yaml \
160
+ --push my-user/my-updates
161
+ ```
162
+
163
+ > **Note**: The default `GITHUB_TOKEN` provided by Actions has limited scope.
164
+ > Use a [Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) stored as a repository secret with `repo` and `read:org` scopes, plus GitHub Models access.
165
+
166
+ ## Development
167
+
168
+ ```bash
169
+ git clone https://github.com/sahansera/gh-weekly-updates.git
170
+ cd gh-weekly-updates
171
+ python -m venv .venv && source .venv/bin/activate
172
+ make dev # install in editable mode with dev deps
173
+ make run # run with defaults
174
+ make lint # ruff check
175
+ ```
176
+
177
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for more details.
178
+
179
+ ## License
180
+
181
+ [MIT](LICENSE)
@@ -0,0 +1,150 @@
1
+ # gh-weekly-updates
2
+
3
+ > Automatically discover and summarise your weekly GitHub impact using AI.
4
+
5
+ `gh-weekly-updates` collects your GitHub activity — pull requests authored & reviewed, issues created & commented on, discussions — and generates a structured Markdown summary using [GitHub Models](https://github.com/marketplace/models).
6
+
7
+ ## Features
8
+
9
+ - **Auto-discover repos** via the GitHub GraphQL Contributions API, or provide an explicit list
10
+ - **Collect detailed activity**: PRs, reviews, issues, issue comments, discussions
11
+ - **AI-powered summarisation** via GitHub Models (`openai/gpt-4.1` by default)
12
+ - **Structured output**: Wins / Strategic Influence / Challenges with inline links
13
+ - **Push to a repo**: automatically commit summaries to a GitHub repo for sharing
14
+ - **Fully configurable**: org, repos, model, prompt — via YAML config or CLI flags
15
+ - **Custom prompts**: tailor the AI summary to your team's format
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ pip install gh-weekly-updates
21
+ ```
22
+
23
+ ### Requirements
24
+
25
+ - Python 3.11+
26
+ - A GitHub personal access token (PAT) **or** the [GitHub CLI](https://cli.github.com/) (`gh`) authenticated
27
+ - Required scopes: `repo`, `read:org`
28
+ - The token also needs access to [GitHub Models](https://github.com/marketplace/models) for AI summarisation
29
+
30
+ ## Quick start
31
+
32
+ ```bash
33
+ # Authenticate with the GitHub CLI (easiest)
34
+ gh auth login
35
+
36
+ # Run with defaults — covers the past week
37
+ gh-weekly-updates
38
+
39
+ # Or specify a date range
40
+ gh-weekly-updates --since 2025-06-01 --until 2025-06-07
41
+ ```
42
+
43
+ ## Configuration
44
+
45
+ Create a `config.yaml` (see [config.example.yaml](config.example.yaml)):
46
+
47
+ ```yaml
48
+ # GitHub org to scope repo discovery to
49
+ org: my-org
50
+
51
+ # Explicit repo list (skips auto-discovery)
52
+ repos:
53
+ - my-org/api-service
54
+ - my-org/web-app
55
+
56
+ # GitHub Model for summarisation
57
+ model: openai/gpt-4.1
58
+
59
+ # Push summary to a repo under weekly-updates/
60
+ push_repo: my-user/my-updates
61
+
62
+ # Custom system prompt (inline)
63
+ prompt: |
64
+ You are an engineering manager writing a concise weekly summary...
65
+
66
+ # Or load prompt from a file
67
+ # prompt_file: my-prompt.txt
68
+ ```
69
+
70
+ ## CLI reference
71
+
72
+ ```
73
+ Usage: gh-weekly-updates [OPTIONS]
74
+
75
+ Options:
76
+ --config PATH Path to YAML config file. Default: ./config.yaml
77
+ --since TEXT Start date (ISO 8601). Default: previous Monday.
78
+ --until TEXT End date (ISO 8601). Default: now.
79
+ --user TEXT GitHub username. Default: authenticated user.
80
+ --repos TEXT Comma-separated list of repos (owner/name).
81
+ --org TEXT GitHub org to scope repo discovery to.
82
+ --output PATH Write summary to a file instead of stdout.
83
+ --push TEXT Push summary to a GitHub repo (owner/name).
84
+ --model TEXT GitHub Model to use. Default: openai/gpt-4.1.
85
+ --verbose Enable debug logging.
86
+ --help Show this message and exit.
87
+ ```
88
+
89
+ ## Authentication
90
+
91
+ `gh-weekly-updates` resolves a GitHub token in this order:
92
+
93
+ 1. `GITHUB_TOKEN` environment variable
94
+ 2. `gh auth token` (GitHub CLI)
95
+
96
+ For GitHub Enterprise with SSO, ensure the token is authorised for your org.
97
+
98
+ ## Using with GitHub Actions
99
+
100
+ You can run `gh-weekly-updates` on a schedule in a GitHub Actions workflow:
101
+
102
+ ```yaml
103
+ name: Weekly Impact Summary
104
+
105
+ on:
106
+ schedule:
107
+ - cron: '0 9 * * 1' # Every Monday at 9am UTC
108
+ workflow_dispatch:
109
+
110
+ jobs:
111
+ summarise:
112
+ runs-on: ubuntu-latest
113
+ steps:
114
+ - uses: actions/checkout@v4
115
+
116
+ - uses: actions/setup-python@v5
117
+ with:
118
+ python-version: '3.12'
119
+
120
+ - name: Install gh-weekly-updates
121
+ run: pip install gh-weekly-updates
122
+
123
+ - name: Generate summary
124
+ env:
125
+ GITHUB_TOKEN: ${{ secrets.GH_PAT }}
126
+ run: |
127
+ gh-weekly-updates \
128
+ --config config.yaml \
129
+ --push my-user/my-updates
130
+ ```
131
+
132
+ > **Note**: The default `GITHUB_TOKEN` provided by Actions has limited scope.
133
+ > Use a [Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) stored as a repository secret with `repo` and `read:org` scopes, plus GitHub Models access.
134
+
135
+ ## Development
136
+
137
+ ```bash
138
+ git clone https://github.com/sahansera/gh-weekly-updates.git
139
+ cd gh-weekly-updates
140
+ python -m venv .venv && source .venv/bin/activate
141
+ make dev # install in editable mode with dev deps
142
+ make run # run with defaults
143
+ make lint # ruff check
144
+ ```
145
+
146
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for more details.
147
+
148
+ ## License
149
+
150
+ [MIT](LICENSE)
@@ -0,0 +1,54 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "gh-weekly-updates"
7
+ version = "0.1.0"
8
+ description = "Automatically discover and summarise your weekly GitHub impact"
9
+ requires-python = ">=3.11"
10
+ readme = "README.md"
11
+ license = {text = "MIT"}
12
+ keywords = ["github", "weekly", "impact", "summary", "engineering"]
13
+ classifiers = [
14
+ "Development Status :: 4 - Beta",
15
+ "Intended Audience :: Developers",
16
+ "License :: OSI Approved :: MIT License",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ "Programming Language :: Python :: 3.13",
21
+ "Topic :: Software Development",
22
+ ]
23
+ dependencies = [
24
+ "click>=8.1",
25
+ "httpx>=0.27",
26
+ "pydantic>=2.0",
27
+ "pyyaml>=6.0",
28
+ "rich>=13.0",
29
+ "openai>=1.30",
30
+ ]
31
+
32
+ [project.optional-dependencies]
33
+ dev = [
34
+ "ruff>=0.4",
35
+ "pytest>=8.0",
36
+ ]
37
+
38
+ [project.urls]
39
+ Homepage = "https://github.com/sahansera/gh-weekly-updates"
40
+ Repository = "https://github.com/sahansera/gh-weekly-updates"
41
+ Issues = "https://github.com/sahansera/gh-weekly-updates/issues"
42
+
43
+ [project.scripts]
44
+ gh-weekly-updates = "gh_weekly_updates.cli:main"
45
+
46
+ [tool.ruff]
47
+ target-version = "py311"
48
+ line-length = 100
49
+
50
+ [tool.ruff.lint]
51
+ select = ["E", "F", "I", "W"]
52
+
53
+ [tool.setuptools.packages.find]
54
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1 @@
1
+ """gh-weekly-updates — auto-discover and summarise your weekly GitHub contributions."""
@@ -0,0 +1,238 @@
1
+ """CLI entrypoint for gh-weekly-updates."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ import sys
7
+ from datetime import datetime, timedelta, timezone
8
+ from pathlib import Path
9
+
10
+ import click
11
+ import yaml
12
+ from rich.console import Console
13
+ from rich.logging import RichHandler
14
+ from rich.markdown import Markdown
15
+ from rich.panel import Panel
16
+
17
+ from gh_weekly_updates.collector import collect_activity
18
+ from gh_weekly_updates.config import get_github_token, get_github_username
19
+ from gh_weekly_updates.contributions import discover_repos
20
+ from gh_weekly_updates.publisher import publish_to_repo
21
+ from gh_weekly_updates.summariser import DEFAULT_MODEL, summarise
22
+
23
+ console = Console()
24
+
25
+ DEFAULT_CONFIG_PATH = "config.yaml"
26
+
27
+
28
+ def _load_config(path: str | None) -> dict:
29
+ """Load YAML config file. Returns empty dict if not found."""
30
+ config_path = Path(path) if path else Path(DEFAULT_CONFIG_PATH)
31
+ if config_path.exists():
32
+ with open(config_path) as f:
33
+ return yaml.safe_load(f) or {}
34
+ return {}
35
+
36
+
37
+ def _default_since() -> datetime:
38
+ """Return the previous Monday 00:00 UTC so we always cover at least a full week."""
39
+ now = datetime.now(timezone.utc)
40
+ today_midnight = now.replace(hour=0, minute=0, second=0, microsecond=0)
41
+ days_since_monday = now.weekday() # Monday=0
42
+ # Always go back to LAST week's Monday (7 + days_since_monday days back)
43
+ # e.g. Tuesday → 8 days back, Monday → 7 days back
44
+ return today_midnight - timedelta(days=days_since_monday + 7)
45
+
46
+
47
+ def _parse_date(value: str) -> datetime:
48
+ """Parse an ISO-8601 date string into a timezone-aware datetime."""
49
+ dt = datetime.fromisoformat(value)
50
+ if dt.tzinfo is None:
51
+ dt = dt.replace(tzinfo=timezone.utc)
52
+ return dt
53
+
54
+
55
+ @click.command()
56
+ @click.option(
57
+ "--config",
58
+ "config_path",
59
+ default=None,
60
+ type=click.Path(),
61
+ help="Path to YAML config file. Default: ./config.yaml",
62
+ )
63
+ @click.option(
64
+ "--since",
65
+ default=None,
66
+ help="Start date (ISO 8601). Default: Monday of previous week.",
67
+ )
68
+ @click.option(
69
+ "--until",
70
+ default=None,
71
+ help="End date (ISO 8601). Default: now.",
72
+ )
73
+ @click.option(
74
+ "--user",
75
+ default=None,
76
+ help="GitHub username. Default: authenticated user.",
77
+ )
78
+ @click.option(
79
+ "--repos",
80
+ default=None,
81
+ help="Comma-separated list of repos (owner/name). Skips auto-discovery.",
82
+ )
83
+ @click.option(
84
+ "--output",
85
+ default=None,
86
+ type=click.Path(),
87
+ help="Write summary to file instead of stdout.",
88
+ )
89
+ @click.option(
90
+ "--org",
91
+ default=None,
92
+ help="GitHub org to scope repo discovery to.",
93
+ )
94
+ @click.option(
95
+ "--push",
96
+ "push_repo",
97
+ default=None,
98
+ help="Push summary to a GitHub repo (owner/name).",
99
+ )
100
+ @click.option(
101
+ "--model",
102
+ default=DEFAULT_MODEL,
103
+ show_default=True,
104
+ help="GitHub Model to use for summarisation.",
105
+ )
106
+ @click.option(
107
+ "--verbose",
108
+ is_flag=True,
109
+ help="Enable debug logging.",
110
+ )
111
+ def main(
112
+ config_path: str | None,
113
+ since: str | None,
114
+ until: str | None,
115
+ user: str | None,
116
+ repos: str | None,
117
+ org: str | None,
118
+ push_repo: str | None,
119
+ output: str | None,
120
+ model: str,
121
+ verbose: bool,
122
+ ) -> None:
123
+ """Discover your weekly GitHub impact and generate a structured summary."""
124
+ # --- Load config ---
125
+ cfg = _load_config(config_path)
126
+
127
+ # CLI flags override config file values
128
+ org = org or cfg.get("org")
129
+ model = model if model != DEFAULT_MODEL else cfg.get("model", model)
130
+ push_repo = push_repo or cfg.get("push_repo")
131
+
132
+ # Custom prompt: inline in config or from a file
133
+ custom_prompt = cfg.get("prompt")
134
+ if not custom_prompt and cfg.get("prompt_file"):
135
+ prompt_path = Path(cfg["prompt_file"])
136
+ if prompt_path.exists():
137
+ custom_prompt = prompt_path.read_text()
138
+
139
+ # Repos: CLI --repos flag (comma-separated) > config file list
140
+ if repos:
141
+ repo_list_override = [r.strip() for r in repos.split(",") if r.strip()]
142
+ elif cfg.get("repos"):
143
+ repo_list_override = cfg["repos"]
144
+ else:
145
+ repo_list_override = None
146
+
147
+ # --- Logging ---
148
+ log_level = logging.DEBUG if verbose else logging.INFO
149
+ logging.basicConfig(
150
+ level=log_level,
151
+ format="%(message)s",
152
+ handlers=[RichHandler(rich_tracebacks=True, show_path=False)],
153
+ )
154
+ log = logging.getLogger("gh_weekly_updates")
155
+
156
+ # --- Auth ---
157
+ with console.status("[bold green]Authenticating with GitHub..."):
158
+ token = get_github_token()
159
+
160
+ # --- Resolve user ---
161
+ if not user:
162
+ with console.status("[bold green]Resolving GitHub username..."):
163
+ user = get_github_username(token)
164
+ console.print(f"[bold]User:[/bold] {user}")
165
+ if org:
166
+ console.print(f"[bold]Org:[/bold] {org}")
167
+
168
+ # --- Date range ---
169
+ since_dt = _parse_date(since) if since else _default_since()
170
+ until_dt = _parse_date(until) if until else datetime.now(timezone.utc)
171
+
172
+ console.print(
173
+ f"[bold]Period:[/bold] {since_dt.strftime('%Y-%m-%d')} → "
174
+ f"{until_dt.strftime('%Y-%m-%d %H:%M')} UTC"
175
+ )
176
+
177
+ # --- Resolve repos ---
178
+ if repo_list_override:
179
+ repo_list = repo_list_override
180
+ console.print(f"[bold]Using configured repos:[/bold] {len(repo_list)}")
181
+ else:
182
+ with console.status("[bold green]Discovering repos you contributed to..."):
183
+ repo_list = discover_repos(token, user, since_dt, until_dt, org=org)
184
+
185
+ if not repo_list:
186
+ console.print("[yellow]No repos found for this period. Nothing to summarise.[/yellow]")
187
+ sys.exit(0)
188
+
189
+ console.print(f"[bold]Repos:[/bold] {len(repo_list)}")
190
+ for r in repo_list:
191
+ console.print(f" • {r}")
192
+
193
+ # --- Collect activity ---
194
+ with console.status("[bold green]Collecting activity across repos..."):
195
+ activity = collect_activity(token, user, repo_list, since_dt, until_dt)
196
+
197
+ console.print(
198
+ Panel(
199
+ f"[bold]{activity.total_activities}[/bold] activities collected\n"
200
+ f" PRs authored: {len(activity.prs_authored)}\n"
201
+ f" PRs reviewed: {len(activity.prs_reviewed)}\n"
202
+ f" Issues created: {len(activity.issues_created)}\n"
203
+ f" Issue comments: {len(activity.issue_comments)}\n"
204
+ f" Discussions created: {len(activity.discussions_created)}\n"
205
+ f" Discussion comments: {len(activity.discussion_comments)}",
206
+ title="Activity Summary",
207
+ border_style="green",
208
+ )
209
+ )
210
+
211
+ if activity.total_activities == 0:
212
+ console.print("[yellow]No activities found. Nothing to summarise.[/yellow]")
213
+ sys.exit(0)
214
+
215
+ # --- Summarise ---
216
+ with console.status("[bold green]Generating impact summary via AI..."):
217
+ summary = summarise(activity, token, model, custom_prompt=custom_prompt)
218
+
219
+ # --- Output ---
220
+ if output:
221
+ with open(output, "w") as f:
222
+ f.write(summary)
223
+ console.print(f"\n[bold green]Summary written to {output}[/bold green]")
224
+ else:
225
+ console.print()
226
+ console.print(Markdown(summary))
227
+
228
+ # --- Push to repo ---
229
+ if push_repo:
230
+ with console.status(f"[bold green]Pushing to {push_repo}..."):
231
+ publish_to_repo(summary, push_repo, since_dt, until_dt)
232
+ console.print(
233
+ f"\n[bold green]Pushed to https://github.com/{push_repo}/tree/main/weekly-updates[/bold green]"
234
+ )
235
+
236
+
237
+ if __name__ == "__main__":
238
+ main()