Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/workflows/qwen-triage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -942,6 +942,30 @@ jobs:
fi
exit 1
fi
# A non-empty response is not necessarily a triage: on an API error
# the stream-json adapter appends the formatted error LAST
# (BaseJsonOutputAdapter appendText), optionally followed by
# rate-limit guidance. Run 33070765162 (triage for #10285) answered
# with a bare 268-char "[API Error: Connection error. ...]" that
# this step passed as success, so nothing retried or alerted. Strip
# the known suffixes, right-trim, then fail on the trailing shape --
# a real summary that merely quotes an API error mid-prose keeps
# writing afterwards and stays green. Same pattern as
# qwen-code-pr-review.yml.
BODY="${RESPONSE}"
for S in \
'Possible quota limitations in place or slow response times detected. Please wait and try again later.' \
'Please wait and try again later. To increase your limits, request a quota increase through AI Studio, or switch to another /auth method' \
'Please wait and try again later. To increase your limits, request a quota increase through Vertex, or switch to another /auth method'; do
BODY="${BODY%"$S"}"
done
BODY="${BODY%"${BODY##*[![:space:]]}"}"
case "${BODY}" in
*"[API Error: "*"]")
echo "::error title=Triage aborted by an API error::The model API returned an error instead of a triage, so no triage was posted. This is infrastructure, not this issue -- re-run the failed job."
exit 1
;;
esac
echo "Triage response received (${#RESPONSE} chars)."

- name: 'Notify silent triage re-run'
Expand Down
57 changes: 57 additions & 0 deletions scripts/tests/qwen-triage-workflow.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,63 @@ describe('qwen-triage tmux workflow', () => {
expect(run({ RESPONSE: 'null' }).status).not.toBe(0);
});

it('fails an API-error response instead of passing it as a triage (#10314)', () => {
const checkStep = step('Check triage response');
const body = checkStep.match(/run: \|-\n([\s\S]*)$/)?.[1];
expect(body).toBeTruthy();
const script = body.replace(/^ {10}/gm, '');
const run = (env) => {
const proc = spawnSync('bash', ['-c', script], {
env: {
...process.env,
RESPONSE: '',
TRIAGE_OUTCOME: 'success',
...env,
},
encoding: 'utf8',
});
return { status: proc.status, out: `${proc.stdout}${proc.stderr}` };
};

// The verbatim 268-char response of run 33070765162 (triage for #10285):
// a bare model-layer connection error that the old check classified as a
// successful triage, so nothing retried or alerted.
const apiError =
'[API Error: Connection error. (cause: connect ETIMEDOUT 47.94.20.201:443; connect ENETUNREACH 2408:400a:3e:effd:6ac1:ae6e:cde9:4efe:443 - Local (:::0); connect ETIMEDOUT 101.201.58.201:443; connect ENETUNREACH 2408:400a:3e:effb:c146:fb04:1e3d:5cc1:443 - Local (:::0))]';
const bare = run({ RESPONSE: apiError });
expect(bare.status).not.toBe(0);
expect(bare.out).toContain('API error');

// The stream-json adapter appends the formatted error LAST
// (BaseJsonOutputAdapter appendText), optionally followed by rate-limit
// guidance: an error after partial output and a quota error ending in
// the guidance suffix must fail too. Same shapes as
// qwen-code-pr-review.yml's classifier.
expect(
run({ RESPONSE: `Partial triage notes\n${apiError}` }).status,
).not.toBe(0);
expect(
run({
RESPONSE:
'[API Error: Quota exceeded.] Please wait and try again later. To increase your limits, request a quota increase through AI Studio, or switch to another /auth method',
}).status,
).not.toBe(0);

// A real summary still passes: one that merely QUOTES an API error
// mid-prose keeps writing afterwards (parity with the pr-review
// workflow's success_mentions_api_error case), and the normal
// empty/'null' behavior is untouched.
expect(
run({
RESPONSE:
'This issue reports "[API Error: Connection error.]" which points at the model endpoint; needs the endpoint config.',
}).status,
).toBe(0);
expect(run({ RESPONSE: 'triaged' }).status).toBe(0);
expect(run({ RESPONSE: '' }).status).not.toBe(0);
expect(run({ RESPONSE: 'null' }).status).not.toBe(0);
});

it('notifies the author when a manual triage re-run posts no review', () => {
const notifyStep = step('Notify silent triage re-run');

Expand Down
Loading