Skip to content
Open
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
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,16 @@ go to the [Gemini Assistant workflow documentation](./examples/workflows/gemini-

- <a name="__input_upload_artifacts"></a><a href="#user-content-__input_upload_artifacts"><code>upload_artifacts</code></a>: _(Optional, default: `false`)_ Whether to upload artifacts to the github action.

- <a name="__input_output_to_file"></a><a href="#user-content-__input_output_to_file"><code>output_to_file</code></a>: _(Optional, default: `false`)_ When true, redirect all output to files and return file paths as step outputs instead of content. Useful when gemini_debug is true to avoid exceeding GitHub Actions output limits.

- <a name="__input_use_pnpm"></a><a href="#user-content-__input_use_pnpm"><code>use_pnpm</code></a>: _(Optional, default: `false`)_ Whether or not to use pnpm instead of npm to install gemini-cli

- <a name="__input_workflow_name"></a><a href="#user-content-__input_workflow_name"><code>workflow_name</code></a>: _(Optional, default: `${{ github.workflow }}`)_ The GitHub workflow name, used for telemetry purposes.

- <a name="__input_github_pr_number"></a><a href="#user-content-__input_github_pr_number"><code>github_pr_number</code></a>: _(Optional, default: `${{ github.event.pull_request.number }}`)_ The Pull Request number the CLI is operating on. Defaults to the event payload.

- <a name="__input_github_issue_number"></a><a href="#user-content-__input_github_issue_number"><code>github_issue_number</code></a>: _(Optional, default: `${{ github.event.issue.number }}`)_ The Issue number (or comma-separated list of issue numbers) the CLI is operating on. Defaults to the event payload.


<!-- END_AUTOGEN_INPUTS -->
<!-- prettier-ignore-end -->
Expand All @@ -207,6 +213,10 @@ go to the [Gemini Assistant workflow documentation](./examples/workflows/gemini-

- <a name="__output_error"></a><a href="#user-content-__output_error"><code>error</code></a>: The error output from the Gemini CLI execution, if any.

- <a name="__output_output_mode"></a><a href="#user-content-__output_output_mode"><code>output_mode</code></a>: Output mode used: "content" (default) or "file".

- <a name="__output_artifacts_dir"></a><a href="#user-content-__output_artifacts_dir"><code>artifacts_dir</code></a>: Path to gemini-artifacts/ directory containing stdout.log, stderr.log, telemetry.log.


<!-- END_AUTOGEN_OUTPUTS -->
<!-- prettier-ignore-end -->
Expand Down
114 changes: 80 additions & 34 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ inputs:
description: 'Whether to upload artifacts to the github action.'
required: false
default: 'false'
output_to_file:
description: 'When true, redirect all output to files and return file paths as step outputs instead of content. Useful when gemini_debug is true to avoid exceeding GitHub Actions output limits.'
required: false
default: 'false'
use_pnpm:
description: 'Whether or not to use pnpm instead of npm to install gemini-cli'
required: false
Expand All @@ -107,6 +111,12 @@ outputs:
error:
description: 'The error output from the Gemini CLI execution, if any.'
value: '${{ steps.gemini_run.outputs.gemini_errors }}'
output_mode:
description: 'Output mode used: "content" (default) or "file".'
value: '${{ steps.gemini_run.outputs.output_mode }}'
artifacts_dir:
description: 'Path to gemini-artifacts/ directory containing stdout.log, stderr.log, telemetry.log.'
value: '${{ steps.gemini_run.outputs.artifacts_dir }}'

runs:
using: 'composite'
Expand Down Expand Up @@ -301,12 +311,23 @@ runs:
# Keep track of whether we've failed
FAILED=false

# Determine debug flag
DEBUG_FLAG=""
if [[ "${GEMINI_DEBUG}" = true ]]; then
DEBUG_FLAG="--debug"
fi

# Run Gemini CLI with the provided prompt, using JSON output format
# We capture stdout (JSON) to TEMP_STDOUT and stderr to TEMP_STDERR
if [[ "${GEMINI_DEBUG}" = true ]]; then
if [[ "${OUTPUT_TO_FILE}" = true ]]; then
echo "::notice::Gemini CLI output redirected to files (gemini-artifacts/)"
if ! gemini ${DEBUG_FLAG} --yolo --prompt "${PROMPT}" --output-format json 2> "${TEMP_STDERR}" 1> "${TEMP_STDOUT}"; then
FAILED=true
fi
elif [[ "${GEMINI_DEBUG}" = true ]]; then
echo "::warning::Gemini CLI debug logging is enabled. This will stream responses, which could reveal sensitive information if processed with untrusted inputs."
echo "::: Start Gemini CLI STDOUT :::"
if ! gemini --debug --yolo --prompt "${PROMPT}" --output-format json 2> >(tee "${TEMP_STDERR}" >&2) | tee "${TEMP_STDOUT}"; then
if ! gemini ${DEBUG_FLAG} --yolo --prompt "${PROMPT}" --output-format json 2> >(tee "${TEMP_STDERR}" >&2) | tee "${TEMP_STDOUT}"; then
FAILED=true
fi
# Wait for async stderr logging to complete. This is because process substitution in Bash is async so let tee finish writing to ${TEMP_STDERR}
Expand Down Expand Up @@ -349,23 +370,38 @@ runs:
fi


# Set the captured response as a step output, supporting multiline
echo "gemini_response<<EOF" >> "${GITHUB_OUTPUT}"
if [[ -n "${RESPONSE}" ]]; then
echo "${RESPONSE}" >> "${GITHUB_OUTPUT}"
else
cat "${TEMP_STDOUT}" >> "${GITHUB_OUTPUT}"
fi
echo "EOF" >> "${GITHUB_OUTPUT}"
ARTIFACTS_DIR="$(pwd)/gemini-artifacts"
echo "artifacts_dir=${ARTIFACTS_DIR}" >> "${GITHUB_OUTPUT}"

# Set the captured errors as a step output, supporting multiline
echo "gemini_errors<<EOF" >> "${GITHUB_OUTPUT}"
if [[ -n "${ERROR_JSON}" ]]; then
echo "${ERROR_JSON}" >> "${GITHUB_OUTPUT}"
if [[ "${OUTPUT_TO_FILE}" = true ]]; then
echo "output_mode=file" >> "${GITHUB_OUTPUT}"
# Return file paths instead of content
echo "gemini_response<<EOF" >> "${GITHUB_OUTPUT}"
echo "${ARTIFACTS_DIR}/stdout.log" >> "${GITHUB_OUTPUT}"
echo "EOF" >> "${GITHUB_OUTPUT}"
echo "gemini_errors<<EOF" >> "${GITHUB_OUTPUT}"
echo "${ARTIFACTS_DIR}/stderr.log" >> "${GITHUB_OUTPUT}"
echo "EOF" >> "${GITHUB_OUTPUT}"
else
cat "${TEMP_STDERR}" >> "${GITHUB_OUTPUT}"
echo "output_mode=content" >> "${GITHUB_OUTPUT}"
# Set the captured response as a step output, supporting multiline
echo "gemini_response<<EOF" >> "${GITHUB_OUTPUT}"
if [[ -n "${RESPONSE}" ]]; then
echo "${RESPONSE}" >> "${GITHUB_OUTPUT}"
else
cat "${TEMP_STDOUT}" >> "${GITHUB_OUTPUT}"
fi
echo "EOF" >> "${GITHUB_OUTPUT}"

# Set the captured errors as a step output, supporting multiline
echo "gemini_errors<<EOF" >> "${GITHUB_OUTPUT}"
if [[ -n "${ERROR_JSON}" ]]; then
echo "${ERROR_JSON}" >> "${GITHUB_OUTPUT}"
else
cat "${TEMP_STDERR}" >> "${GITHUB_OUTPUT}"
fi
echo "EOF" >> "${GITHUB_OUTPUT}"
fi
echo "EOF" >> "${GITHUB_OUTPUT}"

# Generate Job Summary
if [[ -n "${GITHUB_STEP_SUMMARY:-}" ]]; then
Expand All @@ -378,26 +414,35 @@ runs:
echo "${PROMPT}"
echo "\`\`\`"
echo
if [[ -n "${RESPONSE}" ]]; then
echo "#### Response"
echo
echo "${RESPONSE}"
echo
fi
if [[ -n "${ERROR_JSON}" ]]; then
echo "#### Error"
echo
echo "\`\`\`json"
echo "${ERROR_JSON}"
echo "\`\`\`"
echo
elif [[ "${FAILED}" == "true" ]]; then
echo "#### Error Output"
if [[ "${OUTPUT_TO_FILE}" = true ]]; then
echo "#### Output (file mode)"
echo
echo "\`\`\`"
cat "${TEMP_STDERR}"
echo "\`\`\`"
echo "Output redirected to files:"
echo "- stdout.log ($(wc -c < "${TEMP_STDOUT}" | xargs) bytes)"
echo "- stderr.log ($(wc -c < "${TEMP_STDERR}" | xargs) bytes)"
echo
else
if [[ -n "${RESPONSE}" ]]; then
echo "#### Response"
echo
echo "${RESPONSE}"
echo
fi
if [[ -n "${ERROR_JSON}" ]]; then
echo "#### Error"
echo
echo "\`\`\`json"
echo "${ERROR_JSON}"
echo "\`\`\`"
echo
elif [[ "${FAILED}" == "true" ]]; then
echo "#### Error Output"
echo
echo "\`\`\`"
cat "${TEMP_STDERR}"
echo "\`\`\`"
echo
fi
fi
} >> "${GITHUB_STEP_SUMMARY}"
fi
Expand All @@ -415,6 +460,7 @@ runs:
fi
env:
GEMINI_DEBUG: '${{ fromJSON(inputs.gemini_debug || false) }}'
OUTPUT_TO_FILE: '${{ fromJSON(inputs.output_to_file || false) }}'
GEMINI_API_KEY: '${{ inputs.gemini_api_key }}'
SURFACE: 'GitHub'
GOOGLE_CLOUD_PROJECT: '${{ inputs.gcp_project_id }}'
Expand Down