Skip to content

feat: Add OpenCode Issue Solver workflow#12209

Closed
penalosa wants to merge 13 commits intomainfrom
opencode-issue-solver
Closed

feat: Add OpenCode Issue Solver workflow#12209
penalosa wants to merge 13 commits intomainfrom
opencode-issue-solver

Conversation

@penalosa
Copy link
Copy Markdown
Contributor

@penalosa penalosa commented Jan 28, 2026

Adds an automated issue-solving workflow powered by OpenCode.

What it does

🤖✨ When a new issue is opened (from accounts 30+ days old) or when a team member adds the autofix label, this workflow:

  1. Assesses the issue using OpenCode's plan agent to determine if it's easily solvable
  2. Attempts a fix using OpenCode's build agent, running tests for affected packages
  3. If tests pass: Opens a draft PR and comments on the issue
  4. If tests fail: Comments on the issue with the attempted diff and a link to the workflow run

Security model

  • The assess and solve jobs have read-only repo permissions
  • Only the final create-pr job has write permissions, and it just applies a patch artifact
  • Manual triggers (label or workflow_dispatch) require wrangler team membership

Testing

Use the workflow_dispatch trigger to test from any branch before merging.


  • Tests
    • Tests included/updated
    • Automated tests not possible - manual testing has been completed as follows:
    • Additional testing not necessary because: This is a new GitHub Actions workflow that can be tested via workflow_dispatch
  • Public documentation
    • Cloudflare docs PR(s):
    • Documentation not necessary because: Internal workflow automation

Open with Devin

Automated issue triage and fixing powered by OpenCode.
@penalosa penalosa requested a review from a team as a code owner January 28, 2026 16:11
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jan 28, 2026

⚠️ No Changeset found

Latest commit: c45dc37

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 2 potential issues.

View issues and 5 additional flags in Devin Review.

Open in Devin Review

Comment thread .github/workflows/opencode-issue-solver.yml Outdated
Comment thread .github/workflows/opencode-issue-solver.yml
--title "fix: address issue #$ISSUE_NUM" \
--body "Fixes #$ISSUE_NUM.

🤖✨ Beep boop! I'm OpenCode, and I think I've squashed this bug! All automated tests are passing, but my silicon brain might have missed something—would love a human review before this gets merged.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

10/10

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jan 28, 2026

create-cloudflare

npm i https://pkg.pr.new/create-cloudflare@12209

@cloudflare/kv-asset-handler

npm i https://pkg.pr.new/@cloudflare/kv-asset-handler@12209

miniflare

npm i https://pkg.pr.new/miniflare@12209

@cloudflare/pages-shared

npm i https://pkg.pr.new/@cloudflare/pages-shared@12209

@cloudflare/unenv-preset

npm i https://pkg.pr.new/@cloudflare/unenv-preset@12209

@cloudflare/vite-plugin

npm i https://pkg.pr.new/@cloudflare/vite-plugin@12209

@cloudflare/vitest-pool-workers

npm i https://pkg.pr.new/@cloudflare/vitest-pool-workers@12209

@cloudflare/workers-editor-shared

npm i https://pkg.pr.new/@cloudflare/workers-editor-shared@12209

@cloudflare/workers-utils

npm i https://pkg.pr.new/@cloudflare/workers-utils@12209

wrangler

npm i https://pkg.pr.new/wrangler@12209

commit: 454c8de

- Use string comparison for isTeamMember check (was comparing string to boolean)
- Add git user config for workers-devprod bot before commit
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 3 new potential issues.

View issues and 7 additional flags in Devin Review.

Open in Devin Review

Comment thread .github/workflows/opencode-issue-solver.yml Outdated
Comment thread .github/workflows/opencode-issue-solver.yml Outdated
Comment thread .github/workflows/opencode-issue-solver.yml Outdated
- Use env vars instead of template literals to prevent JS injection in parse step
- Use env vars instead of shell interpolation to prevent shell injection in test step
- Use randomized heredoc delimiter to prevent delimiter collision in patch capture
- Switch to anthropics/claude-code-action@v1
- Use 'prompt' and 'claude_args' instead of deprecated inputs
- Use structured_output with --json-schema for assessment parsing
- Rename workflow to 'Autofix' and branch prefix to 'autofix/'
- Reference AGENTS.md for guidelines
Claude Code action doesn't automatically fetch issue context in automation
mode, so we explicitly fetch issue title/body/labels and include them in
the prompts for both assessment and fix steps.
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

View issue and 9 additional flags in Devin Review.

Open in Devin Review

Comment on lines +283 to +284
cat solution.patch >> $GITHUB_OUTPUT
echo "$DELIMITER" >> $GITHUB_OUTPUT
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Heredoc delimiter may not be recognized if patch file lacks trailing newline

When capturing the patch content as a GitHub Actions output using heredoc syntax, the delimiter must appear on its own line to be recognized. If solution.patch doesn't end with a newline (which can happen when the last modified file doesn't end with a newline), the delimiter will be appended to the last line of content rather than appearing on its own line.

Click to expand

How this bug is triggered

At lines 281-284, the patch content is captured using heredoc syntax:

DELIMITER="PATCH_EOF_$(date +%s)_$$"
echo "patch_content<<$DELIMITER" >> $GITHUB_OUTPUT
cat solution.patch >> $GITHUB_OUTPUT
echo "$DELIMITER" >> $GITHUB_OUTPUT

If solution.patch ends without a newline, the $GITHUB_OUTPUT file would contain:

patch_content<<PATCH_EOF_123_456
... patch content ...last linePATCH_EOF_123_456

Instead of the correct:

patch_content<<PATCH_EOF_123_456
... patch content ...last line
PATCH_EOF_123_456

Impact

The heredoc won't be properly terminated, causing patch_content to either include garbage data or be empty/malformed. This affects the comment-potential-fix job which uses this output to post the diff in issue comments.

Recommendation: Add a newline before the delimiter by changing line 283-284 to:

cat solution.patch >> $GITHUB_OUTPUT
echo "" >> $GITHUB_OUTPUT
echo "$DELIMITER" >> $GITHUB_OUTPUT

Or use printf '%s\n' "$DELIMITER" approach.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

View issue and 13 additional flags in Devin Review.

Open in Devin Review

Comment on lines +264 to +275
else
FILTER=""
for pkg in $PACKAGES; do
FILTER="$FILTER --filter=./packages/$pkg"
done
echo "Running tests for packages: $PACKAGES"
if pnpm run test:ci $FILTER; then
echo "passed=true" >> $GITHUB_OUTPUT
else
echo "passed=false" >> $GITHUB_OUTPUT
fi
fi
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Missing pnpm run check when affected packages are identified

When affected_packages is non-empty, the final-test step only runs pnpm run test:ci but skips pnpm run check. This is inconsistent with the branch when no packages are identified (which runs check).

Click to expand

The issue

Lines 264-275 only run pnpm run test:ci $FILTER when packages are identified:

else
  FILTER=""
  for pkg in $PACKAGES; do
    FILTER="$FILTER --filter=./packages/$pkg"
  done
  echo "Running tests for packages: $PACKAGES"
  if pnpm run test:ci $FILTER; then
    echo "passed=true" >> $GITHUB_OUTPUT
  ...

But test:ci (which is dotenv -- turbo test:ci) doesn't include the lint, type-check, and format checks that pnpm run check includes (see root package.json).

Impact

When the workflow identifies affected packages, it may create a PR (via the create-pr job at line 305) with code that:

  • Has TypeScript type errors
  • Has ESLint violations
  • Has formatting issues

These PRs will subsequently fail CI checks after being opened, defeating the purpose of the "tests passed" validation.

Recommendation: Add pnpm run check before running pnpm run test:ci $FILTER when packages are identified, or run both commands together: if pnpm run check && pnpm run test:ci $FILTER; then

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

View issue and 14 additional flags in Devin Review.

Open in Devin Review

Comment on lines +287 to +289
echo "patch_content<<$DELIMITER" >> $GITHUB_OUTPUT
cat solution.patch >> $GITHUB_OUTPUT
echo "$DELIMITER" >> $GITHUB_OUTPUT
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Patch content may exceed GitHub Actions output size limit causing truncation or failure

The patch_content is captured as a job output (line 195) and passed between jobs via needs.solve-issue.outputs.patch_content (line 405). However, GitHub Actions has a 1MB limit per individual output.

Click to expand

How it triggers

When the automated fix modifies many files or makes large changes, the generated solution.patch file can exceed 1MB. The workflow stores this entire patch in GITHUB_OUTPUT at lines 287-289:

DELIMITER="PATCH_EOF_$(date +%s)_$$"
echo "patch_content<<$DELIMITER" >> $GITHUB_OUTPUT
cat solution.patch >> $GITHUB_OUTPUT
echo "$DELIMITER" >> $GITHUB_OUTPUT

Actual vs Expected

  • Actual: If patch exceeds 1MB, the output will be silently truncated or the workflow step will fail. The comment-potential-fix job will then post a comment with a corrupted/incomplete diff.
  • Expected: The full patch should be displayed in the issue comment.

Impact

Users viewing the issue comment will see a truncated or malformed diff, making the attempted fix difficult to understand or apply manually. The workflow already uploads the patch as an artifact (which doesn't have this limit), but the comment-potential-fix job doesn't use the artifact - it relies on the output.

Recommendation: In the comment-potential-fix job, download the patch artifact instead of relying on the job output. Add a download-artifact step and read from the file, or add logic to truncate large patches with a message pointing to the full artifact.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

View issue and 16 additional flags in Devin Review.

Open in Devin Review

Comment on lines +419 to +432
const body = `🤖💭 I gave this one a shot, but couldn't quite get the tests to pass. Here's what I tried—maybe it'll be useful as a starting point for a human!

<details>
<summary><strong>🔧 My attempted fix</strong></summary>

\`\`\`diff
${diff}
\`\`\`

</details>

**My reasoning:** ${analysis.reasoning || 'No reasoning provided'}

📋 [Check out the test output](${runUrl}) to see where my circuits got tangled.`;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Large patch content may exceed GitHub comment size limit causing failure

When tests fail and the comment-potential-fix job runs, the entire patch content is embedded directly into the GitHub issue comment body. GitHub comments have a maximum size limit of 65,536 characters.

Click to expand

How the bug occurs

At line 405, the patch content is passed via job output:

PATCH_CONTENT: ${{ needs.solve-issue.outputs.patch_content }}

Then at lines 424-426, it's embedded directly in the comment:

const body = `...
\`\`\`diff
${diff}
\`\`\`
...`;

If Claude makes extensive changes across multiple files, the diff could easily exceed 65KB, causing github.rest.issues.createComment() at line 434 to fail with an HTTP 422 error.

Actual vs Expected

  • Actual: Large patches cause the comment creation to fail silently, leaving no feedback on the issue
  • Expected: The comment should be created successfully, potentially with truncated diff or a link to the full artifact

Impact

Users won't receive any feedback about the attempted fix when the patch is large, even though the workflow ran and produced a potential solution.

Recommendation: Truncate the diff if it exceeds a threshold (e.g., 50KB) and add a note directing users to download the full patch artifact, or link to the artifact instead of embedding the full diff.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

View issue and 19 additional flags in Devin Review.

Open in Devin Review

git config user.name "workers-devprod"

BRANCH="autofix/issue-$ISSUE_NUM"
git checkout -b "$BRANCH"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔴 Branch creation fails if autofix branch already exists from previous run

When the autofix workflow runs multiple times for the same issue, the git checkout -b command will fail because the branch autofix/issue-$ISSUE_NUM already exists.

Click to expand

Root cause

At line 343, the workflow unconditionally creates a new branch:

BRANCH="autofix/issue-$ISSUE_NUM"
git checkout -b "$BRANCH"

If the workflow was previously triggered for the same issue (e.g., by adding the autofix label, then removing and re-adding it, or via workflow_dispatch), the branch autofix/issue-<N> may already exist locally (after fetch) or remotely.

Impact

  • The git checkout -b command fails with error: fatal: a branch named 'autofix/issue-X' already exists
  • The entire create-pr job fails even though the solve job succeeded
  • Similarly, git push origin "$BRANCH" at line 353 would fail if the remote branch exists with different content

Expected behavior

The workflow should handle existing branches gracefully, either by:

  1. Checking if the branch exists and deleting it first
  2. Using git checkout -B (force create) instead of git checkout -b
  3. Adding a unique suffix (e.g., timestamp or run ID) to the branch name

Recommendation: Use git checkout -B "$BRANCH" to force-create the branch (overwriting if it exists), or add git branch -D "$BRANCH" 2>/dev/null || true before creating the branch. Also consider using git push --force-with-lease origin "$BRANCH" to handle the remote branch case.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@penalosa penalosa closed this Feb 3, 2026
@github-project-automation github-project-automation Bot moved this from Untriaged to Done in workers-sdk Feb 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants