Date: 2025-12-08 Feature: 010-release-notes-generator
This feature has minimal data modeling requirements as it operates within GitHub Actions workflows with ephemeral storage. No persistent database or state management is needed.
Generated text content that flows through the workflow as outputs and artifacts.
Attributes:
| Field | Type | Description |
|---|---|---|
| version | string | Git tag (e.g., "v1.2.0") |
| content | string | Markdown-formatted release notes |
| generated_at | timestamp | ISO 8601 timestamp |
| model | string | Claude model used (e.g., "claude-sonnet-4-5-20250929") |
| commit_count | integer | Number of commits analyzed |
| truncated | boolean | Whether commits were truncated (>200) |
Lifecycle:
- Created in
generate-notesjob - Passed via GitHub Actions outputs to
releasejob - Optionally saved as artifact for installer jobs
- Optionally committed to repository
Raw commit data extracted from git history.
Attributes:
| Field | Type | Description |
|---|---|---|
| subject | string | First line of commit message |
| hash | string | Short commit hash (optional) |
| type | string | Conventional commit type (feat/fix/chore/etc.) |
Collection: git log --pretty=format:"- %s" --no-merges
Request payload sent to Claude API.
Structure:
{
"model": "claude-sonnet-4-5-20250929",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": "Generate release notes for {version}...\n\nCommits:\n{commits}"
}
]
}Response from Claude API.
Structure:
{
"id": "msg_...",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "## What's New in v1.2.0\n\n..."
}
],
"model": "claude-sonnet-4-5-20250929",
"stop_reason": "end_turn",
"usage": {
"input_tokens": 1234,
"output_tokens": 567
}
}┌─────────────────────────────────────────────────────────────────────┐
│ GitHub Actions Workflow │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ Git Tags │───▶│ Commit Msgs │───▶│ Claude API Request │ │
│ │ (v1.1→v1.2) │ │ (filtered) │ │ (JSON payload) │ │
│ └─────────────┘ └─────────────┘ └───────────┬─────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ GitHub │◀───│ Release │◀───│ Claude API Response │ │
│ │ Release │ │ Notes │ │ (markdown text) │ │
│ └─────────────┘ └──────┬──────┘ └─────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────┐ │
│ │ Artifacts (optional) │ │
│ │ - RELEASE_NOTES-v1.2.0.md │ │
│ │ - Included in DMG/EXE │ │
│ └─────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
jobs:
generate-notes:
outputs:
notes: ${{ steps.generate.outputs.notes }}
version: ${{ steps.generate.outputs.version }}- uses: actions/upload-artifact@v4
with:
name: release-notes
path: RELEASE_NOTES-${{ github.ref_name }}.mdreleases/
├── RELEASE_NOTES-v1.0.0.md
├── RELEASE_NOTES-v1.1.0.md
└── RELEASE_NOTES-v1.2.0.md
This feature has no persistent state. Each workflow run is stateless:
[Tag Push] → [Generate Notes] → [Create Release] → [Done]
│
└── On failure: [Fallback Message] → [Create Release] → [Done]
| Rule | Implementation |
|---|---|
| Version format | Must match v* pattern (enforced by workflow trigger) |
| Commit count | Max 200 commits (truncation with warning) |
| API key present | Required secret, fail-fast if missing |
| Rule | Implementation |
|---|---|
| Non-empty notes | Fallback message if empty |
| Max length | Truncate to 4000 chars (safety) |
| Valid markdown | Trust Claude output (manual edit if needed) |