Skip to content

feat: automate release pipeline and close the proactive→implement loop#25

Merged
greynewell merged 2 commits intomainfrom
claude/factory-improvements-20260227-0126
Feb 27, 2026
Merged

feat: automate release pipeline and close the proactive→implement loop#25
greynewell merged 2 commits intomainfrom
claude/factory-improvements-20260227-0126

Conversation

@greynewell
Copy link
Contributor

@greynewell greynewell commented Feb 27, 2026

Summary

  • Goreleaser: cross-platform binary releases (linux/darwin/windows × amd64/arm64) triggered on v* tags — users can now download binaries without having Go installed
  • Auto-tag: on every push to main, bumps semver automatically (feat: → minor, everything else → patch, breaking → major) and pushes a tag, which then triggers goreleaser
  • Fix proactive loop: claude-proactive.yml now appends @claude please implement this to every issue it creates — issues were being created but never picked up
  • Fix auto-assign: claude-auto-assign.yml now also triggers for app/claude bot-created issues (not just org members), and skips if @claude is already in the body to avoid double-firing
  • CLAUDE.md: documents the @claude requirement when creating issues

Before / After

Before: proactive Claude finds bugs → creates issues → issues sit idle forever (auto-assign skips bots, no @claude in body)

After: proactive Claude finds bugs → creates issues with @claude → auto-assign fires as backstop → Claude implements → shepherd merges → auto-tag fires → goreleaser publishes binaries

Test plan

  • Merge this PR and verify auto-tag creates v0.1.0
  • Verify goreleaser release workflow fires and publishes binaries
  • Wait for next hourly proactive run and verify created issues get picked up by Claude

Summary by CodeRabbit

  • New Features

    • Automated semantic version tagging on main commits based on commit messages.
    • Automated release pipeline to build and publish cross-platform binaries.
  • Documentation

    • Guidance added for appending a standardized "@claude" postscript to issue bodies and for Co-Authored-By commit footers.
  • Chores

    • Bot workflow improvements: early skip when "@claude" present and refined handling for Claude bot vs. membership checks.

@coderabbitai
Copy link

coderabbitai bot commented Feb 27, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6030e5d and 92ca3ad.

📒 Files selected for processing (2)
  • .github/workflows/auto-tag.yml
  • .github/workflows/claude-auto-assign.yml

Walkthrough

Adds CI workflows and goreleaser config: auto-generates semantic tags from commit messages, runs releases on tag pushes, and refines Claude-related workflows to detect/append @claude in issue bodies; updates CLAUDE.md with guidance for using @claude. (50 words)

Changes

Cohort / File(s) Summary
Auto-tag workflow
\.github/workflows/auto-tag.yml
New GitHub Action that reads latest semver tag, inspects the most recent commit message to decide MAJOR/MINOR/PATCH bump (BREAKING→major, feat→minor, else→patch), creates vMAJOR.MINOR.PATCH tag, and pushes it (skips if tag exists).
Release automation & config
\.github/workflows/release.yml, \.goreleaser.yaml
Adds a release workflow triggered on v* tag pushes that runs goreleaser. Adds .goreleaser.yaml with multi-OS/arch builds, archive naming, checksums, changelog filters, and pre-build hook.
Claude workflows
\.github/workflows/claude-auto-assign.yml, \.github/workflows/claude-proactive.yml
Modifies Claude flows to early-skip when issue body already contains @claude, adds an isClaudeBot bypass for membership checks, and appends the line @claude please implement this to auto-created issue bodies.
Documentation
CLAUDE.md
Adds guidance to end issue bodies with @claude and documents Co-Authored-By footer expectations for commits.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Dev as Developer
  participant Repo as GitHub Repo
  participant AutoTag as Action: Auto-Tag
  participant GitHub as GitHub (API)
  participant ReleaseWF as Action: Release
  participant Goreleaser as Goreleaser

  Dev->>Repo: push to main
  Repo->>AutoTag: push event (main)
  AutoTag->>Repo: fetch tags & commits
  AutoTag->>AutoTag: parse latest tag and last commit message
  AutoTag->>Repo: create annotated tag vMAJOR.MINOR.PATCH
  AutoTag->>GitHub: push tag
  GitHub->>ReleaseWF: tag push triggers release workflow
  ReleaseWF->>Repo: checkout tag
  ReleaseWF->>Goreleaser: invoke goreleaser release
  Goreleaser->>GitHub: upload artifacts & create Release
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🏷️ Commit speaks, a version wakes,
🤖 A tiny line: "@claude please implement this" it takes,
🐧 Cross-platform builds in tidy wakes,
📦 Archives, checksums, release on the lakes,
✨ Tag, push, and everybody celebrates.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately describes the main changes: automating the release pipeline (Goreleaser + auto-tag workflow) and fixing the proactive→implement loop (claude-proactive appends @claude, claude-auto-assign updated to handle bot issues).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/factory-improvements-20260227-0126

Comment @coderabbitai help to get the list of available commands and usage tips.

- Add goreleaser config for cross-platform binary releases (linux/darwin/windows, amd64/arm64)
- Add release.yml workflow: triggers goreleaser on v* tags
- Add auto-tag.yml workflow: bumps semver on every main push (feat→minor, fix/other→patch, breaking→major)
- Fix claude-proactive.yml: always end issue bodies with @claude so created issues get picked up
- Fix claude-auto-assign.yml: also trigger for app/claude bot issues, skip if @claude already present
- Update CLAUDE.md: document @claude requirement for issues and co-author requirement for commits

Co-Authored-By: Grey Newell <greyshipscode@gmail.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@greynewell greynewell force-pushed the claude/factory-improvements-20260227-0126 branch from 58bed95 to 6030e5d Compare February 27, 2026 01:51
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
CLAUDE.md (1)

22-24: Add a language specifier to the fenced code block.

The linter is flagging this code block because it doesn't have a language specified. Even for plain text examples, adding something like text or markdown helps with consistency and silences the warning.

Think of it like this: if someone's editor has syntax highlighting, specifying the language (even text) makes the intent clear.

✏️ Suggested fix
-```
+```text
 `@claude` please implement this
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @CLAUDE.md around lines 22 - 24, Update the fenced code block in CLAUDE.md so
it includes a language specifier (e.g., change the opening totext)
surrounding the "@claude please implement this" block; locate the
triple-backtick fence in the file and add the specifier to silence the linter
and make the intent explicit.


</details>

</blockquote></details>
<details>
<summary>.github/workflows/auto-tag.yml (1)</summary><blockquote>

`39-45`: **Tag creation looks solid.**

Using the GitHub Actions bot identity for commits/tags is the standard pattern. The tag push will trigger your release workflow since it matches `v*`.

One thing to be aware of: if this workflow runs on a merge commit that already has a tag (like a re-run), it'll try to create a duplicate tag and fail. That's probably fine since the release would already exist, but if you want to be defensive:


<details>
<summary>🛡️ Optional: Skip if tag already exists</summary>

```diff
           NEW_TAG="v${MAJOR}.${MINOR}.${PATCH}"
           echo "New tag: $NEW_TAG"

+          # Skip if tag already exists
+          if git rev-parse "$NEW_TAG" >/dev/null 2>&1; then
+            echo "Tag $NEW_TAG already exists, skipping."
+            exit 0
+          fi
+
           git config user.name "github-actions[bot]"
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/auto-tag.yml around lines 39 - 45, Check whether the tag
already exists before creating/pushing to avoid duplicate-tag failures: use the
NEW_TAG variable and run a remote check like git ls-remote --tags origin
"$NEW_TAG" (or git rev-parse --verify "refs/tags/$NEW_TAG") and only run git tag
"$NEW_TAG" and git push origin "$NEW_TAG" when that check returns no match; if
the tag exists, skip tagging/pushing and optionally echo a message. Ensure the
conditional wraps the existing git tag and git push origin lines so the workflow
is defensive against re-runs.
```

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🤖 Prompt for all review comments with AI agents</summary>

Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/auto-tag.yml:

  • Around line 22-27: The pipeline can produce an empty LATEST and the fallback
    after the pipe won't run; ensure LATEST is non-empty before extracting MAJOR,
    MINOR, and PATCH by assigning a default when empty (for example, use bash
    parameter expansion or an explicit if/test to set LATEST to v0.0.0 if it is
    empty), then derive MAJOR, MINOR, and PATCH from that guaranteed-nonempty LATEST
    variable so you never end up with empty parts or a malformed tag.

In @.github/workflows/claude-auto-assign.yml:

  • Around line 29-30: The bot-detection logic in the isClaudeBot assignment is
    too broad and uses a non-standard string; replace the current check (author ===
    'app/claude' || author.startsWith('claude')) with an exact match against the
    GitHub App bot name — e.g. author === 'claude[bot]' (and optionally author ===
    'app/claude[bot]' if you want to be defensive) — or use a strict regex like
    /^claude([bot])?$/ to avoid matching human usernames; update the isClaudeBot
    variable accordingly.

Nitpick comments:
In @.github/workflows/auto-tag.yml:

  • Around line 39-45: Check whether the tag already exists before
    creating/pushing to avoid duplicate-tag failures: use the NEW_TAG variable and
    run a remote check like git ls-remote --tags origin "$NEW_TAG" (or git rev-parse
    --verify "refs/tags/$NEW_TAG") and only run git tag "$NEW_TAG" and git push
    origin "$NEW_TAG" when that check returns no match; if the tag exists, skip
    tagging/pushing and optionally echo a message. Ensure the conditional wraps the
    existing git tag and git push origin lines so the workflow is defensive against
    re-runs.

In @CLAUDE.md:

  • Around line 22-24: Update the fenced code block in CLAUDE.md so it includes a
    language specifier (e.g., change the opening totext) surrounding the
    "@claude please implement this" block; locate the triple-backtick fence in the
    file and add the specifier to silence the linter and make the intent explicit.

</details>

---

<details>
<summary>ℹ️ Review info</summary>

**Configuration used**: Organization UI

**Review profile**: CHILL

**Plan**: Pro

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 0b0577225b854f625a8a09583be9a9ba67937592 and 58bed958ff3d8f55728785576c33a70db835a78f.

</details>

<details>
<summary>📒 Files selected for processing (6)</summary>

* `.github/workflows/auto-tag.yml`
* `.github/workflows/claude-auto-assign.yml`
* `.github/workflows/claude-proactive.yml`
* `.github/workflows/release.yml`
* `.goreleaser.yaml`
* `CLAUDE.md`

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
CLAUDE.md (1)

22-24: Minor: Add language specifiers to fenced code blocks.

The linter is flagging these code blocks because they don't have a language tag. Even for plain text snippets, you can use text or plaintext to make it explicit and quiet the warning.

Think of it like: the linter doesn't know if you forgot to specify a language or if it's intentionally plain text, so it asks you to be explicit.

✏️ Suggested fix
-```
+```text
 `@claude` please implement this

And similarly for the co-author block:

```diff
-```
+```text
 Co-Authored-By: Grey Newell <greyshipscode@gmail.com>
 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
</details>


Also applies to: 37-40

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @CLAUDE.md around lines 22 - 24, Add explicit language tags to the fenced
code blocks containing the literal snippet "@claude please implement this" and
the co-author lines "Co-Authored-By: Grey Newell greyshipscode@gmail.com" and
"Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com" by changing the
fences from totext (or ```plaintext) so the linter recognizes them as
plain text; update the code fences surrounding those exact strings to include
the language specifier.


</details>

</blockquote></details>
<details>
<summary>.github/workflows/auto-tag.yml (1)</summary><blockquote>

`19-45`: **Consider adding `set -e` for safer script execution.**

Right now, if any command fails (like the `git push`), the script just keeps going. Adding `set -e` at the top of the run block makes it exit immediately on any error, which is usually what you want for CI scripts.



<details>
<summary>✏️ Suggested addition</summary>

```diff
       - name: Bump version and tag
         run: |
+          set -e
           # Get latest semver tag, default to v0.0.0
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/auto-tag.yml around lines 19 - 45, The run block should
exit on any failing command to avoid continuing after errors (e.g., failed git
push); add a shell safety flag such as set -e (optionally set -o pipefail) at
the top of the Bump version and tag run block so that the subsequent commands
manipulating LATEST, MAJOR, MINOR, PATCH, MSG and creating/pushing NEW_TAG stop
immediately on failure.
```

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🤖 Prompt for all review comments with AI agents</summary>

Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/auto-tag.yml:

  • Around line 44-45: The workflow currently runs git tag "$NEW_TAG" and git push
    origin "$NEW_TAG" which will fail if the tag already exists; update the job to
    first check for the tag and skip or handle it gracefully: test for a local tag
    (git rev-parse --verify "refs/tags/$NEW_TAG") and for a remote tag (git
    ls-remote --tags origin "$NEW_TAG") and only run git tag "$NEW_TAG" and git push
    origin "$NEW_TAG" when not present, or explicitly decide to use git tag -f and
    git push --force origin "$NEW_TAG" if overwriting is intended—ensure your change
    references NEW_TAG, git tag and git push origin in the workflow so duplicate-tag
    conditions are detected and reported clearly instead of causing an opaque
    failure.

Nitpick comments:
In @.github/workflows/auto-tag.yml:

  • Around line 19-45: The run block should exit on any failing command to avoid
    continuing after errors (e.g., failed git push); add a shell safety flag such as
    set -e (optionally set -o pipefail) at the top of the Bump version and tag run
    block so that the subsequent commands manipulating LATEST, MAJOR, MINOR, PATCH,
    MSG and creating/pushing NEW_TAG stop immediately on failure.

In @CLAUDE.md:

  • Around line 22-24: Add explicit language tags to the fenced code blocks
    containing the literal snippet "@claude please implement this" and the co-author
    lines "Co-Authored-By: Grey Newell greyshipscode@gmail.com" and
    "Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com" by changing the
    fences from totext (or ```plaintext) so the linter recognizes them as
    plain text; update the code fences surrounding those exact strings to include
    the language specifier.

</details>

---

<details>
<summary>ℹ️ Review info</summary>

**Configuration used**: Organization UI

**Review profile**: CHILL

**Plan**: Pro

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 58bed958ff3d8f55728785576c33a70db835a78f and 6030e5dbb1d3436e5052f53af74d1d749c68e4a0.

</details>

<details>
<summary>📒 Files selected for processing (6)</summary>

* `.github/workflows/auto-tag.yml`
* `.github/workflows/claude-auto-assign.yml`
* `.github/workflows/claude-proactive.yml`
* `.github/workflows/release.yml`
* `.goreleaser.yaml`
* `CLAUDE.md`

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (2)</summary>

* .github/workflows/release.yml
* .goreleaser.yaml

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

- auto-tag.yml: fix LATEST fallback using bash parameter expansion (pipe
  swallows grep exit code, || never fires)
- auto-tag.yml: skip gracefully if computed tag already exists
- claude-auto-assign.yml: fix bot detection to use correct GitHub App
  username format (claude[bot] not app/claude)

Co-Authored-By: Grey Newell <greyshipscode@gmail.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

1 participant