Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 111 additions & 0 deletions agents/changelog-generator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Qodo Agent: Changelog Generator

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).

---

## Features
- Group entries into Features, Fixes, Documentation, Chores, Others
- Optionally group using Conventional Commits
- Includes PR numbers and authors
- Works for date ranges or tag ranges
- Saves Markdown output suitable for `CHANGELOG.md` or `RELEASE.md`

---

## Arguments
| Name | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `repo` | string | yes | - | GitHub repository in `owner/name` format |
| `since` | string | yes | - | Start date or tag for changelog |
| `until` | string | no | HEAD | End date or tag |
| `output_file` | string | no | CHANGELOG.md | File to save generated changelog |
| `group_conventional` | boolean | no | true | Group by Conventional Commits types |
| `include_issues` | boolean | no | true | Include closed issues |
| `include_prs` | boolean | no | true | Include merged pull requests |
| `include_commits` | boolean | no | true | Include commits not tied to PRs |

---

## Build & Validation

To validate the agent configuration and ensure everything is properly set up:

```bash
# Make the build script executable (if needed)
chmod +x build.sh

# Run the build validation
./build.sh
```

The build script will:
- Validate all configuration files (TOML, YAML)
- Check CI/CD configuration syntax
- Verify Qodo CLI can recognize the agent
- Ensure all required dependencies are available

---

## Usage
Prerequisites:
- Node.js 18+ (for Qodo CLI) or Docker
- `GITHUB_PERSONAL_ACCESS_TOKEN` with `repo` scope (if accessing private repos)

Install Qodo CLI:
```
npm install -g @qodo/command
```

Generate changelog between two tags:
```
qodo changelog_generator \
--set repo=owner/repo \
--set since=v1.2.0 \
--set until=v1.3.0 \
--set output_file=CHANGELOG.md
```

Generate changelog since previous tag to HEAD and group by Conventional Commits:
```
LAST_TAG=$(git describe --tags --abbrev=0)
qodo changelog_generator --set repo=owner/repo --set since=$LAST_TAG --set group_conventional=true
```

---

## Sample Output (excerpt)
```
## v1.3.0 (2025-09-21)

### Features
- feat: Add OAuth login support (#123) by @alice

### Fixes
- fix: Handle null pointer in user service (#130) by @bob

### Documentation
- docs: Update API usage examples (#128) by @carol

### Chores
- chore: Bump dependencies
```

---

## CI Examples
See `examples/ci-configs/` for GitHub Actions and GitLab CI pipelines that generate and commit the updated `CHANGELOG.md` on new releases.

---

## Tools
- `github`
- `filesystem`
- `shell`

---

## License
See top-level LICENSE.


55 changes: 55 additions & 0 deletions agents/changelog-generator/agent.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
version = "1.0"

[commands.changelog_generator]
description = "Generates release notes by analyzing commits, PRs, and issues for a given version tag or date range."

instructions = """
You are a changelog generator. Fetch PRs, issues, and commits from the specified repository and release tag or date range.
Group them into categories (Features, Fixes, Documentation, Chores, Others).
Generate a human-readable changelog in Markdown format that can be directly used in a RELEASE.md file.
Include PR numbers and authors.
Optionally group using Conventional Commit types (feat, fix, docs, chore, refactor). If disabled, fall back to heuristic grouping.
"""

arguments = [
{ name = "repo", type = "string", required = true, description = "GitHub repository in owner/name format" },
{ name = "since", type = "string", required = true, description = "Start date or tag for changelog" },
{ name = "until", type = "string", required = false, description = "End date or tag (defaults to HEAD)" },
{ name = "output_file", type = "string", required = false, default = "CHANGELOG.md", description = "File to save generated changelog" },
{ name = "group_conventional", type = "boolean", required = false, default = true, description = "Group using Conventional Commits (feat, fix, docs, chore, refactor)" },
{ name = "include_issues", type = "boolean", required = false, default = true, description = "Include closed issues in the changelog" },
{ name = "include_prs", type = "boolean", required = false, default = true, description = "Include merged pull requests in the changelog" },
{ name = "include_commits", type = "boolean", required = false, default = true, description = "Include commits not associated with PRs" }
]

mcpServers = """
{
"github": {
"url": "https://api.githubcopilot.com/mcp/",
"headers": {
"Authorization": "Bearer ${GITHUB_PERSONAL_ACCESS_TOKEN}"
}
},
"external_shell": {
"command": "uvx",
"args": ["mcp-shell-server"]
}
}
"""

tools = ["github", "filesystem", "external_shell"]
execution_strategy = "plan"

output_schema = """
{
"properties": {
"success": {"type": "boolean", "description": "Whether the changelog generation completed without errors"},
"changelog": {"type": "string", "description": "Generated Markdown changelog content"},
"commit_count": {"type": "number", "description": "Number of commits considered in the range"},
"pr_count": {"type": "number", "description": "Number of pull requests included"},
"issue_count": {"type": "number", "description": "Number of issues included"}
}
}
"""

exit_expression = "success"
78 changes: 78 additions & 0 deletions agents/changelog-generator/agent.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
version: "1.0"

mcpServers:
github:
url: "https://api.githubcopilot.com/mcp/"
headers:
Authorization: "Bearer ${GITHUB_PERSONAL_ACCESS_TOKEN}"
external_shell:
command: "uvx"
args: ["mcp-shell-server"]

commands:
changelog_generator:
description: "Generates release notes by analyzing commits, PRs, and issues for a given version tag or date range."

instructions: |
You are a changelog generator. Fetch PRs, issues, and commits from the specified repository and release tag or date range.
Group them into categories (Features, Fixes, Documentation, Chores, Others).
Generate a human-readable changelog in Markdown format that can be directly used in a RELEASE.md file.
Include PR numbers and authors.
Optionally group using Conventional Commit types (feat, fix, docs, chore, refactor). If disabled, fall back to heuristic grouping.

arguments:
- name: repo
type: string
required: true
description: "GitHub repository in owner/name format"
- name: since
type: string
required: true
description: "Start date or tag for changelog"
- name: until
type: string
required: false
description: "End date or tag (defaults to HEAD)"
- name: output_file
type: string
required: false
default: "CHANGELOG.md"
description: "File to save generated changelog"
- name: group_conventional
type: boolean
required: false
default: true
description: "Group using Conventional Commits (feat, fix, docs, chore, refactor)"
- name: include_issues
type: boolean
required: false
default: true
description: "Include closed issues in the changelog"
- name: include_prs
type: boolean
required: false
default: true
description: "Include merged pull requests in the changelog"
- name: include_commits
type: boolean
required: false
default: true
description: "Include commits not associated with PRs"

tools: ["github", "filesystem", "external_shell"]
execution_strategy: "plan"

output_schema: |
{
"properties": {
"success": {"type": "boolean", "description": "Whether the changelog generation completed without errors"},
"changelog": {"type": "string", "description": "Generated Markdown changelog content"},
"commit_count": {"type": "number", "description": "Number of commits considered in the range"},
"pr_count": {"type": "number", "description": "Number of pull requests included"},
"issue_count": {"type": "number", "description": "Number of issues included"}
}
}

exit_expression: "success"


70 changes: 70 additions & 0 deletions agents/changelog-generator/examples/ci-configs/github-actions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Generate Changelog

on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
since:
description: 'Start tag or date (optional)'
required: false

permissions:
contents: write

jobs:
changelog:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20

- name: Install Qodo CLI
run: npm install -g @qodo/command

- name: Determine range
id: range
shell: bash
run: |
if [ -n "${{ github.event.inputs.since }}" ]; then
echo "since=${{ github.event.inputs.since }}" >> $GITHUB_OUTPUT
else
prev=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || true)
if [ -z "$prev" ]; then
# Fallback to last 14 days
echo "since=$(date -u -d '14 days ago' +%Y-%m-%d)" >> $GITHUB_OUTPUT
else
echo "since=$prev" >> $GITHUB_OUTPUT
fi
fi

- name: Generate CHANGELOG
env:
GITHUB_PERSONAL_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
qodo changelog_generator \
--set repo=${{ github.repository }} \
--set since=${{ steps.range.outputs.since }} \
--set until=${{ github.ref_name }} \
--set group_conventional=true \
--set output_file=CHANGELOG.md

- name: Commit and push
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add CHANGELOG.md
if ! git diff --staged --quiet; then
git commit -m "docs(changelog): update for ${{ github.ref_name }}"
git push
fi


36 changes: 36 additions & 0 deletions agents/changelog-generator/examples/ci-configs/gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
stages:
- docs

generate_changelog:
stage: docs
image: node:20
variables:
GIT_STRATEGY: fetch
script:
- npm install -g @qodo/command
- |
PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || true)
if [ -z "$PREV_TAG" ]; then
SINCE=$(date -u -d '14 days ago' +%Y-%m-%d)
else
SINCE=$PREV_TAG
fi
qodo changelog_generator \
--set repo=${CI_PROJECT_PATH} \
--set since=${SINCE} \
--set until=${CI_COMMIT_REF_NAME} \
--set group_conventional=true \
--set output_file=CHANGELOG.md
- |
git config user.name "gitlab-ci[bot]"
git config user.email "gitlab-ci-bot@noreply"
git add CHANGELOG.md
if ! git diff --staged --quiet; then
git commit -m "docs(changelog): update for ${CI_COMMIT_REF_NAME}"
git push "https://oauth2:${GITLAB_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" HEAD:${CI_COMMIT_REF_NAME}
fi
only:
- tags
- schedules