@biggora/claude-plugins 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -4
- package/package.json +1 -1
- package/registry/registry.json +319 -244
- package/specs/coding.md +24 -0
- package/specs/pod.md +2 -0
- package/src/skills/captcha/README.md +221 -0
- package/src/skills/captcha/SKILL.md +355 -0
- package/src/skills/captcha/references/captcha-types.md +254 -0
- package/src/skills/captcha/references/services.md +172 -0
- package/src/skills/captcha/references/stealth.md +238 -0
- package/src/skills/captcha/scripts/solve_captcha.py +323 -0
- package/src/skills/captcha/scripts/solve_image_grid.py +350 -0
- package/src/skills/google-merchant-api/SKILL.md +581 -0
- package/src/skills/google-merchant-api/references/accounts.md +247 -0
- package/src/skills/google-merchant-api/references/content-api-legacy.md +216 -0
- package/src/skills/google-merchant-api/references/datasources.md +233 -0
- package/src/skills/google-merchant-api/references/inventories.md +201 -0
- package/src/skills/google-merchant-api/references/migration.md +267 -0
- package/src/skills/google-merchant-api/references/products.md +316 -0
- package/src/skills/google-merchant-api/references/promotions.md +201 -0
- package/src/skills/google-merchant-api/references/reports.md +240 -0
- package/src/skills/lv-aggregators-api/SKILL.md +113 -0
- package/src/skills/lv-aggregators-api/references/integration-guide.md +368 -0
- package/src/skills/lv-aggregators-api/references/kurpirkt.md +103 -0
- package/src/skills/lv-aggregators-api/references/salidzini.md +122 -0
- package/src/skills/tailwindcss-best-practices/SKILL.md +180 -0
- package/src/skills/tailwindcss-best-practices/references/best-practices-utility-patterns.md +87 -0
- package/src/skills/tailwindcss-best-practices/references/core-installation.md +109 -0
- package/src/skills/tailwindcss-best-practices/references/core-preflight.md +200 -0
- package/src/skills/tailwindcss-best-practices/references/core-responsive.md +163 -0
- package/src/skills/tailwindcss-best-practices/references/core-source-detection.md +114 -0
- package/src/skills/tailwindcss-best-practices/references/core-theme.md +108 -0
- package/src/skills/tailwindcss-best-practices/references/core-utility-classes.md +59 -0
- package/src/skills/tailwindcss-best-practices/references/core-variants.md +204 -0
- package/src/skills/tailwindcss-best-practices/references/effects-form-controls.md +76 -0
- package/src/skills/tailwindcss-best-practices/references/effects-mask.md +91 -0
- package/src/skills/tailwindcss-best-practices/references/effects-scroll-snap.md +59 -0
- package/src/skills/tailwindcss-best-practices/references/effects-text-shadow.md +78 -0
- package/src/skills/tailwindcss-best-practices/references/effects-transition-animation.md +80 -0
- package/src/skills/tailwindcss-best-practices/references/effects-visibility-interactivity.md +82 -0
- package/src/skills/tailwindcss-best-practices/references/features-content-detection.md +175 -0
- package/src/skills/tailwindcss-best-practices/references/features-custom-styles.md +203 -0
- package/src/skills/tailwindcss-best-practices/references/features-dark-mode.md +137 -0
- package/src/skills/tailwindcss-best-practices/references/features-functions-directives.md +241 -0
- package/src/skills/tailwindcss-best-practices/references/features-upgrade.md +160 -0
- package/src/skills/tailwindcss-best-practices/references/layout-aspect-ratio.md +39 -0
- package/src/skills/tailwindcss-best-practices/references/layout-columns.md +80 -0
- package/src/skills/tailwindcss-best-practices/references/layout-display.md +110 -0
- package/src/skills/tailwindcss-best-practices/references/layout-flexbox.md +112 -0
- package/src/skills/tailwindcss-best-practices/references/layout-grid.md +87 -0
- package/src/skills/tailwindcss-best-practices/references/layout-height.md +97 -0
- package/src/skills/tailwindcss-best-practices/references/layout-inset.md +103 -0
- package/src/skills/tailwindcss-best-practices/references/layout-logical-properties.md +92 -0
- package/src/skills/tailwindcss-best-practices/references/layout-margin.md +126 -0
- package/src/skills/tailwindcss-best-practices/references/layout-min-max-sizing.md +63 -0
- package/src/skills/tailwindcss-best-practices/references/layout-object-fit-position.md +64 -0
- package/src/skills/tailwindcss-best-practices/references/layout-overflow.md +57 -0
- package/src/skills/tailwindcss-best-practices/references/layout-padding.md +77 -0
- package/src/skills/tailwindcss-best-practices/references/layout-position.md +85 -0
- package/src/skills/tailwindcss-best-practices/references/layout-tables.md +67 -0
- package/src/skills/tailwindcss-best-practices/references/layout-width.md +102 -0
- package/src/skills/tailwindcss-best-practices/references/transform-base.md +68 -0
- package/src/skills/tailwindcss-best-practices/references/transform-rotate.md +70 -0
- package/src/skills/tailwindcss-best-practices/references/transform-scale.md +83 -0
- package/src/skills/tailwindcss-best-practices/references/transform-skew.md +62 -0
- package/src/skills/tailwindcss-best-practices/references/transform-translate.md +77 -0
- package/src/skills/tailwindcss-best-practices/references/typography-font-text.md +142 -0
- package/src/skills/tailwindcss-best-practices/references/typography-list-style.md +65 -0
- package/src/skills/tailwindcss-best-practices/references/typography-text-align.md +60 -0
- package/src/skills/tailwindcss-best-practices/references/visual-background.md +76 -0
- package/src/skills/tailwindcss-best-practices/references/visual-border.md +108 -0
- package/src/skills/tailwindcss-best-practices/references/visual-effects.md +111 -0
- package/src/skills/tailwindcss-best-practices/references/visual-svg.md +82 -0
- package/src/skills/test-mobile-app/SKILL.md +11 -6
- package/src/skills/test-mobile-app/scripts/analyze_apk.py +15 -4
- package/src/skills/test-mobile-app/scripts/check_environment.py +5 -5
- package/src/skills/test-mobile-app/scripts/run_tests.py +1 -1
- package/src/skills/test-web-ui/SKILL.md +264 -84
- package/src/skills/test-web-ui/scripts/discover.py +25 -12
- package/src/skills/test-web-ui/scripts/run_tests.py +3 -2
- package/src/skills/vite-best-practices/SKILL.md +115 -0
- package/src/skills/vite-best-practices/references/build-and-ssr.md +255 -0
- package/src/skills/vite-best-practices/references/core-config.md +231 -0
- package/src/skills/vite-best-practices/references/core-features.md +222 -0
- package/src/skills/vite-best-practices/references/core-plugin-api.md +294 -0
- package/src/skills/vite-best-practices/references/environment-api.md +108 -0
- package/src/skills/vite-best-practices/references/rolldown-migration.md +242 -0
- package/codex-cli-workspace/iteration-1/benchmark.json +0 -122
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/eval_metadata.json +0 -13
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/with_skill/grading.json +0 -52
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/with_skill/outputs/response.md +0 -163
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/with_skill/timing.json +0 -5
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/without_skill/grading.json +0 -58
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/without_skill/outputs/response.md +0 -151
- package/codex-cli-workspace/iteration-1/eval-1-ci-integration/without_skill/timing.json +0 -5
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/eval_metadata.json +0 -13
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/grading.json +0 -52
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/outputs/response.md +0 -86
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/timing.json +0 -5
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/grading.json +0 -58
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/outputs/response.md +0 -164
- package/codex-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/timing.json +0 -5
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/eval_metadata.json +0 -13
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/with_skill/grading.json +0 -52
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/with_skill/outputs/response.md +0 -130
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/with_skill/timing.json +0 -5
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/without_skill/grading.json +0 -64
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/without_skill/outputs/response.md +0 -209
- package/codex-cli-workspace/iteration-1/eval-3-profiles-troubleshooting/without_skill/timing.json +0 -5
- package/codex-cli-workspace/iteration-1/review.html +0 -1325
- package/gemini-cli-workspace/iteration-1/benchmark.json +0 -86
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/eval_metadata.json +0 -37
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/with_skill/grading.json +0 -37
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/with_skill/outputs/response.md +0 -401
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/with_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/without_skill/grading.json +0 -37
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/without_skill/outputs/response.md +0 -405
- package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/without_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/eval_metadata.json +0 -37
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/grading.json +0 -37
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/outputs/response.md +0 -212
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/with_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/grading.json +0 -37
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/outputs/response.md +0 -427
- package/gemini-cli-workspace/iteration-1/eval-2-mcp-server-config/without_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/eval_metadata.json +0 -32
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/with_skill/grading.json +0 -32
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/with_skill/outputs/response.md +0 -171
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/with_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/without_skill/grading.json +0 -32
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/without_skill/outputs/response.md +0 -199
- package/gemini-cli-workspace/iteration-1/eval-3-custom-slash-command/without_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-1/review.html +0 -1325
- package/gemini-cli-workspace/iteration-2/benchmark.json +0 -173
- package/gemini-cli-workspace/iteration-2/benchmark.md +0 -28
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/eval_metadata.json +0 -37
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/with_skill/grading.json +0 -37
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/with_skill/outputs/response.md +0 -195
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/with_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/without_skill/grading.json +0 -37
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/without_skill/outputs/response.md +0 -377
- package/gemini-cli-workspace/iteration-2/eval-1-cicd-setup/without_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/eval_metadata.json +0 -37
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/with_skill/grading.json +0 -37
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/with_skill/outputs/response.md +0 -127
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/with_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/without_skill/grading.json +0 -37
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/without_skill/outputs/response.md +0 -164
- package/gemini-cli-workspace/iteration-2/eval-2-mcp-server-config/without_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/eval_metadata.json +0 -32
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/with_skill/grading.json +0 -32
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/with_skill/outputs/response.md +0 -91
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/with_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/without_skill/grading.json +0 -32
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/without_skill/outputs/response.md +0 -112
- package/gemini-cli-workspace/iteration-2/eval-3-custom-slash-command/without_skill/timing.json +0 -5
- package/gemini-cli-workspace/iteration-2/eval-viewer.html +0 -1325
- package/screen-recording-workspace/evals.json +0 -41
- package/screen-recording-workspace/iteration-1/benchmark.json +0 -102
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/eval_metadata.json +0 -31
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/with_skill/grading.json +0 -11
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/with_skill/outputs/demo.mp4 +0 -0
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/with_skill/timing.json +0 -5
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/without_skill/grading.json +0 -11
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/without_skill/outputs/demo.mp4 +0 -0
- package/screen-recording-workspace/iteration-1/eval-0-fullscreen/without_skill/timing.json +0 -5
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/eval_metadata.json +0 -31
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/with_skill/grading.json +0 -11
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/with_skill/outputs/region_capture.mp4 +0 -0
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/with_skill/timing.json +0 -5
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/without_skill/grading.json +0 -11
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/without_skill/outputs/region_capture.mp4 +0 -0
- package/screen-recording-workspace/iteration-1/eval-1-region-audio/without_skill/timing.json +0 -5
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/eval_metadata.json +0 -31
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/with_skill/grading.json +0 -11
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/with_skill/outputs/fallback_recording.mp4 +0 -0
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/with_skill/timing.json +0 -5
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/without_skill/grading.json +0 -11
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/without_skill/outputs/fallback_recording.mp4 +0 -0
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/without_skill/outputs/record_screen.py +0 -67
- package/screen-recording-workspace/iteration-1/eval-2-python-fallback/without_skill/timing.json +0 -5
- package/screen-recording-workspace/iteration-1/review.html +0 -1325
- package/src/skills/codex-cli/evals/evals.json +0 -47
- package/src/skills/gemini-cli/evals/evals.json +0 -46
- package/src/skills/tm-search/evals/evals.json +0 -23
package/gemini-cli-workspace/iteration-1/eval-1-cicd-setup/without_skill/outputs/response.md
DELETED
|
@@ -1,405 +0,0 @@
|
|
|
1
|
-
# Setting Up Gemini CLI for Automated PR Reviews in GitHub Actions
|
|
2
|
-
|
|
3
|
-
This guide covers how to configure Gemini CLI in a GitHub Actions CI/CD pipeline to automatically review pull requests, using an API key from GitHub Secrets and structured JSON output for parsing.
|
|
4
|
-
|
|
5
|
-
## Prerequisites
|
|
6
|
-
|
|
7
|
-
- A Google AI API key (from [Google AI Studio](https://aistudio.google.com/apikey))
|
|
8
|
-
- The API key stored as a GitHub repository secret (e.g., `GEMINI_API_KEY`)
|
|
9
|
-
- A GitHub repository with pull request workflows
|
|
10
|
-
|
|
11
|
-
## Step 1: Store Your API Key in GitHub Secrets
|
|
12
|
-
|
|
13
|
-
1. Go to your repository on GitHub.
|
|
14
|
-
2. Navigate to **Settings > Secrets and variables > Actions**.
|
|
15
|
-
3. Click **New repository secret**.
|
|
16
|
-
4. Name it `GEMINI_API_KEY` and paste your API key as the value.
|
|
17
|
-
|
|
18
|
-
## Step 2: Create the GitHub Actions Workflow
|
|
19
|
-
|
|
20
|
-
Create a file at `.github/workflows/gemini-pr-review.yml`:
|
|
21
|
-
|
|
22
|
-
```yaml
|
|
23
|
-
name: Gemini PR Review
|
|
24
|
-
|
|
25
|
-
on:
|
|
26
|
-
pull_request:
|
|
27
|
-
types: [opened, synchronize, reopened]
|
|
28
|
-
|
|
29
|
-
permissions:
|
|
30
|
-
contents: read
|
|
31
|
-
pull-requests: write
|
|
32
|
-
|
|
33
|
-
jobs:
|
|
34
|
-
review:
|
|
35
|
-
runs-on: ubuntu-latest
|
|
36
|
-
steps:
|
|
37
|
-
- name: Checkout repository
|
|
38
|
-
uses: actions/checkout@v4
|
|
39
|
-
with:
|
|
40
|
-
fetch-depth: 0
|
|
41
|
-
|
|
42
|
-
- name: Set up Node.js
|
|
43
|
-
uses: actions/setup-node@v4
|
|
44
|
-
with:
|
|
45
|
-
node-version: '20'
|
|
46
|
-
|
|
47
|
-
- name: Install Gemini CLI
|
|
48
|
-
run: npm install -g @anthropic-ai/gemini-cli || npm install -g gemini-cli
|
|
49
|
-
|
|
50
|
-
- name: Get PR diff
|
|
51
|
-
id: diff
|
|
52
|
-
run: |
|
|
53
|
-
git fetch origin ${{ github.base_ref }}
|
|
54
|
-
DIFF=$(git diff origin/${{ github.base_ref }}...HEAD)
|
|
55
|
-
# Write diff to a file to avoid shell escaping issues
|
|
56
|
-
echo "$DIFF" > /tmp/pr_diff.txt
|
|
57
|
-
|
|
58
|
-
- name: Get changed files list
|
|
59
|
-
id: files
|
|
60
|
-
run: |
|
|
61
|
-
git fetch origin ${{ github.base_ref }}
|
|
62
|
-
FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
|
|
63
|
-
echo "$FILES" > /tmp/changed_files.txt
|
|
64
|
-
|
|
65
|
-
- name: Run Gemini CLI review
|
|
66
|
-
id: gemini-review
|
|
67
|
-
env:
|
|
68
|
-
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
|
|
69
|
-
run: |
|
|
70
|
-
DIFF=$(cat /tmp/pr_diff.txt)
|
|
71
|
-
FILES=$(cat /tmp/changed_files.txt)
|
|
72
|
-
|
|
73
|
-
PROMPT=$(cat <<'PROMPT_EOF'
|
|
74
|
-
You are a senior code reviewer. Analyze the following pull request diff and provide a structured review.
|
|
75
|
-
|
|
76
|
-
Changed files:
|
|
77
|
-
FILE_LIST_PLACEHOLDER
|
|
78
|
-
|
|
79
|
-
Diff:
|
|
80
|
-
DIFF_PLACEHOLDER
|
|
81
|
-
|
|
82
|
-
Respond ONLY with valid JSON in this exact format (no markdown fencing, no extra text):
|
|
83
|
-
{
|
|
84
|
-
"summary": "Brief summary of the changes",
|
|
85
|
-
"risk_level": "low|medium|high",
|
|
86
|
-
"issues": [
|
|
87
|
-
{
|
|
88
|
-
"file": "path/to/file",
|
|
89
|
-
"line": 42,
|
|
90
|
-
"severity": "error|warning|suggestion",
|
|
91
|
-
"message": "Description of the issue",
|
|
92
|
-
"suggestion": "How to fix it"
|
|
93
|
-
}
|
|
94
|
-
],
|
|
95
|
-
"positive_aspects": ["List of things done well"],
|
|
96
|
-
"approval_recommendation": "approve|request_changes|comment"
|
|
97
|
-
}
|
|
98
|
-
PROMPT_EOF
|
|
99
|
-
)
|
|
100
|
-
|
|
101
|
-
# Replace placeholders
|
|
102
|
-
PROMPT="${PROMPT/FILE_LIST_PLACEHOLDER/$FILES}"
|
|
103
|
-
PROMPT="${PROMPT/DIFF_PLACEHOLDER/$DIFF}"
|
|
104
|
-
|
|
105
|
-
# Run Gemini CLI with the prompt
|
|
106
|
-
# Using the --json flag if available, or parsing output directly
|
|
107
|
-
RESPONSE=$(echo "$PROMPT" | gemini \
|
|
108
|
-
--model gemini-2.0-flash \
|
|
109
|
-
--api-key "$GEMINI_API_KEY" \
|
|
110
|
-
2>/dev/null) || true
|
|
111
|
-
|
|
112
|
-
# If gemini CLI is not available, fall back to direct API call
|
|
113
|
-
if [ -z "$RESPONSE" ]; then
|
|
114
|
-
RESPONSE=$(curl -s "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_API_KEY}" \
|
|
115
|
-
-H 'Content-Type: application/json' \
|
|
116
|
-
-d "$(jq -n --arg prompt "$PROMPT" '{
|
|
117
|
-
"contents": [{"parts": [{"text": $prompt}]}],
|
|
118
|
-
"generationConfig": {
|
|
119
|
-
"responseMimeType": "application/json",
|
|
120
|
-
"temperature": 0.2
|
|
121
|
-
}
|
|
122
|
-
}')" | jq -r '.candidates[0].content.parts[0].text')
|
|
123
|
-
fi
|
|
124
|
-
|
|
125
|
-
echo "$RESPONSE" > /tmp/review_result.json
|
|
126
|
-
|
|
127
|
-
# Validate JSON
|
|
128
|
-
if jq empty /tmp/review_result.json 2>/dev/null; then
|
|
129
|
-
echo "valid_json=true" >> $GITHUB_OUTPUT
|
|
130
|
-
else
|
|
131
|
-
echo "valid_json=false" >> $GITHUB_OUTPUT
|
|
132
|
-
echo "Raw response was not valid JSON, attempting extraction..."
|
|
133
|
-
# Try to extract JSON from markdown fenced blocks
|
|
134
|
-
sed -n '/^```json/,/^```$/p' /tmp/review_result.json | sed '1d;$d' > /tmp/review_cleaned.json
|
|
135
|
-
if jq empty /tmp/review_cleaned.json 2>/dev/null; then
|
|
136
|
-
mv /tmp/review_cleaned.json /tmp/review_result.json
|
|
137
|
-
echo "valid_json=true" >> $GITHUB_OUTPUT
|
|
138
|
-
fi
|
|
139
|
-
fi
|
|
140
|
-
|
|
141
|
-
- name: Parse and post review
|
|
142
|
-
if: success()
|
|
143
|
-
env:
|
|
144
|
-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
145
|
-
run: |
|
|
146
|
-
REVIEW_FILE="/tmp/review_result.json"
|
|
147
|
-
|
|
148
|
-
if ! jq empty "$REVIEW_FILE" 2>/dev/null; then
|
|
149
|
-
echo "Failed to get valid JSON review. Posting raw output as comment."
|
|
150
|
-
gh pr comment ${{ github.event.pull_request.number }} \
|
|
151
|
-
--body "## Gemini Review
|
|
152
|
-
|
|
153
|
-
> Could not parse structured output. Raw response attached.
|
|
154
|
-
|
|
155
|
-
\`\`\`
|
|
156
|
-
$(cat "$REVIEW_FILE")
|
|
157
|
-
\`\`\`"
|
|
158
|
-
exit 0
|
|
159
|
-
fi
|
|
160
|
-
|
|
161
|
-
# Extract fields from JSON
|
|
162
|
-
SUMMARY=$(jq -r '.summary' "$REVIEW_FILE")
|
|
163
|
-
RISK=$(jq -r '.risk_level' "$REVIEW_FILE")
|
|
164
|
-
APPROVAL=$(jq -r '.approval_recommendation' "$REVIEW_FILE")
|
|
165
|
-
POSITIVES=$(jq -r '.positive_aspects // [] | map("- " + .) | join("\n")' "$REVIEW_FILE")
|
|
166
|
-
ISSUE_COUNT=$(jq -r '.issues | length' "$REVIEW_FILE")
|
|
167
|
-
|
|
168
|
-
# Build issue table
|
|
169
|
-
ISSUES_MD=""
|
|
170
|
-
if [ "$ISSUE_COUNT" -gt 0 ]; then
|
|
171
|
-
ISSUES_MD="### Issues Found ($ISSUE_COUNT)
|
|
172
|
-
|
|
173
|
-
| Severity | File | Line | Message | Suggestion |
|
|
174
|
-
|----------|------|------|---------|------------|
|
|
175
|
-
"
|
|
176
|
-
ISSUES_MD+=$(jq -r '.issues[] | "| \(.severity) | `\(.file)` | \(.line) | \(.message) | \(.suggestion) |"' "$REVIEW_FILE")
|
|
177
|
-
else
|
|
178
|
-
ISSUES_MD="### No issues found"
|
|
179
|
-
fi
|
|
180
|
-
|
|
181
|
-
# Build risk badge
|
|
182
|
-
case "$RISK" in
|
|
183
|
-
low) RISK_BADGE="" ;;
|
|
184
|
-
medium) RISK_BADGE="" ;;
|
|
185
|
-
high) RISK_BADGE="" ;;
|
|
186
|
-
*) RISK_BADGE="Risk: $RISK" ;;
|
|
187
|
-
esac
|
|
188
|
-
|
|
189
|
-
# Compose comment
|
|
190
|
-
COMMENT=$(cat <<EOF
|
|
191
|
-
## Gemini Automated PR Review
|
|
192
|
-
|
|
193
|
-
$RISK_BADGE
|
|
194
|
-
|
|
195
|
-
### Summary
|
|
196
|
-
$SUMMARY
|
|
197
|
-
|
|
198
|
-
$ISSUES_MD
|
|
199
|
-
|
|
200
|
-
### Positive Aspects
|
|
201
|
-
$POSITIVES
|
|
202
|
-
|
|
203
|
-
---
|
|
204
|
-
**Recommendation:** \`$APPROVAL\`
|
|
205
|
-
EOF
|
|
206
|
-
)
|
|
207
|
-
|
|
208
|
-
# Post comment to PR
|
|
209
|
-
gh pr comment ${{ github.event.pull_request.number }} --body "$COMMENT"
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
## Step 3: Direct API Approach with Structured JSON Output (Recommended)
|
|
213
|
-
|
|
214
|
-
If the Gemini CLI does not reliably produce JSON, use the Gemini REST API directly with `responseMimeType` set to `application/json`. This forces the model to return valid JSON. Here is a standalone workflow that uses `curl` and `jq`:
|
|
215
|
-
|
|
216
|
-
```yaml
|
|
217
|
-
name: Gemini PR Review (API Direct)
|
|
218
|
-
|
|
219
|
-
on:
|
|
220
|
-
pull_request:
|
|
221
|
-
types: [opened, synchronize, reopened]
|
|
222
|
-
|
|
223
|
-
permissions:
|
|
224
|
-
contents: read
|
|
225
|
-
pull-requests: write
|
|
226
|
-
|
|
227
|
-
jobs:
|
|
228
|
-
review:
|
|
229
|
-
runs-on: ubuntu-latest
|
|
230
|
-
steps:
|
|
231
|
-
- name: Checkout
|
|
232
|
-
uses: actions/checkout@v4
|
|
233
|
-
with:
|
|
234
|
-
fetch-depth: 0
|
|
235
|
-
|
|
236
|
-
- name: Generate review via Gemini API
|
|
237
|
-
id: review
|
|
238
|
-
env:
|
|
239
|
-
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
|
|
240
|
-
run: |
|
|
241
|
-
git fetch origin ${{ github.base_ref }}
|
|
242
|
-
DIFF=$(git diff origin/${{ github.base_ref }}...HEAD | head -c 30000)
|
|
243
|
-
FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD)
|
|
244
|
-
|
|
245
|
-
# Build the prompt
|
|
246
|
-
PROMPT="You are a code reviewer. Review this PR diff. Changed files: ${FILES}. Diff: ${DIFF}. Return a JSON object with keys: summary (string), risk_level (low/medium/high), issues (array of {file, line, severity, message, suggestion}), positive_aspects (array of strings), approval_recommendation (approve/request_changes/comment)."
|
|
247
|
-
|
|
248
|
-
# Call Gemini API with structured output
|
|
249
|
-
RESPONSE=$(curl -sf \
|
|
250
|
-
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_API_KEY}" \
|
|
251
|
-
-H 'Content-Type: application/json' \
|
|
252
|
-
-d "$(jq -n --arg prompt "$PROMPT" '{
|
|
253
|
-
contents: [{parts: [{text: $prompt}]}],
|
|
254
|
-
generationConfig: {
|
|
255
|
-
responseMimeType: "application/json",
|
|
256
|
-
responseSchema: {
|
|
257
|
-
type: "object",
|
|
258
|
-
properties: {
|
|
259
|
-
summary: {type: "string"},
|
|
260
|
-
risk_level: {type: "string", enum: ["low", "medium", "high"]},
|
|
261
|
-
issues: {
|
|
262
|
-
type: "array",
|
|
263
|
-
items: {
|
|
264
|
-
type: "object",
|
|
265
|
-
properties: {
|
|
266
|
-
file: {type: "string"},
|
|
267
|
-
line: {type: "integer"},
|
|
268
|
-
severity: {type: "string", enum: ["error", "warning", "suggestion"]},
|
|
269
|
-
message: {type: "string"},
|
|
270
|
-
suggestion: {type: "string"}
|
|
271
|
-
},
|
|
272
|
-
required: ["file", "severity", "message"]
|
|
273
|
-
}
|
|
274
|
-
},
|
|
275
|
-
positive_aspects: {type: "array", items: {type: "string"}},
|
|
276
|
-
approval_recommendation: {type: "string", enum: ["approve", "request_changes", "comment"]}
|
|
277
|
-
},
|
|
278
|
-
required: ["summary", "risk_level", "issues", "approval_recommendation"]
|
|
279
|
-
},
|
|
280
|
-
temperature: 0.2
|
|
281
|
-
}
|
|
282
|
-
}')")
|
|
283
|
-
|
|
284
|
-
# Extract the text content from the API response
|
|
285
|
-
REVIEW=$(echo "$RESPONSE" | jq -r '.candidates[0].content.parts[0].text')
|
|
286
|
-
echo "$REVIEW" > /tmp/review.json
|
|
287
|
-
|
|
288
|
-
# Validate
|
|
289
|
-
jq empty /tmp/review.json
|
|
290
|
-
|
|
291
|
-
- name: Post review comment
|
|
292
|
-
env:
|
|
293
|
-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
294
|
-
run: |
|
|
295
|
-
REVIEW_FILE="/tmp/review.json"
|
|
296
|
-
|
|
297
|
-
SUMMARY=$(jq -r '.summary' "$REVIEW_FILE")
|
|
298
|
-
RISK=$(jq -r '.risk_level' "$REVIEW_FILE")
|
|
299
|
-
APPROVAL=$(jq -r '.approval_recommendation' "$REVIEW_FILE")
|
|
300
|
-
|
|
301
|
-
# Format issues as markdown
|
|
302
|
-
ISSUES=$(jq -r '
|
|
303
|
-
if (.issues | length) > 0 then
|
|
304
|
-
"| Severity | File | Line | Issue | Fix |\n|---|---|---|---|---|\n" +
|
|
305
|
-
(.issues[] | "| \(.severity) | `\(.file)` | \(.line // "N/A") | \(.message) | \(.suggestion // "N/A") |")
|
|
306
|
-
else
|
|
307
|
-
"_No issues found._"
|
|
308
|
-
end
|
|
309
|
-
' "$REVIEW_FILE")
|
|
310
|
-
|
|
311
|
-
POSITIVES=$(jq -r '(.positive_aspects // []) | map("- " + .) | join("\n")' "$REVIEW_FILE")
|
|
312
|
-
|
|
313
|
-
BODY=$(cat <<EOF
|
|
314
|
-
## Automated PR Review (Gemini)
|
|
315
|
-
|
|
316
|
-
**Risk Level:** \`${RISK}\` | **Recommendation:** \`${APPROVAL}\`
|
|
317
|
-
|
|
318
|
-
### Summary
|
|
319
|
-
${SUMMARY}
|
|
320
|
-
|
|
321
|
-
### Issues
|
|
322
|
-
${ISSUES}
|
|
323
|
-
|
|
324
|
-
### What looks good
|
|
325
|
-
${POSITIVES}
|
|
326
|
-
EOF
|
|
327
|
-
)
|
|
328
|
-
|
|
329
|
-
gh pr comment "${{ github.event.pull_request.number }}" --body "$BODY"
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
## Step 4: Using Gemini CLI with `--json` Flag (If Supported)
|
|
333
|
-
|
|
334
|
-
Some versions of the Gemini CLI support a `--json` output flag. If your version does, the invocation simplifies to:
|
|
335
|
-
|
|
336
|
-
```bash
|
|
337
|
-
gemini --model gemini-2.0-flash \
|
|
338
|
-
--api-key "$GEMINI_API_KEY" \
|
|
339
|
-
--json \
|
|
340
|
-
--prompt "Review this code diff and return structured JSON: $DIFF"
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
Check your installed version's help output (`gemini --help`) to confirm available flags.
|
|
344
|
-
|
|
345
|
-
## Step 5: Parsing the JSON Output in Downstream Steps
|
|
346
|
-
|
|
347
|
-
Once you have valid JSON in a file, you can use it in subsequent pipeline steps:
|
|
348
|
-
|
|
349
|
-
```yaml
|
|
350
|
-
- name: Fail on high-risk reviews
|
|
351
|
-
run: |
|
|
352
|
-
RISK=$(jq -r '.risk_level' /tmp/review.json)
|
|
353
|
-
ERRORS=$(jq '[.issues[] | select(.severity == "error")] | length' /tmp/review.json)
|
|
354
|
-
|
|
355
|
-
echo "Risk level: $RISK"
|
|
356
|
-
echo "Error count: $ERRORS"
|
|
357
|
-
|
|
358
|
-
if [ "$RISK" = "high" ] || [ "$ERRORS" -gt 0 ]; then
|
|
359
|
-
echo "::error::PR review found high risk or errors. Please address the issues."
|
|
360
|
-
exit 1
|
|
361
|
-
fi
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
You can also use it in a matrix strategy or pass data between jobs:
|
|
365
|
-
|
|
366
|
-
```yaml
|
|
367
|
-
- name: Export review data
|
|
368
|
-
id: export
|
|
369
|
-
run: |
|
|
370
|
-
echo "risk=$(jq -r '.risk_level' /tmp/review.json)" >> $GITHUB_OUTPUT
|
|
371
|
-
echo "approval=$(jq -r '.approval_recommendation' /tmp/review.json)" >> $GITHUB_OUTPUT
|
|
372
|
-
echo "issue_count=$(jq '.issues | length' /tmp/review.json)" >> $GITHUB_OUTPUT
|
|
373
|
-
```
|
|
374
|
-
|
|
375
|
-
Then reference in later steps or jobs:
|
|
376
|
-
|
|
377
|
-
```yaml
|
|
378
|
-
- name: Auto-approve if clean
|
|
379
|
-
if: steps.export.outputs.approval == 'approve' && steps.export.outputs.issue_count == '0'
|
|
380
|
-
env:
|
|
381
|
-
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
382
|
-
run: |
|
|
383
|
-
gh pr review "${{ github.event.pull_request.number }}" --approve --body "Automated review passed with no issues."
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
## Key Points
|
|
387
|
-
|
|
388
|
-
1. **`responseMimeType: "application/json"`** in the Gemini API `generationConfig` forces the model to return valid JSON. This is the most reliable way to get structured output.
|
|
389
|
-
|
|
390
|
-
2. **`responseSchema`** lets you define the exact JSON schema you expect. The model will conform to it. This eliminates the need for post-processing or regex extraction.
|
|
391
|
-
|
|
392
|
-
3. **Diff size limits**: Git diffs can be very large. Truncate them (e.g., `head -c 30000`) to stay within token limits. For large PRs, consider reviewing changed files individually.
|
|
393
|
-
|
|
394
|
-
4. **Error handling**: Always validate the JSON output with `jq empty` before trying to parse it. Have a fallback path that posts raw output as a comment.
|
|
395
|
-
|
|
396
|
-
5. **Rate limits**: The Gemini API has rate limits. For high-traffic repos, add retry logic or use the paid tier.
|
|
397
|
-
|
|
398
|
-
6. **Security**: The `GEMINI_API_KEY` secret is never exposed in logs because GitHub Actions automatically masks secrets in output. The `GITHUB_TOKEN` is provided automatically by Actions with the permissions declared in the workflow.
|
|
399
|
-
|
|
400
|
-
## Troubleshooting
|
|
401
|
-
|
|
402
|
-
- **"jq: parse error"**: The model returned non-JSON text. Use `responseMimeType: "application/json"` to fix this.
|
|
403
|
-
- **Empty response**: Check that `GEMINI_API_KEY` is set correctly in secrets and that the model name is valid.
|
|
404
|
-
- **Diff too large**: Truncate the diff or split the review across multiple API calls, one per file.
|
|
405
|
-
- **Permission denied on PR comment**: Ensure `permissions: pull-requests: write` is set in the workflow.
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"eval_id": 2,
|
|
3
|
-
"eval_name": "mcp-server-config",
|
|
4
|
-
"prompt": "I need to connect a custom MCP server I built in Python to gemini cli. The server needs an API key from my environment. Also I want to restrict which tools it can expose. How do I configure this?",
|
|
5
|
-
"assertions": [
|
|
6
|
-
{
|
|
7
|
-
"id": "correct-settings-location",
|
|
8
|
-
"text": "Points to ~/.gemini/settings.json or project-level settings.json",
|
|
9
|
-
"type": "content_check"
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
"id": "shows-mcp-config-structure",
|
|
13
|
-
"text": "Shows mcpServers config with command, args fields",
|
|
14
|
-
"type": "content_check"
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
"id": "env-var-dollar-pattern",
|
|
18
|
-
"text": "Shows $VAR pattern for environment variable references in env field",
|
|
19
|
-
"type": "content_check"
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
"id": "tool-filtering",
|
|
23
|
-
"text": "Explains includeTools and/or excludeTools for restricting exposed tools",
|
|
24
|
-
"type": "content_check"
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"id": "security-note",
|
|
28
|
-
"text": "Mentions security considerations (trust field, not hardcoding keys, etc.)",
|
|
29
|
-
"type": "content_check"
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
"id": "python-command-correct",
|
|
33
|
-
"text": "Uses correct Python command (python/python3) in the command field for the MCP server",
|
|
34
|
-
"type": "accuracy_check"
|
|
35
|
-
}
|
|
36
|
-
]
|
|
37
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"eval_id": 2,
|
|
3
|
-
"eval_name": "mcp-server-config",
|
|
4
|
-
"configuration": "with_skill",
|
|
5
|
-
"expectations": [
|
|
6
|
-
{
|
|
7
|
-
"text": "Points to ~/.gemini/settings.json or project-level settings.json",
|
|
8
|
-
"passed": true,
|
|
9
|
-
"evidence": "Mentions both `~/.gemini/settings.json` (global) and `<project>/.gemini/settings.json` (project-scoped)"
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
"text": "Shows mcpServers config with command, args fields",
|
|
13
|
-
"passed": true,
|
|
14
|
-
"evidence": "Complete mcpServers config with command, args, cwd, env, timeout, trust, includeTools fields"
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
"text": "Shows $VAR pattern for environment variable references in env field",
|
|
18
|
-
"passed": true,
|
|
19
|
-
"evidence": "Shows `\"MY_API_KEY\": \"$MY_API_KEY\"` and explains the $VAR_NAME pattern explicitly"
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
"text": "Explains includeTools and/or excludeTools for restricting exposed tools",
|
|
23
|
-
"passed": true,
|
|
24
|
-
"evidence": "Explains both includeTools (whitelist) and excludeTools (blacklist) with examples and guidance on when to use each"
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"text": "Mentions security considerations (trust field, not hardcoding keys, etc.)",
|
|
28
|
-
"passed": true,
|
|
29
|
-
"evidence": "Warns to never hardcode secrets, explains trust field, mentions auto-redaction of sensitive env vars"
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
"text": "Uses correct Python command (python/python3) in the command field",
|
|
33
|
-
"passed": true,
|
|
34
|
-
"evidence": "Uses both `python` and `python3` with note about system differences"
|
|
35
|
-
}
|
|
36
|
-
]
|
|
37
|
-
}
|