-
Notifications
You must be signed in to change notification settings - Fork 185
Open
Description
TL;DR
The summary output field in the action contains invalid JSON when you enable json output format in the configuration, like this:
{
"output": {
"format": "json"
}
}This is a bug in the multi line field handling logic where the output file is cat'ed to GITHUB_OUTPUT but it is not done correctly.
Expected behavior
The summary output field should contain valid JSON. For example:
{
"response": "I have submitted the review. My task is complete.",
"stats": {}
}Observed behavior
There are extra characters appended at the end, like this:
{
"response": "I have submitted the review. My task is complete.",
"stats": {}
}EOF
gemini_errors<<EOFAction YAML
name: "π Review"
description: "Gemini-powered PR review."
inputs:
github_app_id:
description: "GitHub App ID"
required: true
github_app_private_key:
description: "GitHub App private key PEM for the Bucky app"
required: true
gemini_api_key:
description: "Gemini API key"
required: true
additional_context:
description: "Any additional context from the request"
required: false
default: ""
gemini_cli_version:
description: "Gemini CLI version"
required: false
default: ""
gemini_model:
description: "Gemini model"
required: false
default: ""
runs:
using: "composite"
steps:
- name: Mint identity token
id: mint_identity_token
uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b
with:
app-id: ${{ inputs.github_app_id }}
private-key: ${{ inputs.github_app_private_key }}
permission-contents: read
permission-issues: write
permission-pull-requests: write
- name: Run Gemini pull request review
id: gemini_pr_review
uses: google-github-actions/run-gemini-cli@v0
env:
GITHUB_TOKEN: ${{ steps.mint_identity_token.outputs.token }}
ISSUE_TITLE: ${{ github.event.pull_request.title || github.event.issue.title }}
ISSUE_BODY: ${{ github.event.pull_request.body || github.event.issue.body }}
PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number || github.event.issue.number }}
REPOSITORY: ${{ github.repository }}
ADDITIONAL_CONTEXT: ${{ inputs.additional_context }}
with:
gemini_api_key: ${{ inputs.gemini_api_key }}
gemini_cli_version: ${{ inputs.gemini_cli_version }}
gemini_model: ${{ inputs.gemini_model }}
gemini_debug: false
settings: |
{
"general": {
"disableAutoUpdate": false
},
"output": {
"format": "json"
},
"context": {
"fileName": "AGENTS.md"
},
"model": {
"maxSessionTurns": 25,
"chatCompression": {
"contextPercentageThreshold": 0.7
}
},
"telemetry": {
"enabled": false
},
"privacy": {
"usageStatisticsEnabled": false
},
"ui": {
"showMemoryUsage": true
},
"mcpServers": {
"github": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server:v0.19.0"
],
"includeTools": [
"add_comment_to_pending_review",
"pull_request_read",
"pull_request_review_write"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
}
},
"tools": {
"core": [
"glob",
"google_web_search",
"list_directory",
"read_file",
"read_many_files",
"run_shell_command(cat)",
"run_shell_command(echo)",
"run_shell_command(git)",
"run_shell_command(grep)",
"run_shell_command(head)",
"run_shell_command(nl)",
"run_shell_command(tail)",
"search_file_content",
"web_fetch"
]
}
}
prompt: |-
...
- name: Process summary
id: process_summary
shell: bash
if: always()
env:
GEMINI_SUMMARY: ${{ steps.gemini_pr_review.outputs.summary }}
run: |
set -uo pipefail
echo "::group::Process summary"
# the output can have junk after the JSON structure so use jq to remove it by having it parse from { to }
JSON_OBJ="$(echo "$GEMINI_SUMMARY" | jq -R -s 'match("(?s)\\{.*\\}") | .string | fromjson')"
# verify it
echo "$JSON_OBJ" | jq empty
# safely output multiline string
DELIMITER="__GEMINI_EOF__"
{
echo "json<<${DELIMITER}"
echo "${JSON_OBJ}"
echo "${DELIMITER}"
} >> "${GITHUB_OUTPUT}"
echo "::endgroup::"
- name: Logs
if: always()
shell: bash
env:
GEMINI_SUMMARY: ${{ steps.gemini_pr_review.outputs.summary }}
GEMINI_SUMMARY_JSON: ${{ steps.process_summary.outputs.json }}
GEMINI_ERROR: ${{ steps.gemini_pr_review.outputs.error }}
run: |
set -uo pipefail
# show the plain response in text
echo "::group::Gemini response"
echo "$GEMINI_SUMMARY_JSON" | jq -r .response
echo "::endgroup::"
# dump the entire summary
echo "::group::Gemini output"
echo "$GEMINI_SUMMARY"
echo "::endgroup::"
# dump the errors
echo "::group::Gemini errors"
echo "$GEMINI_ERROR"
echo "::endgroup::"Log output
Run google-github-actions/run-gemini-cli@v0
Run set -exuo pipefail
+ auth_methods=0
+ [[ true == \t\r\u\e ]]
+ (( ++auth_methods ))
+ [[ false == \t\r\u\e ]]
+ [[ false == \t\r\u\e ]]
+ [[ 1 -eq 0 ]]
+ [[ 1 -gt 1 ]]
+ [[ false == \t\r\u\e ]]
+ [[ false == \t\r\u\e ]]
+ [[ true == \t\r\u\e ]]
+ [[ false == \t\r\u\e ]]
+ [[ false == \t\r\u\e ]]
Run mkdir -p .gemini/
Run set -euo pipefail
Run set -euo pipefail
Installing Gemini CLI from npm: @google/gemini-cli@latest
Verifying installation:
0.10.0
Run set -euo pipefail
Run set -uo pipefail
Process summary
Run set -uo pipefail
Gemini response
I have submitted the review. My task is complete.
Gemini output
{
"response": "I have submitted the review. My task is complete.",
"stats": {
"models": {
"gemini-2.5-pro": {
"api": {
"totalRequests": 8,
"totalErrors": 0,
"totalLatencyMs": 40355
},
"tokens": {
"prompt": 280112,
"candidates": 612,
"total": 282069,
"cached": 194828,
"thoughts": 1345,
"tool": 0
}
}
},
"tools": {
"totalCalls": 7,
"totalSuccess": 7,
"totalFail": 0,
"totalDurationMs": 5691,
"totalDecisions": {
"accept": 0,
"reject": 0,
"modify": 0,
"auto_accept": 7
},
"byName": {
"read_file": {
"count": 1,
"success": 1,
"fail": 0,
"durationMs": 5,
"decisions": {
"accept": 0,
"reject": 0,
"modify": 0,
"auto_accept": 1
}
},
"pull_request_read": {
"count": 2,
"success": 2,
"fail": 0,
"durationMs": 822,
"decisions": {
"accept": 0,
"reject": 0,
"modify": 0,
"auto_accept": 2
}
},
"pull_request_review_write": {
"count": 2,
"success": 2,
"fail": 0,
"durationMs": 2408,
"decisions": {
"accept": 0,
"reject": 0,
"modify": 0,
"auto_accept": 2
}
},
"add_comment_to_pending_review": {
"count": 2,
"success": 2,
"fail": 0,
"durationMs": 2456,
"decisions": {
"accept": 0,
"reject": 0,
"modify": 0,
"auto_accept": 2
}
}
}
},
"files": {
"totalLinesAdded": 0,
"totalLinesRemoved": 0
}
}
}EOF
gemini_errors<<EOF
Gemini errors
Additional information
The problem is here, with these lines in action.yml, ~line 272:
# Set the captured response as a step output, supporting multiline
echo "gemini_response<<EOF" >> "${GITHUB_OUTPUT}"
cat "${TEMP_STDOUT}" >> "${GITHUB_OUTPUT}"
echo "EOF" >> "${GITHUB_OUTPUT}"This does not terminate the redirection correctly and ends up picking up the extra output until the next redirection is started. This works correctly:
# safely output multiline string using a more unique delimiter
DELIMITER="__GEMINI_EOF__"
{
echo "gemini_response<<${DELIMITER}"
cat "${TEMP_STDOUT}"
echo "${DELIMITER}"
} >> "${GITHUB_OUTPUT}"Metadata
Metadata
Assignees
Labels
No labels