Skip to content

fix(scm-github): handle HTTP 304 correctly in ETag guard catch blocks#1237

Open
awesome-pro wants to merge 1 commit intoComposioHQ:mainfrom
awesome-pro:fix/issue-1191-etag-guard-http-304
Open

fix(scm-github): handle HTTP 304 correctly in ETag guard catch blocks#1237
awesome-pro wants to merge 1 commit intoComposioHQ:mainfrom
awesome-pro:fix/issue-1191-etag-guard-http-304

Conversation

@awesome-pro
Copy link
Copy Markdown

@awesome-pro awesome-pro commented Apr 14, 2026

Summary

Resolves #1191 — ETag Guard treats HTTP 304 as failure, defeats caching optimization

Root Cause

The gh CLI exits with a non-zero exit code on HTTP 304 responses. This caused execFileAsync to throw before the try-block 304-detection code could run (dead code). Both catch blocks in checkPRListETag and checkCommitStatusETag were treating every HTTP 304 as a failure — logging a warning and returning true ("assume changed"). As a result, the full GraphQL batch ran every 30 seconds instead of being skipped when nothing had changed.

Changes Made

  • packages/plugins/scm-github/src/graphql-batch.ts — Added an early if (errorMsg.includes("HTTP 304")) return false check at the top of both catch blocks (Guard 1 in checkPRListETag, Guard 2 in checkCommitStatusETag). When the error is a 304, the function now correctly returns false (not modified — skip batch, use cache). All other errors fall through to the existing warn-and-return-true path unchanged.

Testing

  • All 140 tests pass (pnpm --filter @aoagents/ao-plugin-scm-github test)
  • The two test files that cover graphql-batch.ts directly (graphql-batch.test.ts — 65 tests, graphql-batch.integration.test.ts — 8 tests) pass with no changes needed

Notes

The fix matches on "HTTP 304" as a substring in the error message, which matches the standard gh CLI output format (gh: HTTP 304). The existing dead code in the try block (checking stdout for "HTTP/1.1 304" or "HTTP/2 304") is left untouched — removing it would be out of scope for this fix.

Fixes #1191

The gh CLI exits non-zero on HTTP 304 responses, causing execFileAsync
to throw before the 304-detection code in the try block could run
(dead code). Both catch blocks in checkPRListETag and
checkCommitStatusETag were treating 304 as a failure and returning true
(assume changed), causing the full GraphQL batch to run every 30s
instead of being skipped when nothing changed.

Add an early return false when the error message contains "HTTP 304"
in both catch blocks, so a 304 is correctly treated as "not modified".

Fixes ComposioHQ#1191
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes scm-github’s ETag guard logic so HTTP 304 (“Not Modified”) responses from gh api are treated as cache hits (skip GraphQL batch) rather than failures that force a refresh, restoring the intended polling optimization and resolving #1191.

Changes:

  • In checkPRListETag catch block, detect "HTTP 304" in the thrown error message and return false (not modified).
  • In checkCommitStatusETag catch block, detect "HTTP 304" in the thrown error message and return false (not modified).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 374 to +378
const errorMsg = err instanceof Error ? err.message : String(err);
// gh CLI exits non-zero on HTTP 304 — that means "not modified", not an error
if (errorMsg.includes("HTTP 304")) {
return false; // Not modified — skip batch, use cache (intended behavior)
}
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

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

The new 304 handling is in the catch path, but the existing unit tests for the guards only simulate 304 via a resolved stdout (success path). Please add/adjust a test to cover the real-world behavior where execFileAsync rejects on 304 (e.g., rejected Error message containing "gh: HTTP 304") so this regression stays protected.

Copilot uses AI. Check for mistakes.
Comment on lines 435 to +440
} catch (err) {
// On error, assume change to ensure we don't miss anything
const errorMsg = err instanceof Error ? err.message : String(err);
// gh CLI exits non-zero on HTTP 304 — that means "not modified", not an error
if (errorMsg.includes("HTTP 304")) {
return false; // Not modified — skip batch, use cache (intended behavior)
}
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

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

Same as Guard 1: add test coverage for the catch-path 304 behavior (where execFileAsync rejects on 304 and the handler returns false). Current tests cover only the resolved-stdout 304 branch, not the thrown-error scenario described in #1191.

Copilot uses AI. Check for mistakes.
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.

Bug: ETag Guard treats HTTP 304 as failure, defeats caching optimization

2 participants