GitHub Integration is not pushing changes in PRs #986

Open
opened 2026-02-16 17:29:00 -05:00 by yindo · 3 comments
Owner

Originally created by @MarcelBochtler on GitHub (Jul 30, 2025).

Originally assigned to: @fwang on GitHub.

In my private repository a PR was opened by the renovate bot, updating a dependency.
This resulted in a test failure, and I described in a comment how I wanted this to be fixed and used /oc fix this.

The opencode.yml workflow was triggered, and according to the logs it fixed the issue, and created a commit:

{"command":"cd /home/runner/work/my-project/my-project && git commit -m \"...\"","description":"Commit the changes"}

Then opencode created the summary and posted this as a comment in the PR.

Unfortunately, the commit was never pushed to the PR branch and seems to be lost.

My configuration:

name: opencode

on:
  issue_comment:
    types: [created]

jobs:
  opencode:
    if: |
      contains(github.event.comment.body, '/oc') ||
      contains(github.event.comment.body, '/opencode')
    runs-on: ubuntu-latest
    permissions:
      contents: read
      id-token: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Run opencode
        uses: sst/opencode/github@latest
        env:
          OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
        with:
          model: openrouter/qwen/qwen3-coder:free

The used opencode version was 0.3.84

Originally created by @MarcelBochtler on GitHub (Jul 30, 2025). Originally assigned to: @fwang on GitHub. In my private repository a PR was opened by the renovate bot, updating a dependency. This resulted in a test failure, and I described in a comment how I wanted this to be fixed and used `/oc fix this`. The `opencode.yml` workflow was triggered, and according to the logs it fixed the issue, and created a commit: ```json {"command":"cd /home/runner/work/my-project/my-project && git commit -m \"...\"","description":"Commit the changes"} ``` Then opencode created the summary and posted this as a comment in the PR. Unfortunately, the commit was never pushed to the PR branch and seems to be lost. My configuration: ```yaml name: opencode on: issue_comment: types: [created] jobs: opencode: if: | contains(github.event.comment.body, '/oc') || contains(github.event.comment.body, '/opencode') runs-on: ubuntu-latest permissions: contents: read id-token: write steps: - name: Checkout repository uses: actions/checkout@v4 - name: Run opencode uses: sst/opencode/github@latest env: OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }} with: model: openrouter/qwen/qwen3-coder:free ``` The used opencode version was 0.3.84
Author
Owner

@fwang commented on GitHub (Aug 22, 2025):

hmm that's weird... does this happen everytime?

@fwang commented on GitHub (Aug 22, 2025): hmm that's weird... does this happen everytime?
Author
Owner

@AKTheKnight commented on GitHub (Nov 4, 2025):

Think I've hit this too, couldn't find this issue (Thanks bot for telling me): #3893

As far as I can tell it's because the branchIsDirty() check is false because git status --porcelain returns nothing if we've committed the changes, even if they haven't been pushed

Image
@AKTheKnight commented on GitHub (Nov 4, 2025): Think I've hit this too, couldn't find this issue (Thanks bot for telling me): #3893 As far as I can tell it's because the branchIsDirty() check is false because `git status --porcelain` returns nothing if we've committed the changes, even if they haven't been pushed <img width="447" height="180" alt="Image" src="https://github.com/user-attachments/assets/79e9ba48-8545-4e52-b959-fc42ccd41541" />
Author
Owner

@code-yeongyu commented on GitHub (Feb 6, 2026):

Root Cause Analysis

The bug has been identified. There are two separate implementations of branchIsDirty():

1. github/index.ts (Used by GitHub Action) — BUGGY

// Line 751-755
async function branchIsDirty() {
  console.log("Checking if branch is dirty...")
  const ret = await $`git status --porcelain`
  return ret.stdout.toString().trim().length > 0
}

This only checks for uncommitted changes via git status --porcelain. If the AI agent already committed the changes (via git commit), git status --porcelain returns empty — so this function returns false, and the push is skipped.

2. packages/opencode/src/cli/cmd/github.ts (Used by CLI opencode github) — FIXED

// Line 1112-1127
async function branchIsDirty(originalHead: string) {
  console.log("Checking if branch is dirty...")
  const ret = await $`git status --porcelain`
  const status = ret.stdout.toString().trim()
  if (status.length > 0) {
    return { dirty: true, uncommittedChanges: true }
  }
  const head = await $`git rev-parse HEAD`
  return {
    dirty: head.stdout.toString().trim() !== originalHead,
    uncommittedChanges: false,
  }
}

This correctly captures originalHead before AI work, then compares HEAD after — detecting both uncommitted changes AND new commits.

The Fix

The github/index.ts implementation needs to be updated to match the CLI version:

  1. Capture originalHead = git rev-parse HEAD before calling chat()
  2. In branchIsDirty(), check both git status --porcelain AND HEAD !== originalHead
  3. Pass uncommittedChanges flag to push functions so they know whether to git add . && git commit first

As @AKTheKnight correctly identified in #3893, the branchIsDirty() check is false because git status --porcelain returns nothing after committed changes.

The fix already exists in the CLI version (packages/opencode/src/cli/cmd/github.ts), it just needs to be ported to the GitHub Action version (github/index.ts).

@code-yeongyu commented on GitHub (Feb 6, 2026): ## Root Cause Analysis The bug has been identified. There are **two separate implementations** of `branchIsDirty()`: ### 1. `github/index.ts` (Used by GitHub Action) — **BUGGY** ❌ ```typescript // Line 751-755 async function branchIsDirty() { console.log("Checking if branch is dirty...") const ret = await $`git status --porcelain` return ret.stdout.toString().trim().length > 0 } ``` This only checks for **uncommitted changes** via `git status --porcelain`. If the AI agent already committed the changes (via `git commit`), `git status --porcelain` returns empty — so this function returns `false`, and the push is **skipped**. ### 2. `packages/opencode/src/cli/cmd/github.ts` (Used by CLI `opencode github`) — **FIXED** ✅ ```typescript // Line 1112-1127 async function branchIsDirty(originalHead: string) { console.log("Checking if branch is dirty...") const ret = await $`git status --porcelain` const status = ret.stdout.toString().trim() if (status.length > 0) { return { dirty: true, uncommittedChanges: true } } const head = await $`git rev-parse HEAD` return { dirty: head.stdout.toString().trim() !== originalHead, uncommittedChanges: false, } } ``` This correctly captures `originalHead` before AI work, then compares `HEAD` after — detecting both uncommitted changes AND new commits. ### The Fix The `github/index.ts` implementation needs to be updated to match the CLI version: 1. Capture `originalHead = git rev-parse HEAD` **before** calling `chat()` 2. In `branchIsDirty()`, check both `git status --porcelain` AND `HEAD !== originalHead` 3. Pass `uncommittedChanges` flag to push functions so they know whether to `git add . && git commit` first As @AKTheKnight correctly identified in #3893, the `branchIsDirty()` check is false because `git status --porcelain` returns nothing after committed changes. The fix already exists in the CLI version (`packages/opencode/src/cli/cmd/github.ts`), it just needs to be ported to the GitHub Action version (`github/index.ts`).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#986