Skip to content

Conversation

@JacobCoffee
Copy link
Owner

@JacobCoffee JacobCoffee commented Nov 23, 2025

Summary

This PR optimizes the git-cliff changelog workflow in the CD pipeline with several improvements:

Changes

pyproject.toml:

  • Add explicit output = "docs/changelog.rst" to git-cliff config

cd.yml workflow:

  • ✅ Upgrade git-cliff-action from @main to @v4 for stability
  • ✅ Generate full changelog history (remove --latest from full changelog step)
  • ✅ Create PR instead of direct commit to main (reviewable changes)
  • ✅ Add GitHub release body updates with latest changelog content
  • ✅ Use gh CLI for GitHub operations
  • ✅ Add Claude Code signature to commits
  • ✅ Add pull-requests: write permission
  • ✅ Use OUTPUT env var instead of --output in args

Workflow Behavior

  1. On release/tag/manual trigger:

    • Generates latest changelog for release body
    • Generates full changelog history to docs/changelog.rst
    • Creates PR with changelog updates
    • Updates GitHub release body (if release or tag event)
  2. Atomic commits created:

    • chore: add output path to git-cliff changelog config
    • ci: optimize git-cliff workflow for automated changelog

Testing

Note: Full CI cannot run on this branch due to Python 3.14 compatibility issues in base branch (expected, as this is based on feature/migrate-to-python3.14). Workflow syntax is valid and follows project conventions.


🤖 Generated with Claude Code

Summary by Sourcery

Optimize the CD changelog workflow to use the latest git-cliff action, generate both latest and full changelog outputs, and integrate automated PR and release body updates.

New Features:

  • Automatically create pull requests with changelog updates instead of committing directly to main.
  • Automatically update GitHub release bodies with the latest changelog content during release or tag events.

Enhancements:

  • Upgrade git-cliff GitHub Action usage to v4 and configure repository-related environment variables for more robust execution.
  • Generate the full changelog file via configuration-driven output rather than CLI flags and simplify workflow arguments.
  • Add permissions and GitHub CLI usage needed for branch creation, PR management, and release editing in the CD pipeline.

CI:

  • Refine the CD workflow to separate latest changelog generation from full history generation and expose the latest content as a workflow output.

Chores:

  • Configure git-cliff to write the changelog to docs/changelog.rst via pyproject.toml.

@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Nov 23, 2025

Reviewer's Guide

Optimizes the CD git-cliff workflow so that it generates both a latest-release snippet and a full docs/changelog.rst file using git-cliff v4, then opens a PR with changelog updates and updates GitHub release notes, instead of pushing directly to main.

Sequence diagram for updated git-cliff-based changelog and release flow

sequenceDiagram
  actor U as "Maintainer"
  participant GH as "GitHub (events)"
  participant WF as "CD Workflow (cd.yml)"
  participant CL1 as "git-cliff action v4 (latest snippet)"
  participant GIT as "Git repository (main + worktree)"
  participant CL2 as "git-cliff action v4 (full changelog)"
  participant GHCLI as "gh CLI"
  participant PRS as "GitHub Pull Requests"
  participant REL as "GitHub Releases"

  U->>GH: "Create release / push tag / manually dispatch"
  GH->>WF: "Trigger cd workflow"

  WF->>GIT: "Checkout repository (fetch-depth 0)"
  WF->>CL1: "Run git-cliff v4 with args '-vv --latest --strip header'"
  activate CL1
  CL1-->>WF: "Output latest changelog snippet (content)"
  deactivate CL1

  WF->>GIT: "Fetch origin/main and create worktree 'worktree-changelog'"
  WF->>CL2: "Run git-cliff v4 in worktree with args '-vv' and env 'OUTPUT=docs/changelog.rst'"
  activate CL2
  CL2->>GIT: "Write full changelog to 'docs/changelog.rst'"
  CL2-->>WF: "Exit with success"
  deactivate CL2

  WF->>GIT: "Stage changelog changes"
  WF->>GIT: "Check if there are staged changes"
  alt "Changelog has changes"
    WF->>GIT: "Create branch 'changelog/update-<short-hash>'"
    WF->>GIT: "Commit with Claude Code signature message"
    WF->>GHCLI: "Push branch and create PR to 'main' with labels 'documentation' and 'automated'"
    GHCLI->>PRS: "Create PR with changelog updates"
  else "No changes"
    WF-->>WF: "Skip commit and PR creation"
  end

  opt "Release or tag-based event"
    WF->>GHCLI: "Edit release using tag name and latest snippet"
    GHCLI->>REL: "Update release notes with latest changelog content"
  end

  WF-->>GH: "Workflow completes (worktree cleaned up)"
Loading

Flow diagram for branching, commit, and PR creation in changelog workflow

flowchart TD
  A["Start in worktree-changelog on origin/main"] --> B["Run git-cliff v4 to generate full changelog to 'docs/changelog.rst'"]
  B --> C["git add updated changelog files"]
  C --> D{"Are there staged changes?"}

  D -->|"No"| E["Print 'No changes to commit' and exit step"]
  E --> F["Continue to cleanup worktree"]

  D -->|"Yes"| G["Create branch 'changelog/update-<short-hash>'"]
  G --> H["Commit with message containing Claude Code signature and co-author"]
  H --> I["Push branch to origin"]
  I --> J["Call 'gh pr create' with base 'main', labels 'documentation' and 'automated'"]
  J --> K["PR with changelog updates is opened"]
  K --> F["Continue to cleanup worktree"]
Loading

File-Level Changes

Change Details Files
Upgrade git-cliff usage and outputs in the CD workflow to support both latest and full changelog generation.
  • Switch git-cliff-action from @main to @v4 for both latest and full changelog steps
  • Split changelog generation into a latest changelog step for release body and a full changelog step for the docs file
  • Change the workflow job output to use the latest changelog step’s content instead of the old one
  • Pass GITHUB_REPO to git-cliff and use OUTPUT env var instead of the --output argument for the full changelog run
.github/workflows/cd.yml
Change the workflow from committing directly to main to creating an automated PR with metadata and proper permissions.
  • Add pull-requests: write permission to the workflow job
  • Replace direct commit-and-push to main with logic that creates a new branch, commits the changelog, and opens a PR via gh CLI
  • Configure git user for commits and add a structured commit message that includes a Claude Code signature and Co-Authored-By trailer
  • Add GH_TOKEN environment variable for gh operations and apply documentation/automated labels to the created PR
.github/workflows/cd.yml
Automatically update GitHub release notes using the latest changelog content when triggered by releases or tags.
  • Add a conditional step that runs only for release or version-tag events
  • Determine the tag name based on whether the event is a GitHub release or a tag push
  • Use gh release edit to update the release notes with the latest changelog content from the git-cliff-latest step
.github/workflows/cd.yml
Make the git-cliff configuration explicitly write the changelog to the docs path used by the workflow.
  • Set tool.git-cliff.changelog.output to docs/changelog.rst so the config matches the workflow’s expectations
pyproject.toml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@railway-app
Copy link

railway-app bot commented Nov 23, 2025

🚅 Deployed to the byte-pr-117 environment in byte

Service Status Web Updated (UTC)
byte ◻️ Removed (View Logs) Web Nov 23, 2025 at 6:21 am

@railway-app railway-app bot temporarily deployed to byte (byte / byte-pr-117) November 23, 2025 05:24 Destroyed
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • The multiline commit message constructed with git commit -m "$(cat <<'EOF' ...)" will include the indentation and may be fragile; consider writing the message to a temporary file and using git commit -F to avoid unintended whitespace and quoting issues.
  • In the 'Update GitHub release body' step, passing ${{ steps.git-cliff-latest.outputs.content }} directly into --notes can break if the changelog contains quotes or shell-sensitive characters; it would be safer to expose this output as an environment variable or file and reference it from the shell script (e.g., --notes-file) to avoid quoting/escaping problems.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The multiline commit message constructed with `git commit -m "$(cat <<'EOF' ...)"` will include the indentation and may be fragile; consider writing the message to a temporary file and using `git commit -F` to avoid unintended whitespace and quoting issues.
- In the 'Update GitHub release body' step, passing `${{ steps.git-cliff-latest.outputs.content }}` directly into `--notes` can break if the changelog contains quotes or shell-sensitive characters; it would be safer to expose this output as an environment variable or file and reference it from the shell script (e.g., `--notes-file`) to avoid quoting/escaping problems.

## Individual Comments

### Comment 1
<location> `.github/workflows/cd.yml:62-63` </location>
<code_context>
-            git commit -m "docs: update changelog [skip ci]"
-            git push origin HEAD:main
+            # Create unique branch name
+            BRANCH_NAME="changelog/update-$(git rev-parse --short HEAD)"
+            git checkout -b "$BRANCH_NAME"
+
+            # Commit with Claude Code signature
</code_context>

<issue_to_address>
**issue:** Using the short commit hash alone for the branch name can cause collisions on reruns.

On re-runs for the same HEAD (manual or retry), this branch name will be the same, causing `git checkout -b` to fail locally and `git push` to fail if the branch already exists on the remote. To avoid this, append something unique like a timestamp or `${{ github.run_id }}` to the branch name, e.g. `changelog/update-$(git rev-parse --short HEAD)-${{ github.run_id }}`.
</issue_to_address>

### Comment 2
<location> `.github/workflows/cd.yml:92-101` </location>
<code_context>
+        env:
+          GH_TOKEN: ${{ github.token }}
+
+      - name: Update GitHub release body
+        if: github.event_name == 'release' || startsWith(github.ref, 'refs/tags/v')
+        run: |
+          # Extract version from tag or release
+          if [ "${{ github.event_name }}" = "release" ]; then
+            TAG_NAME="${{ github.event.release.tag_name }}"
+          else
+            TAG_NAME="${GITHUB_REF#refs/tags/}"
+          fi
+
+          # Update release body with latest changelog
+          gh release edit "$TAG_NAME" \
+            --notes "${{ steps.git-cliff-latest.outputs.content }}" \
+            --repo ${{ github.repository }}
</code_context>

<issue_to_address>
**issue:** Editing releases on tag-based runs may fail when no GitHub Release exists.

This job runs on both `release` events and any `refs/tags/v*` ref. On tag pushes without an existing GitHub Release, `gh release edit "$TAG_NAME"` will fail because the release doesn’t exist. To avoid that, either restrict the `if:` to `github.event_name == 'release'` or add a pre-check (e.g., `gh release view "$TAG_NAME"` and skip if it fails) before editing.
</issue_to_address>

### Comment 3
<location> `.github/workflows/cd.yml:65-66` </location>
<code_context>
+            BRANCH_NAME="changelog/update-$(git rev-parse --short HEAD)"
+            git checkout -b "$BRANCH_NAME"
+
+            # Commit with Claude Code signature
+            git commit -m "$(cat <<'EOF'
+          docs: update changelog
+
</code_context>

<issue_to_address>
**suggestion:** Heredoc indentation will introduce leading spaces in the commit message.

Since the heredoc content is indented to match the YAML, those spaces will appear in the commit subject and body, which may look odd in git log and on GitHub. If that’s not desired, consider left-aligning the heredoc body (no leading spaces on content lines) or using YAML’s `|` block scalar to preserve the intended formatting without extra indentation.

Suggested implementation:

```
            BRANCH_NAME="changelog/update-$(git rev-parse --short HEAD)"
            git checkout -b "$BRANCH_NAME"

            # Commit with Claude Code signature
            git commit -m "docs: update changelog"

```

To fully remove the indentation issue from the heredoc, you should also:
1. Delete the remaining lines that belong to this heredoc block (the rest of the commit message body, if any, and the terminating `EOF` line).
2. If you need a multi-line commit message body, either:
   - Use a single `-m` with embedded `\n` characters, e.g.:
     `git commit -m $'docs: update changelog\n\nAdditional details here.'`
   - Or use multiple `-m` flags:
     `git commit -m "docs: update changelog" -m "Additional details here."`
Both of these approaches avoid heredoc indentation problems while keeping the YAML nicely indented.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@railway-app railway-app bot temporarily deployed to byte (byte / byte-pr-117) November 23, 2025 05:35 Destroyed
@railway-app railway-app bot temporarily deployed to byte (byte / byte-pr-117) November 23, 2025 05:39 Destroyed
@railway-app railway-app bot temporarily deployed to byte (byte / byte-pr-117) November 23, 2025 05:43 Destroyed
@JacobCoffee JacobCoffee force-pushed the feature/optimize-git-cliff-workflow branch from 5a98e08 to b3189f4 Compare November 23, 2025 05:50
@railway-app railway-app bot temporarily deployed to byte (byte / byte-pr-117) November 23, 2025 05:50 Destroyed
@JacobCoffee JacobCoffee force-pushed the feature/migrate-to-python3.14 branch from f832e7c to 20c8a9c Compare November 23, 2025 05:57
@railway-app railway-app bot temporarily deployed to byte (byte / byte-pr-117) November 23, 2025 06:01 Destroyed
Base automatically changed from feature/migrate-to-python3.14 to main November 23, 2025 06:04
JacobCoffee and others added 5 commits November 23, 2025 00:07
Add explicit output file path for git-cliff changelog generation
to docs/changelog.rst in pyproject.toml configuration.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Improve CD workflow with:
- Upgrade git-cliff-action to v4 for stability
- Generate full changelog history (not just latest)
- Create PR instead of direct commit to main
- Add GitHub release body updates with latest changelog
- Use gh CLI for GitHub operations
- Add Claude Code signature to commits
- Add pull-requests write permission
- Use OUTPUT env var instead of --output arg

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
- Restrict release body update to only release events (not tag pushes)
- Fix heredoc indentation using multiple -m flags instead

This prevents gh release edit from failing when tags are pushed
without an existing GitHub Release.
Append github.run_id to changelog branch name to ensure uniqueness
on manual or automatic reruns where the HEAD commit is the same.

This prevents git checkout -b and git push failures when the branch
already exists from a previous run.
Update sourcery pre-commit hook from v1.40.0 to v1.41.1 to resolve
Python 3.13 compatibility issues causing CI failures.
@JacobCoffee JacobCoffee force-pushed the feature/optimize-git-cliff-workflow branch from ad405f6 to 3e8ecce Compare November 23, 2025 06:09
@railway-app railway-app bot temporarily deployed to byte (byte / byte-pr-117) November 23, 2025 06:09 Destroyed
Sourcery v1.41.1 only provides wheels for macOS, causing
Linux CI builds to fail. Removing until cross-platform
support is available.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@railway-app railway-app bot temporarily deployed to byte (byte / byte-pr-117) November 23, 2025 06:17 Destroyed
@railway-app railway-app bot temporarily deployed to byte (byte / byte-pr-117) November 23, 2025 06:20 Destroyed
@railway-app railway-app bot temporarily deployed to byte (byte / byte-pr-117) November 23, 2025 06:20 Destroyed
@JacobCoffee JacobCoffee merged commit f8eaf14 into main Nov 23, 2025
4 checks passed
@JacobCoffee JacobCoffee deleted the feature/optimize-git-cliff-workflow branch November 23, 2025 06:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants