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
6 changes: 4 additions & 2 deletions .github/workflows/gemini-invoke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,16 @@ jobs:
google_api_key: '${{ secrets.GOOGLE_API_KEY }}'
use_gemini_code_assist: '${{ vars.GOOGLE_GENAI_USE_GCA }}'
use_vertex_ai: '${{ vars.GOOGLE_GENAI_USE_VERTEXAI }}'
upload_artifacts: '${{ vars.UPLOAD_ARTIFACTS }}'
settings: |-
{
"model": {
"maxSessionTurns": 25
},
"telemetry": {
"enabled": ${{ vars.GOOGLE_CLOUD_PROJECT != '' }},
"target": "gcp"
"enabled": true,
"target": "local",
"outfile": ".gemini/telemetry.log"
},
"mcpServers": {
"github": {
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/gemini-issue-fixer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ jobs:
google_api_key: '${{ secrets.GOOGLE_API_KEY }}'
use_gemini_code_assist: '${{ vars.GOOGLE_GENAI_USE_GCA }}'
use_vertex_ai: '${{ vars.GOOGLE_GENAI_USE_VERTEXAI }}'
upload_artifacts: '${{ vars.UPLOAD_ARTIFACTS }}'
settings: |-
{
"debug": ${{ fromJSON(env.DEBUG || env.ACTIONS_STEP_DEBUG || false) }},
Expand All @@ -85,8 +86,9 @@ jobs:
}
},
"telemetry": {
"enabled": ${{ vars.GOOGLE_CLOUD_PROJECT != '' }},
"target": "gcp"
"enabled": true,
"target": "local",
"outfile": ".gemini/telemetry.log"
}
}
prompt: '/gemini-issue-fixer'
6 changes: 4 additions & 2 deletions .github/workflows/gemini-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,14 +63,16 @@ jobs:
google_api_key: '${{ secrets.GOOGLE_API_KEY }}'
use_gemini_code_assist: '${{ vars.GOOGLE_GENAI_USE_GCA }}'
use_vertex_ai: '${{ vars.GOOGLE_GENAI_USE_VERTEXAI }}'
upload_artifacts: '${{ vars.UPLOAD_ARTIFACTS }}'
settings: |-
{
"model": {
"maxSessionTurns": 25
},
"telemetry": {
"enabled": ${{ vars.GOOGLE_CLOUD_PROJECT != '' }},
"target": "gcp"
"enabled": true,
"target": "local",
"outfile": ".gemini/telemetry.log"
},
"mcpServers": {
"github": {
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/gemini-scheduled-triage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,14 +103,16 @@ jobs:
google_api_key: '${{ secrets.GOOGLE_API_KEY }}'
use_gemini_code_assist: '${{ vars.GOOGLE_GENAI_USE_GCA }}'
use_vertex_ai: '${{ vars.GOOGLE_GENAI_USE_VERTEXAI }}'
upload_artifacts: '${{ vars.UPLOAD_ARTIFACTS }}'
settings: |-
{
"model": {
"maxSessionTurns": 25
},
"telemetry": {
"enabled": ${{ vars.GOOGLE_CLOUD_PROJECT != '' }},
"target": "gcp"
"enabled": true,
"target": "local",
"outfile": ".gemini/telemetry.log"
},
"tools": {
"core": [
Expand Down
6 changes: 4 additions & 2 deletions .github/workflows/gemini-triage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,16 @@ jobs:
google_api_key: '${{ secrets.GOOGLE_API_KEY }}'
use_gemini_code_assist: '${{ vars.GOOGLE_GENAI_USE_GCA }}'
use_vertex_ai: '${{ vars.GOOGLE_GENAI_USE_VERTEXAI }}'
upload_artifacts: '${{ vars.UPLOAD_ARTIFACTS }}'
settings: |-
{
"model": {
"maxSessionTurns": 25
},
"telemetry": {
"enabled": ${{ vars.GOOGLE_CLOUD_PROJECT != '' }},
"target": "gcp"
"enabled": true,
"target": "local",
"outfile": ".gemini/telemetry.log"
},
"tools": {
"core": [
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ go to the [Gemini Assistant workflow documentation](./examples/workflows/gemini-

- <a name="__input_extensions"></a><a href="#user-content-__input_extensions"><code>extensions</code></a>: _(Optional)_ A list of Gemini CLI extensions to install.

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


<!-- END_AUTOGEN_INPUTS -->

Expand Down
119 changes: 93 additions & 26 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ inputs:
extensions:
description: 'A list of Gemini CLI extensions to install.'
required: false
upload_artifacts:
description: 'Whether or not to upload artifacts to the github action.'
required: false
default: 'false'

outputs:
summary:
Expand Down Expand Up @@ -183,26 +187,6 @@ runs:
token_format: 'access_token'
access_token_scopes: 'https://www.googleapis.com/auth/cloud-platform,https://www.googleapis.com/auth/userinfo.email,https://www.googleapis.com/auth/userinfo.profile'

- name: 'Run Telemetry Collector for Google Cloud'
if: |-
${{ inputs.gcp_workload_identity_provider != '' }}
env:
OTLP_GOOGLE_CLOUD_PROJECT: '${{ inputs.gcp_project_id }}'
GITHUB_ACTION_PATH: '${{ github.action_path }}'
shell: 'bash'
run: |-
set -euo pipefail
mkdir -p .gemini/
sed "s/OTLP_GOOGLE_CLOUD_PROJECT/${OTLP_GOOGLE_CLOUD_PROJECT}/g" "${GITHUB_ACTION_PATH}/scripts/collector-gcp.yaml.template" > ".gemini/collector-gcp.yaml"

chmod 444 "$GOOGLE_APPLICATION_CREDENTIALS"
docker run -d --name gemini-telemetry-collector --network host \
-v "${GITHUB_WORKSPACE}:/github/workspace" \
-e "GOOGLE_APPLICATION_CREDENTIALS=${GOOGLE_APPLICATION_CREDENTIALS/$GITHUB_WORKSPACE//github/workspace}" \
-w "/github/workspace" \
otel/opentelemetry-collector-contrib:0.128.0 \
--config /github/workspace/.gemini/collector-gcp.yaml

- name: 'Install Gemini CLI'
id: 'install'
env:
Expand Down Expand Up @@ -274,22 +258,29 @@ runs:
fi
fi

GEMINI_RESPONSE="$(cat "${TEMP_STDOUT}")"
# Create the artifacts directory and copy full logs
mkdir -p gemini-artifacts
cp "${TEMP_STDOUT}" gemini-artifacts/stdout.log
cp "${TEMP_STDERR}" gemini-artifacts/stderr.log
if [[ -f .gemini/telemetry.log ]]; then
cp .gemini/telemetry.log gemini-artifacts/telemetry.log
else
# Create an empty file so the artifact upload doesn't fail if telemetry is missing
touch gemini-artifacts/telemetry.log
fi

# Set the captured response as a step output, supporting multiline
echo "gemini_response<<EOF" >> "${GITHUB_OUTPUT}"
echo "${GEMINI_RESPONSE}" >> "${GITHUB_OUTPUT}"
cat "${TEMP_STDOUT}" >> "${GITHUB_OUTPUT}"
echo "EOF" >> "${GITHUB_OUTPUT}"

GEMINI_ERRORS="$(cat "${TEMP_STDERR}")"

# Set the captured errors as a step output, supporting multiline
echo "gemini_errors<<EOF" >> "${GITHUB_OUTPUT}"
echo "${GEMINI_ERRORS}" >> "${GITHUB_OUTPUT}"
cat "${TEMP_STDERR}" >> "${GITHUB_OUTPUT}"
echo "EOF" >> "${GITHUB_OUTPUT}"

if [[ "${FAILED}" = true ]]; then
LAST_LINE="$(echo "${GEMINI_ERRORS}" | tail -n1)"
LAST_LINE="$(tail -n1 "${TEMP_STDERR}")"
echo "::error title=Gemini CLI execution failed::${LAST_LINE}"
echo "See logs for more details"
exit 1
Expand All @@ -307,6 +298,82 @@ runs:
PROMPT: '${{ inputs.prompt }}'
GEMINI_MODEL: '${{ inputs.gemini_model }}'

- name: 'Upload Gemini CLI outputs'
if: |-
${{ inputs.upload_artifacts }}
uses: 'actions/upload-artifact@v4' # ratchet:exclude
with:
name: 'gemini-output'
path: 'gemini-artifacts/'

- name: 'Upload Telemetry to Google Cloud'
if: |-
${{ inputs.gcp_workload_identity_provider != '' }}
shell: 'bash'
run: |-
set -euo pipefail

# If the telemetry log doesn't exist or is empty, do nothing.
if [[ ! -s ".gemini/telemetry.log" ]]; then
echo "No telemetry log found, skipping upload."
exit 0
fi

# Generate the real config file from the template
sed -e "s#OTLP_GOOGLE_CLOUD_PROJECT#${OTLP_GOOGLE_CLOUD_PROJECT}#g" \
-e "s#GITHUB_REPOSITORY_PLACEHOLDER#${GITHUB_REPOSITORY}#g" \
-e "s#GITHUB_RUN_ID_PLACEHOLDER#${GITHUB_RUN_ID}#g" \
"${GITHUB_ACTION_PATH}/scripts/collector-gcp.yaml.template" > ".gemini/collector-gcp.yaml"

# Ensure credentials file has the right permissions
chmod 444 "$GOOGLE_APPLICATION_CREDENTIALS"

# Run the collector in the background with a known name
docker run --rm --name gemini-telemetry-collector --network host \
-v "${GITHUB_WORKSPACE}:/github/workspace" \
-e "GOOGLE_APPLICATION_CREDENTIALS=${GOOGLE_APPLICATION_CREDENTIALS/$GITHUB_WORKSPACE//github/workspace}" \
-w "/github/workspace" \
otel/opentelemetry-collector-contrib:0.108.0 \
--config /github/workspace/.gemini/collector-gcp.yaml &

# Wait for the collector to start up
echo "Waiting for collector to initialize..."
sleep 10

# Monitor the queue until it's empty or we time out
echo "Monitoring exporter queue..."
ATTEMPTS=0
MAX_ATTEMPTS=12 # 12 * 5s = 60s timeout
while true; do
# Use -f to fail silently if the server isn't ready yet
# Filter out the prometheus help/type comments before grabbing the value
QUEUE_SIZE=$(curl -sf http://localhost:8888/metrics | grep otelcol_exporter_queue_size | grep -v '^#' | awk '{print $2}' || echo "-1")

if [ "$QUEUE_SIZE" == "0" ]; then
echo "Exporter queue is empty, all data processed."
break
fi

if [ "$ATTEMPTS" -ge "$MAX_ATTEMPTS" ]; then
echo "::warning::Timed out waiting for exporter queue to empty. Proceeding with shutdown."
break
fi

echo "Queue size: $QUEUE_SIZE, waiting..."
sleep 5
ATTEMPTS=$((ATTEMPTS + 1))
done

# Gracefully shut down the collector
echo "Stopping collector..."
docker stop gemini-telemetry-collector
echo "Collector stopped."
env:
OTLP_GOOGLE_CLOUD_PROJECT: '${{ inputs.gcp_project_id }}'
GITHUB_ACTION_PATH: '${{ github.action_path }}'
GITHUB_REPOSITORY: '${{ github.repository }}'
GITHUB_RUN_ID: '${{ github.run_id }}'

branding:
icon: 'terminal'
color: 'blue'
45 changes: 22 additions & 23 deletions scripts/collector-gcp.yaml.template
Original file line number Diff line number Diff line change
@@ -1,34 +1,33 @@
receivers:
otlp:
protocols:
grpc:
endpoint: 'localhost:4317'
filelog:
include: ['.gemini/telemetry.log']
start_at: 'beginning'

processors:
resource:
attributes:
- key: 'github.repository'
value: 'GITHUB_REPOSITORY_PLACEHOLDER'
action: 'upsert'
- key: 'github.run_id'
value: 'GITHUB_RUN_ID_PLACEHOLDER'
action: 'upsert'
batch:
timeout: '1s'
send_batch_size: 100
timeout: '10s'

exporters:
googlecloud:
project: 'OTLP_GOOGLE_CLOUD_PROJECT'
metric:
prefix: 'custom.googleapis.com/gemini_cli'
log:
default_log_name: 'gemini_cli'
default_log_name: 'gemini-cli'

service:
telemetry:
logs:
level: 'debug'
metrics:
level: 'none'
pipelines:
traces:
receivers: ['otlp']
processors: ['batch']
exporters: ['googlecloud']
metrics:
receivers: ['otlp']
processors: ['batch']
exporters: ['googlecloud']
logs:
receivers: ['otlp']
processors: ['batch']
receivers: ['filelog']
processors: ['batch', 'resource']
exporters: ['googlecloud']
telemetry:
metrics:
address: '0.0.0.0:8888'
Loading