Skip to content
Merged
188 changes: 188 additions & 0 deletions .github/workflows/gemini-review.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
name: '🔎 Gemini Review & Security Analysis'

on:
pull_request:
types:
- 'opened'
issue_comment:
types:
- 'created'

concurrency:
group: '${{ github.workflow }}-review-${{ github.event_name }}-${{ github.event.pull_request.number || github.event.issue.number }}'
cancel-in-progress: true

defaults:
run:
shell: 'bash'

jobs:
review:
if: |
(github.event_name == 'pull_request' && github.event.action == 'opened') ||
(github.event_name == 'issue_comment' && github.event.comment.body == '@gemini-cli /review')
runs-on: 'ubuntu-latest'
timeout-minutes: 15
permissions:
contents: 'read'
id-token: 'write'
issues: 'write'
pull-requests: 'write'
steps:
- name: 'Mint identity token'
id: 'mint_identity_token'
if: |-
${{ vars.APP_ID }}
uses: 'actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b' # ratchet:actions/create-github-app-token@v2
with:
app-id: '${{ vars.APP_ID }}'
private-key: '${{ secrets.APP_PRIVATE_KEY }}'
permission-contents: 'read'
permission-issues: 'write'
permission-pull-requests: 'write'

- name: 'Acknowledge request'
env:
GITHUB_TOKEN: '${{ steps.mint_identity_token.outputs.token || secrets.GITHUB_TOKEN || github.token }}'
ISSUE_NUMBER: '${{ github.event.pull_request.number || github.event.issue.number }}'
MESSAGE: |-
🤖 Hi @${{ github.actor }}, I've received your request, and I'm working on it now! You can track my progress [in the logs](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}) for more details.
REPOSITORY: '${{ github.repository }}'
run: |-
gh issue comment "${ISSUE_NUMBER}" \
--body "${MESSAGE}" \
--repo "${REPOSITORY}"

- name: 'Checkout repository'
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5

- name: 'Run Gemini pull request review'
uses: 'google-github-actions/run-gemini-cli@main' # ratchet:exclude
id: 'gemini_pr_review'
env:
GITHUB_TOKEN: '${{ steps.mint_identity_token.outputs.token || secrets.GITHUB_TOKEN || github.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 }}'
with:
gcp_location: '${{ vars.GOOGLE_CLOUD_LOCATION }}'
gcp_project_id: '${{ vars.GOOGLE_CLOUD_PROJECT }}'
gcp_service_account: '${{ vars.SERVICE_ACCOUNT_EMAIL }}'
gcp_workload_identity_provider: '${{ vars.GCP_WIF_PROVIDER }}'
gemini_api_key: '${{ secrets.GEMINI_API_KEY }}'
gemini_cli_version: '${{ vars.GEMINI_CLI_VERSION }}'
gemini_debug: '${{ fromJSON(vars.DEBUG || vars.ACTIONS_STEP_DEBUG || false) }}'
gemini_model: '${{ vars.GEMINI_MODEL }}'
google_api_key: '${{ secrets.GOOGLE_API_KEY }}'
use_gemini_code_assist: '${{ vars.GOOGLE_GENAI_USE_GCA }}'
use_vertex_ai: '${{ vars.GOOGLE_GENAI_USE_VERTEXAI }}'
settings: |-
{
"model": {
"maxSessionTurns": 25
},
"telemetry": {
"enabled": ${{ vars.GOOGLE_CLOUD_PROJECT != '' }},
"target": "gcp"
},
"mcpServers": {
"github": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server"
],
"includeTools": [
"add_comment_to_pending_review",
"create_pending_pull_request_review",
"pull_request_read",
"submit_pending_pull_request_review"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
}
},
"tools": {
"core": [
"run_shell_command(cat)",
"run_shell_command(echo)",
"run_shell_command(grep)",
"run_shell_command(head)",
"run_shell_command(tail)"
]
}
}
prompt: '/gemini-review'
- name: 'Run Gemini security analysis review'
uses: 'google-github-actions/run-gemini-cli@main' # ratchet:exclude
id: 'gemini_security_analysis'
env:
GITHUB_TOKEN: '${{ steps.mint_identity_token.outputs.token || secrets.GITHUB_TOKEN || github.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 }}'
with:
gcp_location: '${{ vars.GOOGLE_CLOUD_LOCATION }}'
gcp_project_id: '${{ vars.GOOGLE_CLOUD_PROJECT }}'
gcp_service_account: '${{ vars.SERVICE_ACCOUNT_EMAIL }}'
gcp_workload_identity_provider: '${{ vars.GCP_WIF_PROVIDER }}'
gemini_api_key: '${{ secrets.GEMINI_API_KEY }}'
gemini_cli_version: '${{ vars.GEMINI_CLI_VERSION }}'
gemini_debug: '${{ fromJSON(vars.DEBUG || vars.ACTIONS_STEP_DEBUG || false) }}'
gemini_model: '${{ vars.GEMINI_MODEL }}'
google_api_key: '${{ secrets.GOOGLE_API_KEY }}'
use_gemini_code_assist: '${{ vars.GOOGLE_GENAI_USE_GCA }}'
use_vertex_ai: '${{ vars.GOOGLE_GENAI_USE_VERTEXAI }}'
extensions: |
[
"https://github.com/gemini-cli-extensions/security.git"
]
settings: |-
{
"model": {
"maxSessionTurns": 100
},
"telemetry": {
"enabled": ${{ vars.GOOGLE_CLOUD_PROJECT != '' }},
"target": "gcp"
},
"mcpServers": {
"github": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server"
],
"includeTools": [
"add_comment_to_pending_review",
"create_pending_pull_request_review",
"pull_request_read",
"submit_pending_pull_request_review"
],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
}
},
"tools": {
"core": [
"run_shell_command(cat)",
"run_shell_command(echo)",
"run_shell_command(grep)",
"run_shell_command(head)",
"run_shell_command(tail)"
]
}
}
prompt: '/security:analyze-github-pr'
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.env

dist/
node_modules/
node_modules/
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,13 @@ By default, the `/security:analyze` command determines the scope of the analysis

## GitHub Integration

Coming soon!
Integrate the Gemini CLI Security Extension into your GitHub worklfow for analyzing incoming code can be done with the following:

* Base your workflow off of the [google-github-actions/run-gemini-cli GitHub Action](https://github.com/google-github-actions/run-gemini-cli)
* Ensure that the [gemini-cli-extensions/security](https://github.com/gemini-cli-extensions/security) extension is passed to the action for installation.
* Pass `/security:analyze-github-pr` as the prompt to invoke the Security Extension!

See this [Example Workflow](https://github.com/gemini-cli-extensions/security/blob/main/.github/workflows/github-review.yml)

## Benchmark

Expand Down
12 changes: 6 additions & 6 deletions commands/security/analyze-github-pr.toml
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,9 @@ You will now begin executing the plan. The following are your precise instructio
- Retrieve the GitHub repository name from the environment variable "${REPOSITORY}".
- Retrieve the GitHub pull request number from the environment variable "${PULL_REQUEST_NUMBER}".
- Retrieve the additional user instructions and context from the environment variable "${ADDITIONAL_CONTEXT}".
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to note here: This can be a surface for prompt injection attack, but since only maintainers are allowed to run this, this is not a problem at the moment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. This is copied from run-gemini-cli who should be notified of this too.

Another way for this extension to be useful being added other repo's like run-gemini-cli 😄

- Use `mcp__github__get_pull_request` to get the title, body, and metadata about the pull request.
- Use `mcp__github__get_pull_request_files` to get the list of files that were added, removed, and changed in the pull request.
- Use `mcp__github__get_pull_request_diff` to get the diff from the pull request. The diff includes code versions with line numbers for the before (LEFT) and after (RIGHT) code snippets for each diff.
- Use `pull_request_read.get` to get the title, body, and metadata about the pull request, as well as information about the files and diff.
- Use `pull_request_files.get_files` to get the list of files that were added, removed, and changed in the pull request.
- Use `pull_request_diff.get_diff` to get the diff from the pull request. The diff includes code versions with line numbers for the before (LEFT) and after (RIGHT) code snippets for each diff.

* Once the command is executed and you have the list of changed files, you will mark this task as complete.

Expand All @@ -129,9 +129,9 @@ After completing these two initial tasks, continue executing the dynamically gen

After your **Core Operational Loop** is completed, report the final report back to GitHub:

3.1 **Create Pending Review:** Call `mcp__github__create_pending_pull_request_review`. Ignore errors like "can only have one pending review per pull request" and proceed to the next step.
3.1 **Create Pending Review:** Call `create_pending_pull_request_review`. Ignore errors like "can only have one pending review per pull request" and proceed to the next step.

3.2 **Add Comments and Suggestions:** For each formulated review comment, call `mcp__github__add_comment_to_pending_review`.
3.2 **Add Comments and Suggestions:** For each formulated review comment, call `add_comment_to_pending_review`.

2a. When there is a code suggestion (preferred), structure the comment payload using this exact template:

Expand All @@ -149,7 +149,7 @@ After completing these two initial tasks, continue executing the dynamically gen
{{SEVERITY}} {{COMMENT_TEXT}}
</COMMENT>

3.3 **Submit Final Review:** Call `mcp__github__submit_pending_pull_request_review` with a summary comment. **DO NOT** approve the pull request. **DO NOT** request changes. The summary comment **MUST** use this exact markdown format:
3.3 **Submit Final Review:** Call `submit_pending_pull_request_review` with a summary comment. **DO NOT** approve the pull request. **DO NOT** request changes. The summary comment **MUST** use this exact markdown format:

<SUMMARY>
## 📋 Security Analysis Summary
Expand Down
Loading