Skip to content

Commit d51e8b8

Browse files
authored
Merge pull request #28 from pratik-mahalle/pratik
feat: add Changelog / Release Notes Agent for automated changelog generation
2 parents 50b31ce + 56ede97 commit d51e8b8

File tree

5 files changed

+350
-0
lines changed

5 files changed

+350
-0
lines changed
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Qodo Agent: Changelog Generator
2+
3+
Automate generation of a well-structured CHANGELOG from merged PRs, closed issues, and commit messages. Supports optional grouping by Conventional Commits (feat, fix, docs, chore, refactor).
4+
5+
---
6+
7+
## Features
8+
- Group entries into Features, Fixes, Documentation, Chores, Others
9+
- Optionally group using Conventional Commits
10+
- Includes PR numbers and authors
11+
- Works for date ranges or tag ranges
12+
- Saves Markdown output suitable for `CHANGELOG.md` or `RELEASE.md`
13+
14+
---
15+
16+
## Arguments
17+
| Name | Type | Required | Default | Description |
18+
|------|------|----------|---------|-------------|
19+
| `repo` | string | yes | - | GitHub repository in `owner/name` format |
20+
| `since` | string | yes | - | Start date or tag for changelog |
21+
| `until` | string | no | HEAD | End date or tag |
22+
| `output_file` | string | no | CHANGELOG.md | File to save generated changelog |
23+
| `group_conventional` | boolean | no | true | Group by Conventional Commits types |
24+
| `include_issues` | boolean | no | true | Include closed issues |
25+
| `include_prs` | boolean | no | true | Include merged pull requests |
26+
| `include_commits` | boolean | no | true | Include commits not tied to PRs |
27+
28+
---
29+
30+
## Build & Validation
31+
32+
To validate the agent configuration and ensure everything is properly set up:
33+
34+
```bash
35+
# Make the build script executable (if needed)
36+
chmod +x build.sh
37+
38+
# Run the build validation
39+
./build.sh
40+
```
41+
42+
The build script will:
43+
- Validate all configuration files (TOML, YAML)
44+
- Check CI/CD configuration syntax
45+
- Verify Qodo CLI can recognize the agent
46+
- Ensure all required dependencies are available
47+
48+
---
49+
50+
## Usage
51+
Prerequisites:
52+
- Node.js 18+ (for Qodo CLI) or Docker
53+
- `GITHUB_PERSONAL_ACCESS_TOKEN` with `repo` scope (if accessing private repos)
54+
55+
Install Qodo CLI:
56+
```
57+
npm install -g @qodo/command
58+
```
59+
60+
Generate changelog between two tags:
61+
```
62+
qodo changelog_generator \
63+
--set repo=owner/repo \
64+
--set since=v1.2.0 \
65+
--set until=v1.3.0 \
66+
--set output_file=CHANGELOG.md
67+
```
68+
69+
Generate changelog since previous tag to HEAD and group by Conventional Commits:
70+
```
71+
LAST_TAG=$(git describe --tags --abbrev=0)
72+
qodo changelog_generator --set repo=owner/repo --set since=$LAST_TAG --set group_conventional=true
73+
```
74+
75+
---
76+
77+
## Sample Output (excerpt)
78+
```
79+
## v1.3.0 (2025-09-21)
80+
81+
### Features
82+
- feat: Add OAuth login support (#123) by @alice
83+
84+
### Fixes
85+
- fix: Handle null pointer in user service (#130) by @bob
86+
87+
### Documentation
88+
- docs: Update API usage examples (#128) by @carol
89+
90+
### Chores
91+
- chore: Bump dependencies
92+
```
93+
94+
---
95+
96+
## CI Examples
97+
See `examples/ci-configs/` for GitHub Actions and GitLab CI pipelines that generate and commit the updated `CHANGELOG.md` on new releases.
98+
99+
---
100+
101+
## Tools
102+
- `github`
103+
- `filesystem`
104+
- `shell`
105+
106+
---
107+
108+
## License
109+
See top-level LICENSE.
110+
111+
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
version = "1.0"
2+
3+
[commands.changelog_generator]
4+
description = "Generates release notes by analyzing commits, PRs, and issues for a given version tag or date range."
5+
6+
instructions = """
7+
You are a changelog generator. Fetch PRs, issues, and commits from the specified repository and release tag or date range.
8+
Group them into categories (Features, Fixes, Documentation, Chores, Others).
9+
Generate a human-readable changelog in Markdown format that can be directly used in a RELEASE.md file.
10+
Include PR numbers and authors.
11+
Optionally group using Conventional Commit types (feat, fix, docs, chore, refactor). If disabled, fall back to heuristic grouping.
12+
"""
13+
14+
arguments = [
15+
{ name = "repo", type = "string", required = true, description = "GitHub repository in owner/name format" },
16+
{ name = "since", type = "string", required = true, description = "Start date or tag for changelog" },
17+
{ name = "until", type = "string", required = false, description = "End date or tag (defaults to HEAD)" },
18+
{ name = "output_file", type = "string", required = false, default = "CHANGELOG.md", description = "File to save generated changelog" },
19+
{ name = "group_conventional", type = "boolean", required = false, default = true, description = "Group using Conventional Commits (feat, fix, docs, chore, refactor)" },
20+
{ name = "include_issues", type = "boolean", required = false, default = true, description = "Include closed issues in the changelog" },
21+
{ name = "include_prs", type = "boolean", required = false, default = true, description = "Include merged pull requests in the changelog" },
22+
{ name = "include_commits", type = "boolean", required = false, default = true, description = "Include commits not associated with PRs" }
23+
]
24+
25+
mcpServers = """
26+
{
27+
"github": {
28+
"url": "https://api.githubcopilot.com/mcp/",
29+
"headers": {
30+
"Authorization": "Bearer ${GITHUB_PERSONAL_ACCESS_TOKEN}"
31+
}
32+
},
33+
"external_shell": {
34+
"command": "uvx",
35+
"args": ["mcp-shell-server"]
36+
}
37+
}
38+
"""
39+
40+
tools = ["github", "filesystem", "external_shell"]
41+
execution_strategy = "plan"
42+
43+
output_schema = """
44+
{
45+
"properties": {
46+
"success": {"type": "boolean", "description": "Whether the changelog generation completed without errors"},
47+
"changelog": {"type": "string", "description": "Generated Markdown changelog content"},
48+
"commit_count": {"type": "number", "description": "Number of commits considered in the range"},
49+
"pr_count": {"type": "number", "description": "Number of pull requests included"},
50+
"issue_count": {"type": "number", "description": "Number of issues included"}
51+
}
52+
}
53+
"""
54+
55+
exit_expression = "success"
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
version: "1.0"
2+
3+
mcpServers:
4+
github:
5+
url: "https://api.githubcopilot.com/mcp/"
6+
headers:
7+
Authorization: "Bearer ${GITHUB_PERSONAL_ACCESS_TOKEN}"
8+
external_shell:
9+
command: "uvx"
10+
args: ["mcp-shell-server"]
11+
12+
commands:
13+
changelog_generator:
14+
description: "Generates release notes by analyzing commits, PRs, and issues for a given version tag or date range."
15+
16+
instructions: |
17+
You are a changelog generator. Fetch PRs, issues, and commits from the specified repository and release tag or date range.
18+
Group them into categories (Features, Fixes, Documentation, Chores, Others).
19+
Generate a human-readable changelog in Markdown format that can be directly used in a RELEASE.md file.
20+
Include PR numbers and authors.
21+
Optionally group using Conventional Commit types (feat, fix, docs, chore, refactor). If disabled, fall back to heuristic grouping.
22+
23+
arguments:
24+
- name: repo
25+
type: string
26+
required: true
27+
description: "GitHub repository in owner/name format"
28+
- name: since
29+
type: string
30+
required: true
31+
description: "Start date or tag for changelog"
32+
- name: until
33+
type: string
34+
required: false
35+
description: "End date or tag (defaults to HEAD)"
36+
- name: output_file
37+
type: string
38+
required: false
39+
default: "CHANGELOG.md"
40+
description: "File to save generated changelog"
41+
- name: group_conventional
42+
type: boolean
43+
required: false
44+
default: true
45+
description: "Group using Conventional Commits (feat, fix, docs, chore, refactor)"
46+
- name: include_issues
47+
type: boolean
48+
required: false
49+
default: true
50+
description: "Include closed issues in the changelog"
51+
- name: include_prs
52+
type: boolean
53+
required: false
54+
default: true
55+
description: "Include merged pull requests in the changelog"
56+
- name: include_commits
57+
type: boolean
58+
required: false
59+
default: true
60+
description: "Include commits not associated with PRs"
61+
62+
tools: ["github", "filesystem", "external_shell"]
63+
execution_strategy: "plan"
64+
65+
output_schema: |
66+
{
67+
"properties": {
68+
"success": {"type": "boolean", "description": "Whether the changelog generation completed without errors"},
69+
"changelog": {"type": "string", "description": "Generated Markdown changelog content"},
70+
"commit_count": {"type": "number", "description": "Number of commits considered in the range"},
71+
"pr_count": {"type": "number", "description": "Number of pull requests included"},
72+
"issue_count": {"type": "number", "description": "Number of issues included"}
73+
}
74+
}
75+
76+
exit_expression: "success"
77+
78+
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
name: Generate Changelog
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
workflow_dispatch:
8+
inputs:
9+
since:
10+
description: 'Start tag or date (optional)'
11+
required: false
12+
13+
permissions:
14+
contents: write
15+
16+
jobs:
17+
changelog:
18+
runs-on: ubuntu-latest
19+
steps:
20+
- name: Checkout
21+
uses: actions/checkout@v4
22+
with:
23+
fetch-depth: 0
24+
25+
- name: Setup Node.js
26+
uses: actions/setup-node@v4
27+
with:
28+
node-version: 20
29+
30+
- name: Install Qodo CLI
31+
run: npm install -g @qodo/command
32+
33+
- name: Determine range
34+
id: range
35+
shell: bash
36+
run: |
37+
if [ -n "${{ github.event.inputs.since }}" ]; then
38+
echo "since=${{ github.event.inputs.since }}" >> $GITHUB_OUTPUT
39+
else
40+
prev=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || true)
41+
if [ -z "$prev" ]; then
42+
# Fallback to last 14 days
43+
echo "since=$(date -u -d '14 days ago' +%Y-%m-%d)" >> $GITHUB_OUTPUT
44+
else
45+
echo "since=$prev" >> $GITHUB_OUTPUT
46+
fi
47+
fi
48+
49+
- name: Generate CHANGELOG
50+
env:
51+
GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
52+
run: |
53+
qodo changelog_generator \
54+
--set repo=${{ github.repository }} \
55+
--set since=${{ steps.range.outputs.since }} \
56+
--set until=${{ github.ref_name }} \
57+
--set group_conventional=true \
58+
--set output_file=CHANGELOG.md
59+
60+
- name: Commit and push
61+
run: |
62+
git config user.name "github-actions[bot]"
63+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
64+
git add CHANGELOG.md
65+
if ! git diff --staged --quiet; then
66+
git commit -m "docs(changelog): update for ${{ github.ref_name }}"
67+
git push
68+
fi
69+
70+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
stages:
2+
- docs
3+
4+
generate_changelog:
5+
stage: docs
6+
image: node:20
7+
variables:
8+
GIT_STRATEGY: fetch
9+
script:
10+
- npm install -g @qodo/command
11+
- |
12+
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || true)
13+
if [ -z "$PREV_TAG" ]; then
14+
SINCE=$(date -u -d '14 days ago' +%Y-%m-%d)
15+
else
16+
SINCE=$PREV_TAG
17+
fi
18+
qodo changelog_generator \
19+
--set repo=${CI_PROJECT_PATH} \
20+
--set since=${SINCE} \
21+
--set until=${CI_COMMIT_REF_NAME} \
22+
--set group_conventional=true \
23+
--set output_file=CHANGELOG.md
24+
- |
25+
git config user.name "gitlab-ci[bot]"
26+
git config user.email "gitlab-ci-bot@noreply"
27+
git add CHANGELOG.md
28+
if ! git diff --staged --quiet; then
29+
git commit -m "docs(changelog): update for ${CI_COMMIT_REF_NAME}"
30+
git push "https://oauth2:${GITLAB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" HEAD:${CI_COMMIT_REF_NAME}
31+
fi
32+
only:
33+
- tags
34+
- schedules
35+
36+

0 commit comments

Comments
 (0)