pretty-release-notes 1.4.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.
- pretty_release_notes-1.4.0/LICENSE +7 -0
- pretty_release_notes-1.4.0/PKG-INFO +335 -0
- pretty_release_notes-1.4.0/README.md +295 -0
- pretty_release_notes-1.4.0/pretty_release_notes/__init__.py +38 -0
- pretty_release_notes-1.4.0/pretty_release_notes/__main__.py +6 -0
- pretty_release_notes-1.4.0/pretty_release_notes/adapters/__init__.py +1 -0
- pretty_release_notes-1.4.0/pretty_release_notes/adapters/cli_progress.py +25 -0
- pretty_release_notes-1.4.0/pretty_release_notes/api.py +239 -0
- pretty_release_notes-1.4.0/pretty_release_notes/core/__init__.py +1 -0
- pretty_release_notes-1.4.0/pretty_release_notes/core/config.py +166 -0
- pretty_release_notes-1.4.0/pretty_release_notes/core/config_loader.py +221 -0
- pretty_release_notes-1.4.0/pretty_release_notes/core/execution.py +74 -0
- pretty_release_notes-1.4.0/pretty_release_notes/core/interfaces.py +35 -0
- pretty_release_notes-1.4.0/pretty_release_notes/database.py +152 -0
- pretty_release_notes-1.4.0/pretty_release_notes/generator.py +317 -0
- pretty_release_notes-1.4.0/pretty_release_notes/github_client.py +232 -0
- pretty_release_notes-1.4.0/pretty_release_notes/main.py +245 -0
- pretty_release_notes-1.4.0/pretty_release_notes/models/__init__.py +15 -0
- pretty_release_notes-1.4.0/pretty_release_notes/models/_utils.py +47 -0
- pretty_release_notes-1.4.0/pretty_release_notes/models/change.py +34 -0
- pretty_release_notes-1.4.0/pretty_release_notes/models/commit.py +75 -0
- pretty_release_notes-1.4.0/pretty_release_notes/models/issue.py +17 -0
- pretty_release_notes-1.4.0/pretty_release_notes/models/pull_request.py +208 -0
- pretty_release_notes-1.4.0/pretty_release_notes/models/release_notes.py +241 -0
- pretty_release_notes-1.4.0/pretty_release_notes/models/release_notes_line.py +36 -0
- pretty_release_notes-1.4.0/pretty_release_notes/models/repository.py +20 -0
- pretty_release_notes-1.4.0/pretty_release_notes/openai_client.py +165 -0
- pretty_release_notes-1.4.0/pretty_release_notes/prompt.txt +34 -0
- pretty_release_notes-1.4.0/pretty_release_notes/py.typed +0 -0
- pretty_release_notes-1.4.0/pretty_release_notes/setup_command.py +336 -0
- pretty_release_notes-1.4.0/pretty_release_notes/ui.py +46 -0
- pretty_release_notes-1.4.0/pretty_release_notes/web/__init__.py +1 -0
- pretty_release_notes-1.4.0/pretty_release_notes/web/app.py +193 -0
- pretty_release_notes-1.4.0/pretty_release_notes/web/server.py +11 -0
- pretty_release_notes-1.4.0/pretty_release_notes.egg-info/PKG-INFO +335 -0
- pretty_release_notes-1.4.0/pretty_release_notes.egg-info/SOURCES.txt +53 -0
- pretty_release_notes-1.4.0/pretty_release_notes.egg-info/dependency_links.txt +1 -0
- pretty_release_notes-1.4.0/pretty_release_notes.egg-info/entry_points.txt +2 -0
- pretty_release_notes-1.4.0/pretty_release_notes.egg-info/requires.txt +18 -0
- pretty_release_notes-1.4.0/pretty_release_notes.egg-info/top_level.txt +1 -0
- pretty_release_notes-1.4.0/pyproject.toml +112 -0
- pretty_release_notes-1.4.0/setup.cfg +4 -0
- pretty_release_notes-1.4.0/tests/test_api.py +322 -0
- pretty_release_notes-1.4.0/tests/test_core.py +439 -0
- pretty_release_notes-1.4.0/tests/test_database.py +37 -0
- pretty_release_notes-1.4.0/tests/test_database_threading.py +261 -0
- pretty_release_notes-1.4.0/tests/test_execution.py +239 -0
- pretty_release_notes-1.4.0/tests/test_generator.py +184 -0
- pretty_release_notes-1.4.0/tests/test_main.py +109 -0
- pretty_release_notes-1.4.0/tests/test_models_utils.py +119 -0
- pretty_release_notes-1.4.0/tests/test_openai_client.py +167 -0
- pretty_release_notes-1.4.0/tests/test_pull_request.py +128 -0
- pretty_release_notes-1.4.0/tests/test_release_notes.py +637 -0
- pretty_release_notes-1.4.0/tests/test_setup_command.py +319 -0
- pretty_release_notes-1.4.0/tests/test_web_api.py +441 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright 2024 Raffael Meyer
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pretty-release-notes
|
|
3
|
+
Version: 1.4.0
|
|
4
|
+
Summary: Transform GitHub release notes with AI
|
|
5
|
+
Author: Raffael Meyer
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/alyf-de/pretty_release_notes
|
|
8
|
+
Project-URL: Documentation, https://github.com/alyf-de/pretty_release_notes#readme
|
|
9
|
+
Project-URL: Repository, https://github.com/alyf-de/pretty_release_notes
|
|
10
|
+
Project-URL: Issues, https://github.com/alyf-de/pretty_release_notes/issues
|
|
11
|
+
Keywords: github,release-notes,llm,cli
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
19
|
+
Classifier: Topic :: Text Processing :: Markup :: Markdown
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: typer~=0.24.0
|
|
24
|
+
Requires-Dist: rich~=15.0
|
|
25
|
+
Requires-Dist: requests~=2.33
|
|
26
|
+
Requires-Dist: python-dotenv~=1.2
|
|
27
|
+
Requires-Dist: tenacity~=9.1
|
|
28
|
+
Requires-Dist: any-llm-sdk[all]~=1.13
|
|
29
|
+
Provides-Extra: web
|
|
30
|
+
Requires-Dist: fastapi~=0.136.0; extra == "web"
|
|
31
|
+
Requires-Dist: uvicorn~=0.44.0; extra == "web"
|
|
32
|
+
Requires-Dist: pydantic~=2.13; extra == "web"
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: pytest~=9.0; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest-cov~=7.1; extra == "dev"
|
|
36
|
+
Requires-Dist: mypy~=1.20; extra == "dev"
|
|
37
|
+
Requires-Dist: ruff~=0.15.0; extra == "dev"
|
|
38
|
+
Requires-Dist: types-requests~=2.33.0.20260408; extra == "dev"
|
|
39
|
+
Dynamic: license-file
|
|
40
|
+
|
|
41
|
+
Turn GitHub's auto-generated release notes into human-readable sentences.
|
|
42
|
+
|
|
43
|
+
Go from this:
|
|
44
|
+
|
|
45
|
+

|
|
46
|
+
|
|
47
|
+
To this:
|
|
48
|
+
|
|
49
|
+

|
|
50
|
+
|
|
51
|
+
## Features
|
|
52
|
+
|
|
53
|
+
- **AI-Powered Summaries** - Converts technical PR titles into clear, user-friendly sentences
|
|
54
|
+
- **Smart Filtering** - Automatically excludes non-user-facing changes (chore, ci, refactor, test, style)
|
|
55
|
+
- **Revert Detection** - Automatically filters out PRs that were reverted within the same release
|
|
56
|
+
- **Backport Intelligence** - Reuses summaries from original PRs for backports, maintaining consistency
|
|
57
|
+
- **Author & Reviewer Attribution** - Credits human contributors while excluding bots
|
|
58
|
+
- **Intelligent Caching** - Stores generated summaries to avoid redundant API calls and reduce costs
|
|
59
|
+
- **Grouped Release Notes** - Optional grouping by conventional commit type (Features, Bug Fixes, Performance, etc.)
|
|
60
|
+
- **Multi-Mode Architecture** - Use as CLI tool, Python library, or REST API backend
|
|
61
|
+
- **Rich Context** - Incorporates PR descriptions, linked issues, and code diffs for accurate summaries
|
|
62
|
+
- **Interactive Setup** - Guided configuration with validation and migration from legacy formats
|
|
63
|
+
|
|
64
|
+
> [!NOTE]
|
|
65
|
+
> The default prompt is geared towards [ERPNext](https://github.com/frappe/erpnext) and the [Frappe Framework](https://github.com/frappe/frappe). If you want to use this for different projects, set your own `prompt_path` in `config.toml`.
|
|
66
|
+
|
|
67
|
+
## Configuration
|
|
68
|
+
|
|
69
|
+
### Interactive Setup (Recommended)
|
|
70
|
+
|
|
71
|
+
The easiest way to configure the tool is using the interactive setup command:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pretty-release-notes setup
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
This will:
|
|
78
|
+
- Guide you through all configuration options with helpful prompts
|
|
79
|
+
- Show sane defaults for each setting
|
|
80
|
+
- Create the config file at `~/.pretty-release-notes/config.toml`
|
|
81
|
+
|
|
82
|
+
**First-time migration from .env?** Use the `--migrate-env` flag:
|
|
83
|
+
```bash
|
|
84
|
+
pretty-release-notes setup --migrate-env
|
|
85
|
+
```
|
|
86
|
+
This will read your existing `.env` file and suggest those values as defaults.
|
|
87
|
+
|
|
88
|
+
### Manual Setup
|
|
89
|
+
|
|
90
|
+
Alternatively, copy `config.toml.example` to `~/.pretty-release-notes/config.toml` and fill in your credentials:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Create config directory
|
|
94
|
+
mkdir -p ~/.pretty-release-notes
|
|
95
|
+
|
|
96
|
+
# Copy example config
|
|
97
|
+
cp config.toml.example ~/.pretty-release-notes/config.toml
|
|
98
|
+
|
|
99
|
+
# Edit with your credentials
|
|
100
|
+
nano ~/.pretty-release-notes/config.toml
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Configuration Format
|
|
104
|
+
|
|
105
|
+
The configuration file uses TOML format with sections for GitHub credentials, LLM settings, database caching, and filters. The canonical section name is `[llm]`, while the legacy `[openai]` section is still accepted for backward compatibility. Prefer fully qualified `provider:model` values such as `openai:gpt-4.1`; unqualified model names are still accepted and default to OpenAI for backward compatibility. You can also set `reasoning_effort` to `none`, `low`, `medium`, `high`, or `xhigh` for supported models/providers. See [`config.toml.example`](config.toml.example) for the complete structure and all available options.
|
|
106
|
+
|
|
107
|
+
You can override the config location using the `--config-path` flag.
|
|
108
|
+
|
|
109
|
+
## Installation
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
# Clone the repository
|
|
113
|
+
git clone https://github.com/barredterra/pretty_release_notes
|
|
114
|
+
cd pretty_release_notes
|
|
115
|
+
|
|
116
|
+
# Create virtual environment and install
|
|
117
|
+
python -m venv env
|
|
118
|
+
source env/bin/activate
|
|
119
|
+
pip install -e .
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Usage
|
|
123
|
+
|
|
124
|
+
### CLI
|
|
125
|
+
|
|
126
|
+
After installation, you can use the CLI in several ways:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# View all commands
|
|
130
|
+
pretty-release-notes --help
|
|
131
|
+
|
|
132
|
+
# Generate release notes
|
|
133
|
+
pretty-release-notes generate erpnext v15.38.4 # using owner from config.toml
|
|
134
|
+
pretty-release-notes generate --owner alyf-de banking v0.0.1
|
|
135
|
+
|
|
136
|
+
# Use a custom config file
|
|
137
|
+
pretty-release-notes generate --config-path /path/to/config.toml erpnext v15.38.4
|
|
138
|
+
|
|
139
|
+
# Specify custom comparison range
|
|
140
|
+
pretty-release-notes generate erpnext v15.38.4 --previous-tag v15.38.0
|
|
141
|
+
|
|
142
|
+
# Override reasoning effort for a single run
|
|
143
|
+
pretty-release-notes generate erpnext v15.38.4 --reasoning-effort high
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Example output:
|
|
147
|
+
|
|
148
|
+
```markdown
|
|
149
|
+
---- Original ----
|
|
150
|
+
## What's Changed
|
|
151
|
+
* fix: list view and form status not same for purchase order (backport #43690) (backport #43692) by @mergify in https://github.com/frappe/erpnext/pull/43706
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
**Full Changelog**: https://github.com/frappe/erpnext/compare/v15.38.3...v15.38.4
|
|
155
|
+
|
|
156
|
+
---- Modified ----
|
|
157
|
+
## What's Changed
|
|
158
|
+
* Removes unnecessary decimal precision checks for _per_received_ and _per_billed_ fields in **Purchase Order**, so the list view status and form status remain consistent. https://github.com/frappe/erpnext/pull/43706
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
**Full Changelog**: https://github.com/frappe/erpnext/compare/v15.38.3...v15.38.4
|
|
162
|
+
**Authors**: @rohitwaghchaure
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Library Usage
|
|
166
|
+
|
|
167
|
+
You can also use `pretty_release_notes` as a Python library in your own projects:
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
from pretty_release_notes import ReleaseNotesBuilder
|
|
171
|
+
|
|
172
|
+
# Build a client with configuration
|
|
173
|
+
client = (
|
|
174
|
+
ReleaseNotesBuilder()
|
|
175
|
+
.with_github_token("ghp_your_token")
|
|
176
|
+
.with_llm(
|
|
177
|
+
"sk_your_key",
|
|
178
|
+
model="openai:gpt-4.1", # or model="anthropic:claude-sonnet-4-5"
|
|
179
|
+
reasoning_effort="medium",
|
|
180
|
+
)
|
|
181
|
+
.with_database("sqlite")
|
|
182
|
+
.with_filters(
|
|
183
|
+
exclude_types={"chore", "ci", "refactor"},
|
|
184
|
+
exclude_labels={"skip-release-notes"},
|
|
185
|
+
)
|
|
186
|
+
.build()
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
# Generate release notes
|
|
190
|
+
notes = client.generate_release_notes(
|
|
191
|
+
owner="frappe",
|
|
192
|
+
repo="erpnext",
|
|
193
|
+
tag="v15.38.4",
|
|
194
|
+
previous_tag_name="v15.38.0", # Optional: custom comparison range
|
|
195
|
+
)
|
|
196
|
+
print(notes)
|
|
197
|
+
|
|
198
|
+
# Optionally update on GitHub
|
|
199
|
+
client.update_github_release("frappe", "erpnext", "v15.38.4", notes)
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
For more examples, see [`examples/library_usage.py`](examples/library_usage.py).
|
|
203
|
+
|
|
204
|
+
### Web API
|
|
205
|
+
|
|
206
|
+
The tool can also be run as a REST API server for integration with web frontends.
|
|
207
|
+
|
|
208
|
+
#### Starting the Server
|
|
209
|
+
|
|
210
|
+
First, install the web dependencies:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
source env/bin/activate
|
|
214
|
+
pip install -e .[web]
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Then start the server:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
# Using uvicorn directly
|
|
221
|
+
python -m uvicorn pretty_release_notes.web.app:app --host 0.0.0.0 --port 8000
|
|
222
|
+
|
|
223
|
+
# Or using the provided server script
|
|
224
|
+
python -m pretty_release_notes.web.server
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
The API will be available at `http://localhost:8000` with interactive documentation at `http://localhost:8000/docs`.
|
|
228
|
+
|
|
229
|
+
#### API Endpoints
|
|
230
|
+
|
|
231
|
+
**Health Check**
|
|
232
|
+
```bash
|
|
233
|
+
curl http://localhost:8000/health
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**Create Release Notes Job**
|
|
237
|
+
```bash
|
|
238
|
+
curl -X POST http://localhost:8000/generate \
|
|
239
|
+
-H "Content-Type: application/json" \
|
|
240
|
+
-d '{
|
|
241
|
+
"owner": "frappe",
|
|
242
|
+
"repo": "erpnext",
|
|
243
|
+
"tag": "v15.38.4",
|
|
244
|
+
"previous_tag_name": "v15.38.0",
|
|
245
|
+
"github_token": "ghp_your_token_here",
|
|
246
|
+
"llm_key": "sk-your_key_here",
|
|
247
|
+
"llm_model": "openai:gpt-4.1",
|
|
248
|
+
"reasoning_effort": "medium",
|
|
249
|
+
"exclude_types": ["chore", "ci", "refactor"],
|
|
250
|
+
"exclude_labels": ["skip-release-notes"],
|
|
251
|
+
"exclude_authors": ["dependabot[bot]"],
|
|
252
|
+
"no_read": false,
|
|
253
|
+
"no_write": false
|
|
254
|
+
}'
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Legacy `openai_key`, `openai_model`, and `openai_reasoning_effort` request fields are still accepted for backward compatibility. Use `no_database` to skip both cache reads and writes.
|
|
258
|
+
|
|
259
|
+
Response:
|
|
260
|
+
```json
|
|
261
|
+
{
|
|
262
|
+
"job_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
263
|
+
"status": "pending",
|
|
264
|
+
"created_at": "2025-01-19T10:30:00.000000"
|
|
265
|
+
}
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**Check Job Status**
|
|
269
|
+
```bash
|
|
270
|
+
curl http://localhost:8000/jobs/{job_id}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
Response:
|
|
274
|
+
```json
|
|
275
|
+
{
|
|
276
|
+
"job_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
277
|
+
"status": "completed",
|
|
278
|
+
"created_at": "2025-01-19T10:30:00.000000",
|
|
279
|
+
"completed_at": "2025-01-19T10:30:15.000000",
|
|
280
|
+
"result": "## What's Changed\n* Fixed bug...",
|
|
281
|
+
"progress": [
|
|
282
|
+
{
|
|
283
|
+
"timestamp": "2025-01-19T10:30:05.000000",
|
|
284
|
+
"type": "success",
|
|
285
|
+
"message": "Downloaded PRs in 0.42 seconds."
|
|
286
|
+
}
|
|
287
|
+
],
|
|
288
|
+
"error": null
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### Automated Polling
|
|
293
|
+
|
|
294
|
+
Run release note generation automatically whenever a new release is published. Add the repos you want to watch to your config:
|
|
295
|
+
|
|
296
|
+
```toml
|
|
297
|
+
[poll]
|
|
298
|
+
repos = ["frappe/erpnext", "frappe/frappe"]
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Then set it up:
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
# Seed state with current releases (so existing ones aren't reprocessed)
|
|
305
|
+
pretty-release-notes poll --seed
|
|
306
|
+
|
|
307
|
+
# Install a cron job that polls every 15 minutes
|
|
308
|
+
pretty-release-notes poll --install-cron
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
You can also run a single poll cycle manually:
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
pretty-release-notes poll
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
The poll command uses the same config, database, and filters as `generate`. Processed releases are tracked in `~/.pretty-release-notes/processed_releases.json`.
|
|
318
|
+
|
|
319
|
+
## Authors and Reviewers
|
|
320
|
+
|
|
321
|
+
The authors and reviewers of the PRs are added to the release notes.
|
|
322
|
+
|
|
323
|
+
- An author who reviewed or merged their own PR or backport is not a reviewer.
|
|
324
|
+
- A non-author who reviewed or merged someone else's PR is a reviewer.
|
|
325
|
+
- The author of the original PR is also the author of the backport.
|
|
326
|
+
|
|
327
|
+
## Backports
|
|
328
|
+
|
|
329
|
+
We try to use the same message for backports as for the original PR. For this, we look for `(backport #<number>)` _at the end_ of the PR title and check if we have existing messages for that PR in our database. If we do, we use the message for the original PR. If we don't, we create a new message for the backport.
|
|
330
|
+
|
|
331
|
+
This means that backports of backports are currently not supported / will get a new message. To get the same message, PRs must be a direct backport of the original PR.
|
|
332
|
+
|
|
333
|
+
## Contributing
|
|
334
|
+
|
|
335
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, testing, code quality tools, and commit conventions.
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
Turn GitHub's auto-generated release notes into human-readable sentences.
|
|
2
|
+
|
|
3
|
+
Go from this:
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
To this:
|
|
8
|
+
|
|
9
|
+

|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **AI-Powered Summaries** - Converts technical PR titles into clear, user-friendly sentences
|
|
14
|
+
- **Smart Filtering** - Automatically excludes non-user-facing changes (chore, ci, refactor, test, style)
|
|
15
|
+
- **Revert Detection** - Automatically filters out PRs that were reverted within the same release
|
|
16
|
+
- **Backport Intelligence** - Reuses summaries from original PRs for backports, maintaining consistency
|
|
17
|
+
- **Author & Reviewer Attribution** - Credits human contributors while excluding bots
|
|
18
|
+
- **Intelligent Caching** - Stores generated summaries to avoid redundant API calls and reduce costs
|
|
19
|
+
- **Grouped Release Notes** - Optional grouping by conventional commit type (Features, Bug Fixes, Performance, etc.)
|
|
20
|
+
- **Multi-Mode Architecture** - Use as CLI tool, Python library, or REST API backend
|
|
21
|
+
- **Rich Context** - Incorporates PR descriptions, linked issues, and code diffs for accurate summaries
|
|
22
|
+
- **Interactive Setup** - Guided configuration with validation and migration from legacy formats
|
|
23
|
+
|
|
24
|
+
> [!NOTE]
|
|
25
|
+
> The default prompt is geared towards [ERPNext](https://github.com/frappe/erpnext) and the [Frappe Framework](https://github.com/frappe/frappe). If you want to use this for different projects, set your own `prompt_path` in `config.toml`.
|
|
26
|
+
|
|
27
|
+
## Configuration
|
|
28
|
+
|
|
29
|
+
### Interactive Setup (Recommended)
|
|
30
|
+
|
|
31
|
+
The easiest way to configure the tool is using the interactive setup command:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pretty-release-notes setup
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
This will:
|
|
38
|
+
- Guide you through all configuration options with helpful prompts
|
|
39
|
+
- Show sane defaults for each setting
|
|
40
|
+
- Create the config file at `~/.pretty-release-notes/config.toml`
|
|
41
|
+
|
|
42
|
+
**First-time migration from .env?** Use the `--migrate-env` flag:
|
|
43
|
+
```bash
|
|
44
|
+
pretty-release-notes setup --migrate-env
|
|
45
|
+
```
|
|
46
|
+
This will read your existing `.env` file and suggest those values as defaults.
|
|
47
|
+
|
|
48
|
+
### Manual Setup
|
|
49
|
+
|
|
50
|
+
Alternatively, copy `config.toml.example` to `~/.pretty-release-notes/config.toml` and fill in your credentials:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Create config directory
|
|
54
|
+
mkdir -p ~/.pretty-release-notes
|
|
55
|
+
|
|
56
|
+
# Copy example config
|
|
57
|
+
cp config.toml.example ~/.pretty-release-notes/config.toml
|
|
58
|
+
|
|
59
|
+
# Edit with your credentials
|
|
60
|
+
nano ~/.pretty-release-notes/config.toml
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Configuration Format
|
|
64
|
+
|
|
65
|
+
The configuration file uses TOML format with sections for GitHub credentials, LLM settings, database caching, and filters. The canonical section name is `[llm]`, while the legacy `[openai]` section is still accepted for backward compatibility. Prefer fully qualified `provider:model` values such as `openai:gpt-4.1`; unqualified model names are still accepted and default to OpenAI for backward compatibility. You can also set `reasoning_effort` to `none`, `low`, `medium`, `high`, or `xhigh` for supported models/providers. See [`config.toml.example`](config.toml.example) for the complete structure and all available options.
|
|
66
|
+
|
|
67
|
+
You can override the config location using the `--config-path` flag.
|
|
68
|
+
|
|
69
|
+
## Installation
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Clone the repository
|
|
73
|
+
git clone https://github.com/barredterra/pretty_release_notes
|
|
74
|
+
cd pretty_release_notes
|
|
75
|
+
|
|
76
|
+
# Create virtual environment and install
|
|
77
|
+
python -m venv env
|
|
78
|
+
source env/bin/activate
|
|
79
|
+
pip install -e .
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Usage
|
|
83
|
+
|
|
84
|
+
### CLI
|
|
85
|
+
|
|
86
|
+
After installation, you can use the CLI in several ways:
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
# View all commands
|
|
90
|
+
pretty-release-notes --help
|
|
91
|
+
|
|
92
|
+
# Generate release notes
|
|
93
|
+
pretty-release-notes generate erpnext v15.38.4 # using owner from config.toml
|
|
94
|
+
pretty-release-notes generate --owner alyf-de banking v0.0.1
|
|
95
|
+
|
|
96
|
+
# Use a custom config file
|
|
97
|
+
pretty-release-notes generate --config-path /path/to/config.toml erpnext v15.38.4
|
|
98
|
+
|
|
99
|
+
# Specify custom comparison range
|
|
100
|
+
pretty-release-notes generate erpnext v15.38.4 --previous-tag v15.38.0
|
|
101
|
+
|
|
102
|
+
# Override reasoning effort for a single run
|
|
103
|
+
pretty-release-notes generate erpnext v15.38.4 --reasoning-effort high
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Example output:
|
|
107
|
+
|
|
108
|
+
```markdown
|
|
109
|
+
---- Original ----
|
|
110
|
+
## What's Changed
|
|
111
|
+
* fix: list view and form status not same for purchase order (backport #43690) (backport #43692) by @mergify in https://github.com/frappe/erpnext/pull/43706
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
**Full Changelog**: https://github.com/frappe/erpnext/compare/v15.38.3...v15.38.4
|
|
115
|
+
|
|
116
|
+
---- Modified ----
|
|
117
|
+
## What's Changed
|
|
118
|
+
* Removes unnecessary decimal precision checks for _per_received_ and _per_billed_ fields in **Purchase Order**, so the list view status and form status remain consistent. https://github.com/frappe/erpnext/pull/43706
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
**Full Changelog**: https://github.com/frappe/erpnext/compare/v15.38.3...v15.38.4
|
|
122
|
+
**Authors**: @rohitwaghchaure
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Library Usage
|
|
126
|
+
|
|
127
|
+
You can also use `pretty_release_notes` as a Python library in your own projects:
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from pretty_release_notes import ReleaseNotesBuilder
|
|
131
|
+
|
|
132
|
+
# Build a client with configuration
|
|
133
|
+
client = (
|
|
134
|
+
ReleaseNotesBuilder()
|
|
135
|
+
.with_github_token("ghp_your_token")
|
|
136
|
+
.with_llm(
|
|
137
|
+
"sk_your_key",
|
|
138
|
+
model="openai:gpt-4.1", # or model="anthropic:claude-sonnet-4-5"
|
|
139
|
+
reasoning_effort="medium",
|
|
140
|
+
)
|
|
141
|
+
.with_database("sqlite")
|
|
142
|
+
.with_filters(
|
|
143
|
+
exclude_types={"chore", "ci", "refactor"},
|
|
144
|
+
exclude_labels={"skip-release-notes"},
|
|
145
|
+
)
|
|
146
|
+
.build()
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
# Generate release notes
|
|
150
|
+
notes = client.generate_release_notes(
|
|
151
|
+
owner="frappe",
|
|
152
|
+
repo="erpnext",
|
|
153
|
+
tag="v15.38.4",
|
|
154
|
+
previous_tag_name="v15.38.0", # Optional: custom comparison range
|
|
155
|
+
)
|
|
156
|
+
print(notes)
|
|
157
|
+
|
|
158
|
+
# Optionally update on GitHub
|
|
159
|
+
client.update_github_release("frappe", "erpnext", "v15.38.4", notes)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
For more examples, see [`examples/library_usage.py`](examples/library_usage.py).
|
|
163
|
+
|
|
164
|
+
### Web API
|
|
165
|
+
|
|
166
|
+
The tool can also be run as a REST API server for integration with web frontends.
|
|
167
|
+
|
|
168
|
+
#### Starting the Server
|
|
169
|
+
|
|
170
|
+
First, install the web dependencies:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
source env/bin/activate
|
|
174
|
+
pip install -e .[web]
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Then start the server:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Using uvicorn directly
|
|
181
|
+
python -m uvicorn pretty_release_notes.web.app:app --host 0.0.0.0 --port 8000
|
|
182
|
+
|
|
183
|
+
# Or using the provided server script
|
|
184
|
+
python -m pretty_release_notes.web.server
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
The API will be available at `http://localhost:8000` with interactive documentation at `http://localhost:8000/docs`.
|
|
188
|
+
|
|
189
|
+
#### API Endpoints
|
|
190
|
+
|
|
191
|
+
**Health Check**
|
|
192
|
+
```bash
|
|
193
|
+
curl http://localhost:8000/health
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**Create Release Notes Job**
|
|
197
|
+
```bash
|
|
198
|
+
curl -X POST http://localhost:8000/generate \
|
|
199
|
+
-H "Content-Type: application/json" \
|
|
200
|
+
-d '{
|
|
201
|
+
"owner": "frappe",
|
|
202
|
+
"repo": "erpnext",
|
|
203
|
+
"tag": "v15.38.4",
|
|
204
|
+
"previous_tag_name": "v15.38.0",
|
|
205
|
+
"github_token": "ghp_your_token_here",
|
|
206
|
+
"llm_key": "sk-your_key_here",
|
|
207
|
+
"llm_model": "openai:gpt-4.1",
|
|
208
|
+
"reasoning_effort": "medium",
|
|
209
|
+
"exclude_types": ["chore", "ci", "refactor"],
|
|
210
|
+
"exclude_labels": ["skip-release-notes"],
|
|
211
|
+
"exclude_authors": ["dependabot[bot]"],
|
|
212
|
+
"no_read": false,
|
|
213
|
+
"no_write": false
|
|
214
|
+
}'
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Legacy `openai_key`, `openai_model`, and `openai_reasoning_effort` request fields are still accepted for backward compatibility. Use `no_database` to skip both cache reads and writes.
|
|
218
|
+
|
|
219
|
+
Response:
|
|
220
|
+
```json
|
|
221
|
+
{
|
|
222
|
+
"job_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
223
|
+
"status": "pending",
|
|
224
|
+
"created_at": "2025-01-19T10:30:00.000000"
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**Check Job Status**
|
|
229
|
+
```bash
|
|
230
|
+
curl http://localhost:8000/jobs/{job_id}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Response:
|
|
234
|
+
```json
|
|
235
|
+
{
|
|
236
|
+
"job_id": "550e8400-e29b-41d4-a716-446655440000",
|
|
237
|
+
"status": "completed",
|
|
238
|
+
"created_at": "2025-01-19T10:30:00.000000",
|
|
239
|
+
"completed_at": "2025-01-19T10:30:15.000000",
|
|
240
|
+
"result": "## What's Changed\n* Fixed bug...",
|
|
241
|
+
"progress": [
|
|
242
|
+
{
|
|
243
|
+
"timestamp": "2025-01-19T10:30:05.000000",
|
|
244
|
+
"type": "success",
|
|
245
|
+
"message": "Downloaded PRs in 0.42 seconds."
|
|
246
|
+
}
|
|
247
|
+
],
|
|
248
|
+
"error": null
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Automated Polling
|
|
253
|
+
|
|
254
|
+
Run release note generation automatically whenever a new release is published. Add the repos you want to watch to your config:
|
|
255
|
+
|
|
256
|
+
```toml
|
|
257
|
+
[poll]
|
|
258
|
+
repos = ["frappe/erpnext", "frappe/frappe"]
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Then set it up:
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
# Seed state with current releases (so existing ones aren't reprocessed)
|
|
265
|
+
pretty-release-notes poll --seed
|
|
266
|
+
|
|
267
|
+
# Install a cron job that polls every 15 minutes
|
|
268
|
+
pretty-release-notes poll --install-cron
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
You can also run a single poll cycle manually:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
pretty-release-notes poll
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
The poll command uses the same config, database, and filters as `generate`. Processed releases are tracked in `~/.pretty-release-notes/processed_releases.json`.
|
|
278
|
+
|
|
279
|
+
## Authors and Reviewers
|
|
280
|
+
|
|
281
|
+
The authors and reviewers of the PRs are added to the release notes.
|
|
282
|
+
|
|
283
|
+
- An author who reviewed or merged their own PR or backport is not a reviewer.
|
|
284
|
+
- A non-author who reviewed or merged someone else's PR is a reviewer.
|
|
285
|
+
- The author of the original PR is also the author of the backport.
|
|
286
|
+
|
|
287
|
+
## Backports
|
|
288
|
+
|
|
289
|
+
We try to use the same message for backports as for the original PR. For this, we look for `(backport #<number>)` _at the end_ of the PR title and check if we have existing messages for that PR in our database. If we do, we use the message for the original PR. If we don't, we create a new message for the backport.
|
|
290
|
+
|
|
291
|
+
This means that backports of backports are currently not supported / will get a new message. To get the same message, PRs must be a direct backport of the original PR.
|
|
292
|
+
|
|
293
|
+
## Contributing
|
|
294
|
+
|
|
295
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, testing, code quality tools, and commit conventions.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Pretty Release Notes - Transform GitHub release notes with AI."""
|
|
2
|
+
|
|
3
|
+
# Public API exports for library usage
|
|
4
|
+
from .api import ReleaseNotesBuilder, ReleaseNotesClient
|
|
5
|
+
from .core.config import (
|
|
6
|
+
DatabaseConfig,
|
|
7
|
+
FilterConfig,
|
|
8
|
+
GitHubConfig,
|
|
9
|
+
LLMConfig,
|
|
10
|
+
OpenAIConfig,
|
|
11
|
+
ReleaseNotesConfig,
|
|
12
|
+
)
|
|
13
|
+
from .core.interfaces import (
|
|
14
|
+
CompositeProgressReporter,
|
|
15
|
+
NullProgressReporter,
|
|
16
|
+
ProgressEvent,
|
|
17
|
+
ProgressReporter,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__version__ = "1.4.0"
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
# Client classes
|
|
24
|
+
"ReleaseNotesBuilder",
|
|
25
|
+
"ReleaseNotesClient",
|
|
26
|
+
# Configuration
|
|
27
|
+
"ReleaseNotesConfig",
|
|
28
|
+
"GitHubConfig",
|
|
29
|
+
"LLMConfig",
|
|
30
|
+
"OpenAIConfig",
|
|
31
|
+
"DatabaseConfig",
|
|
32
|
+
"FilterConfig",
|
|
33
|
+
# Progress reporting
|
|
34
|
+
"ProgressReporter",
|
|
35
|
+
"ProgressEvent",
|
|
36
|
+
"NullProgressReporter",
|
|
37
|
+
"CompositeProgressReporter",
|
|
38
|
+
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Adapters for integrating core abstractions with external systems."""
|