pr-decorator 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.
- pr_decorator-0.1.0/LICENSE +21 -0
- pr_decorator-0.1.0/PKG-INFO +315 -0
- pr_decorator-0.1.0/README.md +287 -0
- pr_decorator-0.1.0/agent/__init__.py +5 -0
- pr_decorator-0.1.0/agent/execute.py +209 -0
- pr_decorator-0.1.0/agent/loop.py +105 -0
- pr_decorator-0.1.0/agent/models.py +107 -0
- pr_decorator-0.1.0/agent/observe.py +92 -0
- pr_decorator-0.1.0/agent/plan.py +74 -0
- pr_decorator-0.1.0/agent/render.py +33 -0
- pr_decorator-0.1.0/agent/validate.py +77 -0
- pr_decorator-0.1.0/main.py +173 -0
- pr_decorator-0.1.0/pr_decorator.egg-info/PKG-INFO +315 -0
- pr_decorator-0.1.0/pr_decorator.egg-info/SOURCES.txt +23 -0
- pr_decorator-0.1.0/pr_decorator.egg-info/dependency_links.txt +1 -0
- pr_decorator-0.1.0/pr_decorator.egg-info/entry_points.txt +2 -0
- pr_decorator-0.1.0/pr_decorator.egg-info/requires.txt +5 -0
- pr_decorator-0.1.0/pr_decorator.egg-info/top_level.txt +3 -0
- pr_decorator-0.1.0/prompts/__init__.py +1 -0
- pr_decorator-0.1.0/prompts/mr_template.txt +44 -0
- pr_decorator-0.1.0/pyproject.toml +72 -0
- pr_decorator-0.1.0/setup.cfg +4 -0
- pr_decorator-0.1.0/tests/test_loop.py +58 -0
- pr_decorator-0.1.0/tests/test_observe.py +43 -0
- pr_decorator-0.1.0/tests/test_plan_validate.py +45 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kunal
|
|
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,315 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pr-decorator
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Agentic system that decorates Pull/Merge Requests into a standardized MR report via AWS Bedrock (Amazon Nova Pro).
|
|
5
|
+
Author-email: Kunal Jha <kunaljha5@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/kunaljha5/pr-decorator
|
|
8
|
+
Project-URL: Repository, https://github.com/kunaljha5/pr-decorator
|
|
9
|
+
Project-URL: Issues, https://github.com/kunaljha5/pr-decorator/issues
|
|
10
|
+
Keywords: pull-request,merge-request,code-review,aws,bedrock,nova,git,automation,agent
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Software Development :: Version Control :: Git
|
|
19
|
+
Classifier: Operating System :: OS Independent
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: boto3>=1.34
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
26
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
27
|
+
Dynamic: license-file
|
|
28
|
+
|
|
29
|
+
# PR Decorator Agent — Primary Instructions
|
|
30
|
+
|
|
31
|
+
## Project Overview
|
|
32
|
+
An agentic AI system powered by **AWS Bedrock** that automatically decorates Pull Requests (Merge Requests) by following a structured observe → plan → execute → observe loop, and generates a standardized MR report as output.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Agent Loop (Core Behavior)
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
OBSERVE → PLAN → EXECUTE → OBSERVE → (if outcome OK) → FINISH & GENERATE OUTPUT
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
| Phase | Description |
|
|
43
|
+
|-------------|-------------|
|
|
44
|
+
| **Observe** | Read the raw diff, commits, branch name, ticket references, and any existing MR metadata |
|
|
45
|
+
| **Plan** | Decide what sections need to be filled, what code changes occurred, what categories they fall into |
|
|
46
|
+
| **Execute** | Call AWS Bedrock (Claude/Titan/etc.) to generate each section of the MR description |
|
|
47
|
+
| **Observe** | Validate the generated output — check for completeness, correctness, and formatting |
|
|
48
|
+
| **Finish** | If output passes validation, finalize and post/return the decorated MR |
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## MR Output Template
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
MR Title : <concise, imperative-mood title>
|
|
56
|
+
MR Description :
|
|
57
|
+
Purpose : <why this MR exists — business/technical reason>
|
|
58
|
+
Ticket ID : <linked issue/ticket e.g. JIRA-123>
|
|
59
|
+
Code Changes : <summary of what files/modules changed and how>
|
|
60
|
+
Features Added: <new capabilities introduced, if any>
|
|
61
|
+
Linting Fixed : <style/formatting/lint issues resolved, if any>
|
|
62
|
+
Bug Fixed : <bugs resolved with brief description, if any>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Primary Instructions for the Agent
|
|
68
|
+
|
|
69
|
+
### 1. Input Collection (Observe Phase)
|
|
70
|
+
- Accept a **git diff** or list of changed files as primary input
|
|
71
|
+
- Accept optional metadata: branch name, commit messages, linked ticket ID
|
|
72
|
+
- Accept optional: existing MR title/description (for enrichment mode)
|
|
73
|
+
|
|
74
|
+
### 2. Analysis & Planning (Plan Phase)
|
|
75
|
+
- Parse the diff to classify changes:
|
|
76
|
+
- New files → Features Added
|
|
77
|
+
- Modified logic → Code Changes or Bug Fixed
|
|
78
|
+
- Formatting/style-only changes → Linting Fixed
|
|
79
|
+
- Config/dependency changes → Code Changes
|
|
80
|
+
- Extract ticket ID from branch name or commit message (e.g. `feat/JIRA-123-...`)
|
|
81
|
+
- Infer the purpose from commit messages and change patterns
|
|
82
|
+
|
|
83
|
+
### 3. Generation (Execute Phase)
|
|
84
|
+
- Call **AWS Bedrock** with a structured prompt per section
|
|
85
|
+
- Use a system prompt that enforces the MR template format
|
|
86
|
+
- Generate each section independently or in a single structured call
|
|
87
|
+
- Keep descriptions concise, technical, and developer-friendly
|
|
88
|
+
|
|
89
|
+
### 4. Validation (Observe Phase — Post Execute)
|
|
90
|
+
- Check all required fields are populated (no empty sections)
|
|
91
|
+
- Ensure Ticket ID is present (warn if missing)
|
|
92
|
+
- Ensure MR Title follows imperative mood convention (e.g. "Add", "Fix", "Refactor")
|
|
93
|
+
- If any section is empty or invalid → re-plan and re-execute that section only
|
|
94
|
+
|
|
95
|
+
### 5. Output Generation (Finish Phase)
|
|
96
|
+
- Output the final decorated MR as:
|
|
97
|
+
- Markdown string (for GitLab/GitHub MR body)
|
|
98
|
+
- Optionally: JSON payload for API submission
|
|
99
|
+
- Log a brief agent trace: what was observed, planned, executed, and validated
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## AWS Bedrock Integration
|
|
104
|
+
|
|
105
|
+
- **Model**: Amazon **Nova Pro** via Bedrock. Default model id is the APAC
|
|
106
|
+
cross-region inference profile `apac.amazon.nova-pro-v1:0` (required to call
|
|
107
|
+
Nova in `ap-south-1`). Override with the `BEDROCK_MODEL_ID` env var or the
|
|
108
|
+
`--model` flag (e.g. `amazon.nova-pro-v1:0` / `us.amazon.nova-pro-v1:0` in US regions).
|
|
109
|
+
- **Invocation**: Uses `bedrock-runtime` → `converse` API (model-agnostic).
|
|
110
|
+
- **Prompt Strategy**: Strict output-format enforcement via `prompts/mr_template.txt`.
|
|
111
|
+
- **Region**: Configurable. Default `ap-south-1`; override with `BEDROCK_REGION` /
|
|
112
|
+
`AWS_REGION` env var or the `--region` flag.
|
|
113
|
+
- **Auth**: IAM Role / AWS credential chain (no hardcoded keys).
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Non-Functional Requirements
|
|
118
|
+
|
|
119
|
+
- The agent must be **stateless** — each PR decoration is an independent run
|
|
120
|
+
- Support **retry logic** (max 2 retries) if Bedrock call fails
|
|
121
|
+
- Output must always conform to the MR template — no freeform deviation
|
|
122
|
+
- Agent trace/log must be saved alongside output for debugging
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## File Structure (Suggested)
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
pr-decorator/
|
|
130
|
+
├── instruction.md ← this file
|
|
131
|
+
├── agent/
|
|
132
|
+
│ ├── observe.py ← diff parsing & input collection
|
|
133
|
+
│ ├── plan.py ← change classification & section planning
|
|
134
|
+
│ ├── execute.py ← AWS Bedrock call & prompt management
|
|
135
|
+
│ ├── validate.py ← output validation logic
|
|
136
|
+
│ └── loop.py ← orchestrates observe→plan→execute→observe
|
|
137
|
+
├── prompts/
|
|
138
|
+
│ └── mr_template.txt ← system prompt with MR template
|
|
139
|
+
├── output/
|
|
140
|
+
│ └── mr_report.md ← generated MR decoration output
|
|
141
|
+
└── main.py ← entry point
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Local Setup — Build & Validate
|
|
147
|
+
|
|
148
|
+
### 1. Prerequisites
|
|
149
|
+
- Python **3.12** (see `.python-version`).
|
|
150
|
+
- [`uv`](https://docs.astral.sh/uv/) (recommended) or plain `venv` + `pip`.
|
|
151
|
+
- AWS credentials with Bedrock access in your target region, and **model access
|
|
152
|
+
to Amazon Nova Pro enabled** in the Bedrock console
|
|
153
|
+
(*Bedrock → Model access → Nova Pro*).
|
|
154
|
+
|
|
155
|
+
### 2. Build (create venv + install)
|
|
156
|
+
|
|
157
|
+
With `uv`:
|
|
158
|
+
```bash
|
|
159
|
+
uv venv --python 3.12 .venv
|
|
160
|
+
uv pip install -e ".[dev]"
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Or with stock Python:
|
|
164
|
+
```bash
|
|
165
|
+
python3.12 -m venv .venv
|
|
166
|
+
source .venv/bin/activate
|
|
167
|
+
pip install -e ".[dev]"
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### 3. Configure AWS
|
|
171
|
+
|
|
172
|
+
Auth uses the standard credential chain — **never hardcode keys**. Any of:
|
|
173
|
+
```bash
|
|
174
|
+
aws configure # writes ~/.aws/credentials + config
|
|
175
|
+
# or
|
|
176
|
+
aws sso login --profile <p> && export AWS_PROFILE=<p>
|
|
177
|
+
# or export AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Optional overrides (defaults shown):
|
|
181
|
+
```bash
|
|
182
|
+
export BEDROCK_REGION=ap-south-1
|
|
183
|
+
export BEDROCK_MODEL_ID=apac.amazon.nova-pro-v1:0
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
Verify credentials + Bedrock reachability before running the agent:
|
|
187
|
+
```bash
|
|
188
|
+
.venv/bin/python -c "import boto3; print(boto3.client('sts', region_name='ap-south-1').get_caller_identity()['Account'])"
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### 4. Run
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# Zero-arg: auto-detect base (origin/main → main → master), diff the current
|
|
195
|
+
# branch against it, and auto-fill branch + commit messages. Just run:
|
|
196
|
+
uv run main.py
|
|
197
|
+
# (or: .venv/bin/python main.py)
|
|
198
|
+
|
|
199
|
+
# Override the range / branch / ticket explicitly:
|
|
200
|
+
.venv/bin/python main.py --range origin/main...HEAD --branch "$(git branch --show-current)"
|
|
201
|
+
|
|
202
|
+
# Or pipe any diff in:
|
|
203
|
+
git diff origin/main | .venv/bin/python main.py --format markdown
|
|
204
|
+
|
|
205
|
+
# From a saved diff file, JSON output, with an explicit ticket:
|
|
206
|
+
.venv/bin/python main.py --diff-file changes.diff --ticket-id PRD-1 --format json
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Useful flags: `--model`, `--region`, `--format {markdown,json}`, `--no-write`
|
|
210
|
+
(print only, skip writing to `output/`), `--context-lines N` (context lines for
|
|
211
|
+
`git diff --unified` on `--range`; the large default feeds whole-file content to
|
|
212
|
+
the LLM so it can judge intent — lower it for very large PRs). Content size is
|
|
213
|
+
capped via `MR_MAX_FILE_CHARS` / `MR_MAX_TOTAL_CHARS` env vars.
|
|
214
|
+
|
|
215
|
+
### 5. Validate it worked
|
|
216
|
+
|
|
217
|
+
A successful run:
|
|
218
|
+
- exits with code **0** (non-zero means a required section failed validation),
|
|
219
|
+
- prints the decorated MR to stdout, and
|
|
220
|
+
- writes `output/mr_report.md` (or `.json`) **and** `output/agent_trace.json`.
|
|
221
|
+
|
|
222
|
+
Check the trace to confirm the Bedrock call landed — look for an `execute`
|
|
223
|
+
entry with `"ok": true` and a `finish` entry with `"ok": true`:
|
|
224
|
+
```bash
|
|
225
|
+
cat output/agent_trace.json
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Smoke-test the full loop **offline** (no AWS needed) with a stubbed client:
|
|
229
|
+
```bash
|
|
230
|
+
.venv/bin/python - <<'PY'
|
|
231
|
+
from agent import loop, render
|
|
232
|
+
from agent.execute import BedrockExecutor
|
|
233
|
+
|
|
234
|
+
class Stub:
|
|
235
|
+
def converse(self, **kw):
|
|
236
|
+
payload = '{"title":"Add feature","sections":{"Purpose":"x","Ticket ID":"PRD-1","Code Changes":"y","Features Added":"","Linting Fixed":"","Bug Fixed":""}}'
|
|
237
|
+
return {"output": {"message": {"content": [{"text": payload}]}}}
|
|
238
|
+
|
|
239
|
+
res = loop.run("diff --git a/f b/f\n+x\n", executor=BedrockExecutor(client=Stub()), branch="feat/PRD-1")
|
|
240
|
+
print(render.to_markdown(res.report))
|
|
241
|
+
print("ok:", res.validation.ok)
|
|
242
|
+
PY
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
> **Note:** Per project policy there are no unit tests to execute; validation
|
|
246
|
+
> is done by running the agent and inspecting the output + trace as above.
|
|
247
|
+
|
|
248
|
+
> **Missing AWS credentials?** If no credentials resolve from the chain, the run
|
|
249
|
+
> stops immediately (it does **not** retry) with a clear message —
|
|
250
|
+
> `error: AWS credentials are missing. ...` — and exits with code `2`.
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## CI / CD — Build, Package & Publish
|
|
255
|
+
|
|
256
|
+
The `.github/workflows/build.yml` workflow runs on every push, PR, and version
|
|
257
|
+
tag:
|
|
258
|
+
|
|
259
|
+
- **build** — builds the wheel + sdist with `uv build`, validates metadata with
|
|
260
|
+
`twine check`, installs the wheel into a clean venv to confirm the
|
|
261
|
+
`pr-decorator` CLI and packaged prompt work, and uploads `dist/*` as a
|
|
262
|
+
downloadable artifact.
|
|
263
|
+
- **publish-pypi** *(tags `v*` only)* — publishes to PyPI via **Trusted
|
|
264
|
+
Publishing** (OIDC; no API tokens stored).
|
|
265
|
+
- **release** *(tags `v*` only)* — attaches the artifacts to a GitHub Release.
|
|
266
|
+
|
|
267
|
+
### Publishing to PyPI
|
|
268
|
+
|
|
269
|
+
The package is published to <https://pypi.org/project/pr-decorator/>.
|
|
270
|
+
|
|
271
|
+
**One-time setup — register the GitHub repo as a Trusted Publisher on PyPI:**
|
|
272
|
+
|
|
273
|
+
1. Log in to PyPI → *Your projects* → **pr-decorator** → *Settings* →
|
|
274
|
+
*Publishing* (for a brand-new name, use *Publishing* → *Add a pending
|
|
275
|
+
publisher* first).
|
|
276
|
+
2. Add a GitHub Actions publisher:
|
|
277
|
+
- **Owner:** `kunaljha5`
|
|
278
|
+
- **Repository:** `pr-decorator`
|
|
279
|
+
- **Workflow name:** `build.yml`
|
|
280
|
+
- **Environment:** `pypi`
|
|
281
|
+
3. In the GitHub repo, create an **Environment** named `pypi`
|
|
282
|
+
(*Settings → Environments → New environment*) — optionally add required
|
|
283
|
+
reviewers to gate releases.
|
|
284
|
+
|
|
285
|
+
**Cut a release:**
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
# bump version in pyproject.toml first (e.g. 0.1.0 -> 0.1.1), commit, then:
|
|
289
|
+
git tag v0.1.1
|
|
290
|
+
git push origin v0.1.1
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
The tag triggers build → publish-pypi → release. After it succeeds:
|
|
294
|
+
|
|
295
|
+
```bash
|
|
296
|
+
pip install pr-decorator # or: uv pip install pr-decorator
|
|
297
|
+
pr-decorator --help
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
> To dry-run against **TestPyPI** first, add a Trusted Publisher on
|
|
301
|
+
> <https://test.pypi.org> and set `repository-url:
|
|
302
|
+
> https://test.pypi.org/legacy/` on the `pypa/gh-action-pypi-publish` step.
|
|
303
|
+
>
|
|
304
|
+
> Manual publish without CI (needs a PyPI API token):
|
|
305
|
+
> `uv build && uvx twine upload dist/*`.
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## Success Criteria
|
|
310
|
+
|
|
311
|
+
- [ ] Agent correctly classifies all change types from a git diff
|
|
312
|
+
- [ ] All MR template fields are populated in every run
|
|
313
|
+
- [ ] AWS Bedrock is called correctly with proper auth
|
|
314
|
+
- [ ] Agent loop retries on failure before giving up
|
|
315
|
+
- [ ] Final output is valid Markdown ready to paste into GitLab/GitHub MR
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# PR Decorator Agent — Primary Instructions
|
|
2
|
+
|
|
3
|
+
## Project Overview
|
|
4
|
+
An agentic AI system powered by **AWS Bedrock** that automatically decorates Pull Requests (Merge Requests) by following a structured observe → plan → execute → observe loop, and generates a standardized MR report as output.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Agent Loop (Core Behavior)
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
OBSERVE → PLAN → EXECUTE → OBSERVE → (if outcome OK) → FINISH & GENERATE OUTPUT
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
| Phase | Description |
|
|
15
|
+
|-------------|-------------|
|
|
16
|
+
| **Observe** | Read the raw diff, commits, branch name, ticket references, and any existing MR metadata |
|
|
17
|
+
| **Plan** | Decide what sections need to be filled, what code changes occurred, what categories they fall into |
|
|
18
|
+
| **Execute** | Call AWS Bedrock (Claude/Titan/etc.) to generate each section of the MR description |
|
|
19
|
+
| **Observe** | Validate the generated output — check for completeness, correctness, and formatting |
|
|
20
|
+
| **Finish** | If output passes validation, finalize and post/return the decorated MR |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## MR Output Template
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
MR Title : <concise, imperative-mood title>
|
|
28
|
+
MR Description :
|
|
29
|
+
Purpose : <why this MR exists — business/technical reason>
|
|
30
|
+
Ticket ID : <linked issue/ticket e.g. JIRA-123>
|
|
31
|
+
Code Changes : <summary of what files/modules changed and how>
|
|
32
|
+
Features Added: <new capabilities introduced, if any>
|
|
33
|
+
Linting Fixed : <style/formatting/lint issues resolved, if any>
|
|
34
|
+
Bug Fixed : <bugs resolved with brief description, if any>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Primary Instructions for the Agent
|
|
40
|
+
|
|
41
|
+
### 1. Input Collection (Observe Phase)
|
|
42
|
+
- Accept a **git diff** or list of changed files as primary input
|
|
43
|
+
- Accept optional metadata: branch name, commit messages, linked ticket ID
|
|
44
|
+
- Accept optional: existing MR title/description (for enrichment mode)
|
|
45
|
+
|
|
46
|
+
### 2. Analysis & Planning (Plan Phase)
|
|
47
|
+
- Parse the diff to classify changes:
|
|
48
|
+
- New files → Features Added
|
|
49
|
+
- Modified logic → Code Changes or Bug Fixed
|
|
50
|
+
- Formatting/style-only changes → Linting Fixed
|
|
51
|
+
- Config/dependency changes → Code Changes
|
|
52
|
+
- Extract ticket ID from branch name or commit message (e.g. `feat/JIRA-123-...`)
|
|
53
|
+
- Infer the purpose from commit messages and change patterns
|
|
54
|
+
|
|
55
|
+
### 3. Generation (Execute Phase)
|
|
56
|
+
- Call **AWS Bedrock** with a structured prompt per section
|
|
57
|
+
- Use a system prompt that enforces the MR template format
|
|
58
|
+
- Generate each section independently or in a single structured call
|
|
59
|
+
- Keep descriptions concise, technical, and developer-friendly
|
|
60
|
+
|
|
61
|
+
### 4. Validation (Observe Phase — Post Execute)
|
|
62
|
+
- Check all required fields are populated (no empty sections)
|
|
63
|
+
- Ensure Ticket ID is present (warn if missing)
|
|
64
|
+
- Ensure MR Title follows imperative mood convention (e.g. "Add", "Fix", "Refactor")
|
|
65
|
+
- If any section is empty or invalid → re-plan and re-execute that section only
|
|
66
|
+
|
|
67
|
+
### 5. Output Generation (Finish Phase)
|
|
68
|
+
- Output the final decorated MR as:
|
|
69
|
+
- Markdown string (for GitLab/GitHub MR body)
|
|
70
|
+
- Optionally: JSON payload for API submission
|
|
71
|
+
- Log a brief agent trace: what was observed, planned, executed, and validated
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## AWS Bedrock Integration
|
|
76
|
+
|
|
77
|
+
- **Model**: Amazon **Nova Pro** via Bedrock. Default model id is the APAC
|
|
78
|
+
cross-region inference profile `apac.amazon.nova-pro-v1:0` (required to call
|
|
79
|
+
Nova in `ap-south-1`). Override with the `BEDROCK_MODEL_ID` env var or the
|
|
80
|
+
`--model` flag (e.g. `amazon.nova-pro-v1:0` / `us.amazon.nova-pro-v1:0` in US regions).
|
|
81
|
+
- **Invocation**: Uses `bedrock-runtime` → `converse` API (model-agnostic).
|
|
82
|
+
- **Prompt Strategy**: Strict output-format enforcement via `prompts/mr_template.txt`.
|
|
83
|
+
- **Region**: Configurable. Default `ap-south-1`; override with `BEDROCK_REGION` /
|
|
84
|
+
`AWS_REGION` env var or the `--region` flag.
|
|
85
|
+
- **Auth**: IAM Role / AWS credential chain (no hardcoded keys).
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Non-Functional Requirements
|
|
90
|
+
|
|
91
|
+
- The agent must be **stateless** — each PR decoration is an independent run
|
|
92
|
+
- Support **retry logic** (max 2 retries) if Bedrock call fails
|
|
93
|
+
- Output must always conform to the MR template — no freeform deviation
|
|
94
|
+
- Agent trace/log must be saved alongside output for debugging
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## File Structure (Suggested)
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
pr-decorator/
|
|
102
|
+
├── instruction.md ← this file
|
|
103
|
+
├── agent/
|
|
104
|
+
│ ├── observe.py ← diff parsing & input collection
|
|
105
|
+
│ ├── plan.py ← change classification & section planning
|
|
106
|
+
│ ├── execute.py ← AWS Bedrock call & prompt management
|
|
107
|
+
│ ├── validate.py ← output validation logic
|
|
108
|
+
│ └── loop.py ← orchestrates observe→plan→execute→observe
|
|
109
|
+
├── prompts/
|
|
110
|
+
│ └── mr_template.txt ← system prompt with MR template
|
|
111
|
+
├── output/
|
|
112
|
+
│ └── mr_report.md ← generated MR decoration output
|
|
113
|
+
└── main.py ← entry point
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Local Setup — Build & Validate
|
|
119
|
+
|
|
120
|
+
### 1. Prerequisites
|
|
121
|
+
- Python **3.12** (see `.python-version`).
|
|
122
|
+
- [`uv`](https://docs.astral.sh/uv/) (recommended) or plain `venv` + `pip`.
|
|
123
|
+
- AWS credentials with Bedrock access in your target region, and **model access
|
|
124
|
+
to Amazon Nova Pro enabled** in the Bedrock console
|
|
125
|
+
(*Bedrock → Model access → Nova Pro*).
|
|
126
|
+
|
|
127
|
+
### 2. Build (create venv + install)
|
|
128
|
+
|
|
129
|
+
With `uv`:
|
|
130
|
+
```bash
|
|
131
|
+
uv venv --python 3.12 .venv
|
|
132
|
+
uv pip install -e ".[dev]"
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Or with stock Python:
|
|
136
|
+
```bash
|
|
137
|
+
python3.12 -m venv .venv
|
|
138
|
+
source .venv/bin/activate
|
|
139
|
+
pip install -e ".[dev]"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 3. Configure AWS
|
|
143
|
+
|
|
144
|
+
Auth uses the standard credential chain — **never hardcode keys**. Any of:
|
|
145
|
+
```bash
|
|
146
|
+
aws configure # writes ~/.aws/credentials + config
|
|
147
|
+
# or
|
|
148
|
+
aws sso login --profile <p> && export AWS_PROFILE=<p>
|
|
149
|
+
# or export AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / AWS_SESSION_TOKEN
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Optional overrides (defaults shown):
|
|
153
|
+
```bash
|
|
154
|
+
export BEDROCK_REGION=ap-south-1
|
|
155
|
+
export BEDROCK_MODEL_ID=apac.amazon.nova-pro-v1:0
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Verify credentials + Bedrock reachability before running the agent:
|
|
159
|
+
```bash
|
|
160
|
+
.venv/bin/python -c "import boto3; print(boto3.client('sts', region_name='ap-south-1').get_caller_identity()['Account'])"
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### 4. Run
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# Zero-arg: auto-detect base (origin/main → main → master), diff the current
|
|
167
|
+
# branch against it, and auto-fill branch + commit messages. Just run:
|
|
168
|
+
uv run main.py
|
|
169
|
+
# (or: .venv/bin/python main.py)
|
|
170
|
+
|
|
171
|
+
# Override the range / branch / ticket explicitly:
|
|
172
|
+
.venv/bin/python main.py --range origin/main...HEAD --branch "$(git branch --show-current)"
|
|
173
|
+
|
|
174
|
+
# Or pipe any diff in:
|
|
175
|
+
git diff origin/main | .venv/bin/python main.py --format markdown
|
|
176
|
+
|
|
177
|
+
# From a saved diff file, JSON output, with an explicit ticket:
|
|
178
|
+
.venv/bin/python main.py --diff-file changes.diff --ticket-id PRD-1 --format json
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Useful flags: `--model`, `--region`, `--format {markdown,json}`, `--no-write`
|
|
182
|
+
(print only, skip writing to `output/`), `--context-lines N` (context lines for
|
|
183
|
+
`git diff --unified` on `--range`; the large default feeds whole-file content to
|
|
184
|
+
the LLM so it can judge intent — lower it for very large PRs). Content size is
|
|
185
|
+
capped via `MR_MAX_FILE_CHARS` / `MR_MAX_TOTAL_CHARS` env vars.
|
|
186
|
+
|
|
187
|
+
### 5. Validate it worked
|
|
188
|
+
|
|
189
|
+
A successful run:
|
|
190
|
+
- exits with code **0** (non-zero means a required section failed validation),
|
|
191
|
+
- prints the decorated MR to stdout, and
|
|
192
|
+
- writes `output/mr_report.md` (or `.json`) **and** `output/agent_trace.json`.
|
|
193
|
+
|
|
194
|
+
Check the trace to confirm the Bedrock call landed — look for an `execute`
|
|
195
|
+
entry with `"ok": true` and a `finish` entry with `"ok": true`:
|
|
196
|
+
```bash
|
|
197
|
+
cat output/agent_trace.json
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Smoke-test the full loop **offline** (no AWS needed) with a stubbed client:
|
|
201
|
+
```bash
|
|
202
|
+
.venv/bin/python - <<'PY'
|
|
203
|
+
from agent import loop, render
|
|
204
|
+
from agent.execute import BedrockExecutor
|
|
205
|
+
|
|
206
|
+
class Stub:
|
|
207
|
+
def converse(self, **kw):
|
|
208
|
+
payload = '{"title":"Add feature","sections":{"Purpose":"x","Ticket ID":"PRD-1","Code Changes":"y","Features Added":"","Linting Fixed":"","Bug Fixed":""}}'
|
|
209
|
+
return {"output": {"message": {"content": [{"text": payload}]}}}
|
|
210
|
+
|
|
211
|
+
res = loop.run("diff --git a/f b/f\n+x\n", executor=BedrockExecutor(client=Stub()), branch="feat/PRD-1")
|
|
212
|
+
print(render.to_markdown(res.report))
|
|
213
|
+
print("ok:", res.validation.ok)
|
|
214
|
+
PY
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
> **Note:** Per project policy there are no unit tests to execute; validation
|
|
218
|
+
> is done by running the agent and inspecting the output + trace as above.
|
|
219
|
+
|
|
220
|
+
> **Missing AWS credentials?** If no credentials resolve from the chain, the run
|
|
221
|
+
> stops immediately (it does **not** retry) with a clear message —
|
|
222
|
+
> `error: AWS credentials are missing. ...` — and exits with code `2`.
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## CI / CD — Build, Package & Publish
|
|
227
|
+
|
|
228
|
+
The `.github/workflows/build.yml` workflow runs on every push, PR, and version
|
|
229
|
+
tag:
|
|
230
|
+
|
|
231
|
+
- **build** — builds the wheel + sdist with `uv build`, validates metadata with
|
|
232
|
+
`twine check`, installs the wheel into a clean venv to confirm the
|
|
233
|
+
`pr-decorator` CLI and packaged prompt work, and uploads `dist/*` as a
|
|
234
|
+
downloadable artifact.
|
|
235
|
+
- **publish-pypi** *(tags `v*` only)* — publishes to PyPI via **Trusted
|
|
236
|
+
Publishing** (OIDC; no API tokens stored).
|
|
237
|
+
- **release** *(tags `v*` only)* — attaches the artifacts to a GitHub Release.
|
|
238
|
+
|
|
239
|
+
### Publishing to PyPI
|
|
240
|
+
|
|
241
|
+
The package is published to <https://pypi.org/project/pr-decorator/>.
|
|
242
|
+
|
|
243
|
+
**One-time setup — register the GitHub repo as a Trusted Publisher on PyPI:**
|
|
244
|
+
|
|
245
|
+
1. Log in to PyPI → *Your projects* → **pr-decorator** → *Settings* →
|
|
246
|
+
*Publishing* (for a brand-new name, use *Publishing* → *Add a pending
|
|
247
|
+
publisher* first).
|
|
248
|
+
2. Add a GitHub Actions publisher:
|
|
249
|
+
- **Owner:** `kunaljha5`
|
|
250
|
+
- **Repository:** `pr-decorator`
|
|
251
|
+
- **Workflow name:** `build.yml`
|
|
252
|
+
- **Environment:** `pypi`
|
|
253
|
+
3. In the GitHub repo, create an **Environment** named `pypi`
|
|
254
|
+
(*Settings → Environments → New environment*) — optionally add required
|
|
255
|
+
reviewers to gate releases.
|
|
256
|
+
|
|
257
|
+
**Cut a release:**
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
# bump version in pyproject.toml first (e.g. 0.1.0 -> 0.1.1), commit, then:
|
|
261
|
+
git tag v0.1.1
|
|
262
|
+
git push origin v0.1.1
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
The tag triggers build → publish-pypi → release. After it succeeds:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
pip install pr-decorator # or: uv pip install pr-decorator
|
|
269
|
+
pr-decorator --help
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
> To dry-run against **TestPyPI** first, add a Trusted Publisher on
|
|
273
|
+
> <https://test.pypi.org> and set `repository-url:
|
|
274
|
+
> https://test.pypi.org/legacy/` on the `pypa/gh-action-pypi-publish` step.
|
|
275
|
+
>
|
|
276
|
+
> Manual publish without CI (needs a PyPI API token):
|
|
277
|
+
> `uv build && uvx twine upload dist/*`.
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Success Criteria
|
|
282
|
+
|
|
283
|
+
- [ ] Agent correctly classifies all change types from a git diff
|
|
284
|
+
- [ ] All MR template fields are populated in every run
|
|
285
|
+
- [ ] AWS Bedrock is called correctly with proper auth
|
|
286
|
+
- [ ] Agent loop retries on failure before giving up
|
|
287
|
+
- [ ] Final output is valid Markdown ready to paste into GitLab/GitHub MR
|