[PR #512] Add AI-powered automated changelog generation workflow #528

Closed
opened 2026-03-02 04:13:53 +03:00 by kerem · 0 comments
Owner

Original Pull Request: https://github.com/git-ai-project/git-ai/pull/512

State: closed
Merged: Yes


Add AI-powered automated changelog generation on release

Summary

Adds automated AI-generated changelogs that are committed directly to CHANGELOG.md and injected into GitHub release notes on every production release. Addresses #510.

New files:

  • .github/workflows/update-changelog.yml — new workflow triggered on release: published (and manually via workflow_dispatch) that uses @nyaomaru/changelog-bot CLI to generate a changelog entry via OpenAI, commits it to CHANGELOG.md on main, then replaces a placeholder in the release body with the generated notes. Includes a dry_run option for testing without modifying anything.
  • .github/release.yml — configures GitHub's built-in auto-generated release notes with PR label categories (New Features, Bug Fixes, Performance, Documentation, Other)
  • CHANGELOG.md — starter file with Keep a Changelog header

Modified files:

  • .github/workflows/release.yml — adds generate_release_notes: true so GitHub auto-generates basic release notes immediately, and adds a placeholder (> Detailed AI-generated changelog is being generated and will appear here shortly...) that gets replaced by the changelog workflow once it completes. Placeholder is conditionally hidden for next/prerelease releases.

End-to-end flow:

  1. release.yml creates a GitHub release with auto-generated notes + placeholder (production only)
  2. The release: published event triggers update-changelog.yml
  3. Workflow validates OPENAI_API_KEY, runs changelog-bot CLI to generate a structured changelog entry
  4. Commits updated CHANGELOG.md directly to main
  5. Extracts the new entry and replaces the placeholder in the release body via gh release edit

next channel interaction: The next release channel sets prerelease=true (release.yml line 268), and the changelog job condition (github.event.release.prerelease == false) skips the entire job for next releases. The placeholder text is also conditionally omitted from next release bodies so users don't see a "generating..." message that will never be replaced.

Updates since last revision

  • Fixed script injection vulnerability: All github.event.release.* values (tag_name, body) are now passed via step-level env: blocks and referenced as shell variables, instead of inline ${{ }} interpolation in run: blocks
  • Fixed unexported shell variables: Added export CURRENT_BODY PLACEHOLDER before the Python subprocess that performs placeholder replacement
  • Fixed Python SyntaxError: Switched from python3 -c "..." to a heredoc (python3 << 'PYTHON_SCRIPT') to avoid shell quoting issues with the apostrophe in "### What's Changed"
  • Added workflow_dispatch trigger for testing: Can now manually trigger the workflow with a release_tag input and dry_run=true to validate AI generation without committing or modifying the release
  • next channel handling: Placeholder in release body is conditionally hidden for prerelease/next releases using ternary expressions in the body: template
  • Fixed script injection in config step: The "Set release tag" step now passes github.event_name, inputs.*, and github.event.release.tag_name through env: block instead of direct ${{ }} interpolation
  • Random heredoc delimiters: BODY_EOF and ENTRY_EOF delimiters now use random suffixes via openssl rand -hex 8 to prevent collision with release body content
  • Skip release update when changelog unchanged: Added committed output flag to commit step; downstream "Extract changelog entry" and "Update release notes" steps now require committed == 'true', preventing empty content from replacing the placeholder
  • Escape dots in awk regex: Version strings are now escaped via sed 's/\./\\./g' before interpolating into awk patterns to prevent . from matching any character

Review & Testing Checklist for Human

  • Add OPENAI_API_KEY as a repository secret — required; the workflow fails immediately without it
  • CI passing is insufficient — This workflow cannot be validated by PR CI. It only triggers on release: published or workflow_dispatch. You must test manually after merging.
  • Race condition between workflows: release.yml pushes a version bump commit to main after creating the release (line 470). The changelog workflow checks out ref: main and later does git push origin HEAD:main. If the version bump hasn't landed yet when checkout happens but lands before the changelog push, the push will be rejected as non-fast-forward. Verify timing on first real release — you may need to add a git pull --rebase origin main before pushing.
  • Check branch protection compatibility: The workflow pushes directly to main (git push origin HEAD:main). If branch protection requires PR reviews or status checks, this push will fail. You may need to allow github-actions[bot] to bypass protection rules.
  • Test with dry-run before production release: After merging, go to Actions → "Update Changelog" → "Run workflow" → enter an existing release tag → run with dry_run=true. This validates the AI generation pipeline without modifying anything. Then do a real production release to verify the full end-to-end flow.

Notes

  • Prereleases and draft releases are skipped by the if condition on the job
  • The placeholder replacement uses a Python heredoc with regex to handle multiline matching; falls back to appending if the placeholder isn't found
  • changelog-bot supports both OpenAI and Anthropic providers; this workflow uses openai
  • The OPENAI_MODEL env var can optionally be set to override the default model
  • Currently uses npx @nyaomaru/changelog-bot@latest which floats to the newest version — consider pinning to a specific version for predictable behavior

Requested by: @svarlamov
Link to Devin run

**Original Pull Request:** https://github.com/git-ai-project/git-ai/pull/512 **State:** closed **Merged:** Yes --- # Add AI-powered automated changelog generation on release ## Summary Adds automated AI-generated changelogs that are committed directly to `CHANGELOG.md` and injected into GitHub release notes on every production release. Addresses #510. **New files:** - **`.github/workflows/update-changelog.yml`** — new workflow triggered on `release: published` (and manually via `workflow_dispatch`) that uses [`@nyaomaru/changelog-bot`](https://github.com/nyaomaru/changelog-bot) CLI to generate a changelog entry via OpenAI, commits it to `CHANGELOG.md` on `main`, then replaces a placeholder in the release body with the generated notes. Includes a `dry_run` option for testing without modifying anything. - **`.github/release.yml`** — configures GitHub's built-in auto-generated release notes with PR label categories (New Features, Bug Fixes, Performance, Documentation, Other) - **`CHANGELOG.md`** — starter file with [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) header **Modified files:** - **`.github/workflows/release.yml`** — adds `generate_release_notes: true` so GitHub auto-generates basic release notes immediately, and adds a placeholder (`> Detailed AI-generated changelog is being generated and will appear here shortly...`) that gets replaced by the changelog workflow once it completes. Placeholder is conditionally hidden for `next`/prerelease releases. **End-to-end flow:** 1. `release.yml` creates a GitHub release with auto-generated notes + placeholder (production only) 2. The `release: published` event triggers `update-changelog.yml` 3. Workflow validates `OPENAI_API_KEY`, runs `changelog-bot` CLI to generate a structured changelog entry 4. Commits updated `CHANGELOG.md` directly to `main` 5. Extracts the new entry and replaces the placeholder in the release body via `gh release edit` **`next` channel interaction:** The `next` release channel sets `prerelease=true` (release.yml line 268), and the changelog job condition (`github.event.release.prerelease == false`) skips the entire job for `next` releases. The placeholder text is also conditionally omitted from `next` release bodies so users don't see a "generating..." message that will never be replaced. ## Updates since last revision - **Fixed script injection vulnerability**: All `github.event.release.*` values (`tag_name`, `body`) are now passed via step-level `env:` blocks and referenced as shell variables, instead of inline `${{ }}` interpolation in `run:` blocks - **Fixed unexported shell variables**: Added `export CURRENT_BODY PLACEHOLDER` before the Python subprocess that performs placeholder replacement - **Fixed Python SyntaxError**: Switched from `python3 -c "..."` to a heredoc (`python3 << 'PYTHON_SCRIPT'`) to avoid shell quoting issues with the apostrophe in `"### What's Changed"` - **Added `workflow_dispatch` trigger for testing**: Can now manually trigger the workflow with a `release_tag` input and `dry_run=true` to validate AI generation without committing or modifying the release - **`next` channel handling**: Placeholder in release body is conditionally hidden for prerelease/next releases using ternary expressions in the `body:` template - **Fixed script injection in config step**: The "Set release tag" step now passes `github.event_name`, `inputs.*`, and `github.event.release.tag_name` through `env:` block instead of direct `${{ }}` interpolation - **Random heredoc delimiters**: `BODY_EOF` and `ENTRY_EOF` delimiters now use random suffixes via `openssl rand -hex 8` to prevent collision with release body content - **Skip release update when changelog unchanged**: Added `committed` output flag to commit step; downstream "Extract changelog entry" and "Update release notes" steps now require `committed == 'true'`, preventing empty content from replacing the placeholder - **Escape dots in awk regex**: Version strings are now escaped via `sed 's/\./\\./g'` before interpolating into awk patterns to prevent `.` from matching any character ## Review & Testing Checklist for Human - [ ] **Add `OPENAI_API_KEY` as a repository secret** — required; the workflow fails immediately without it - [ ] **CI passing is insufficient** — This workflow cannot be validated by PR CI. It only triggers on `release: published` or `workflow_dispatch`. You must test manually after merging. - [ ] **Race condition between workflows**: `release.yml` pushes a version bump commit to `main` after creating the release (line 470). The changelog workflow checks out `ref: main` and later does `git push origin HEAD:main`. If the version bump hasn't landed yet when checkout happens but lands before the changelog push, the push will be rejected as non-fast-forward. Verify timing on first real release — you may need to add a `git pull --rebase origin main` before pushing. - [ ] **Check branch protection compatibility**: The workflow pushes directly to `main` (`git push origin HEAD:main`). If branch protection requires PR reviews or status checks, this push will fail. You may need to allow `github-actions[bot]` to bypass protection rules. - [ ] **Test with dry-run before production release**: After merging, go to Actions → "Update Changelog" → "Run workflow" → enter an existing release tag → run with `dry_run=true`. This validates the AI generation pipeline without modifying anything. Then do a real production release to verify the full end-to-end flow. ### Notes - Prereleases and draft releases are skipped by the `if` condition on the job - The placeholder replacement uses a Python heredoc with regex to handle multiline matching; falls back to appending if the placeholder isn't found - `changelog-bot` supports both OpenAI and Anthropic providers; this workflow uses `openai` - The `OPENAI_MODEL` env var can optionally be set to override the default model - Currently uses `npx @nyaomaru/changelog-bot@latest` which floats to the newest version — consider pinning to a specific version for predictable behavior Requested by: @svarlamov [Link to Devin run](https://app.devin.ai/sessions/ed5bad0172374a9f91f9c60d3769db6b)
kerem 2026-03-02 04:13:53 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/git-ai#528
No description provided.