diff --git a/README.md b/README.md index cdb4c3e09..00748e426 100644 --- a/README.md +++ b/README.md @@ -190,10 +190,16 @@ go to the [Gemini Assistant workflow documentation](./examples/workflows/gemini- - upload_artifacts: _(Optional, default: `false`)_ Whether to upload artifacts to the github action. +- output_to_file: _(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. + - use_pnpm: _(Optional, default: `false`)_ Whether or not to use pnpm instead of npm to install gemini-cli - workflow_name: _(Optional, default: `${{ github.workflow }}`)_ The GitHub workflow name, used for telemetry purposes. +- github_pr_number: _(Optional, default: `${{ github.event.pull_request.number }}`)_ The Pull Request number the CLI is operating on. Defaults to the event payload. + +- github_issue_number: _(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. + @@ -207,6 +213,10 @@ go to the [Gemini Assistant workflow documentation](./examples/workflows/gemini- - error: The error output from the Gemini CLI execution, if any. +- output_mode: Output mode used: "content" (default) or "file". + +- artifacts_dir: Path to gemini-artifacts/ directory containing stdout.log, stderr.log, telemetry.log. + diff --git a/action.yml b/action.yml index 7eccaf14b..84fbd70bf 100644 --- a/action.yml +++ b/action.yml @@ -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 @@ -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' @@ -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} @@ -349,23 +370,38 @@ runs: fi - # Set the captured response as a step output, supporting multiline - echo "gemini_response<> "${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<> "${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<> "${GITHUB_OUTPUT}" + echo "${ARTIFACTS_DIR}/stdout.log" >> "${GITHUB_OUTPUT}" + echo "EOF" >> "${GITHUB_OUTPUT}" + echo "gemini_errors<> "${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<> "${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<> "${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 @@ -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 @@ -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 }}'