Skip to content

Commit 262ef11

Browse files
committed
Merge branch 'fix/gemini-md-directory-clean' and resolve conflicts
2 parents 6d4cf93 + 0a6935b commit 262ef11

File tree

309 files changed

+12800
-4567
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

309 files changed

+12800
-4567
lines changed

.gemini/settings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"experimental": {
3+
"skills": true
4+
}
5+
}

.gemini/skills/pr-creator/SKILL.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
---
2+
name: pr-creator
3+
description: Use this skill when asked to create a pull request (PR). It ensures all PRs follow the repository's established templates and standards.
4+
---
5+
6+
# Pull Request Creator
7+
8+
This skill guides the creation of high-quality Pull Requests that adhere to the repository's standards.
9+
10+
## Workflow
11+
12+
Follow these steps to create a Pull Request:
13+
14+
1. **Locate Template**: Search for a pull request template in the repository.
15+
* Check `.github/pull_request_template.md`
16+
* Check `.github/PULL_REQUEST_TEMPLATE.md`
17+
* If multiple templates exist (e.g., in `.github/PULL_REQUEST_TEMPLATE/`), ask the user which one to use or select the most appropriate one based on the context (e.g., `bug_fix.md` vs `feature.md`).
18+
19+
2. **Read Template**: Read the content of the identified template file.
20+
21+
3. **Draft Description**: Create a PR description that strictly follows the template's structure.
22+
* **Headings**: Keep all headings from the template.
23+
* **Checklists**: Review each item. Mark with `[x]` if completed. If an item is not applicable, leave it unchecked or mark as `[ ]` (depending on the template's instructions) or remove it if the template allows flexibility (but prefer keeping it unchecked for transparency).
24+
* **Content**: Fill in the sections with clear, concise summaries of your changes.
25+
* **Related Issues**: Link any issues fixed or related to this PR (e.g., "Fixes #123").
26+
27+
4. **Create PR**: Use the `gh` CLI to create the PR.
28+
```bash
29+
gh pr create --title "type(scope): succinct description" --body "..."
30+
```
31+
* **Title**: Ensure the title follows the [Conventional Commits](https://www.conventionalcommits.org/) format if the repository uses it (e.g., `feat(ui): add new button`, `fix(core): resolve crash`).
32+
33+
## Principles
34+
35+
* **Compliance**: Never ignore the PR template. It exists for a reason.
36+
* **Completeness**: Fill out all relevant sections.
37+
* **Accuracy**: Don't check boxes for tasks you haven't done.

.github/scripts/pr-triage.sh

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,51 @@ process_pr() {
1919
local PR_NUMBER=$1
2020
echo "🔄 Processing PR #${PR_NUMBER}"
2121

22-
# Get closing issue number with error handling
23-
local ISSUE_NUMBER
24-
if ! ISSUE_NUMBER=$(gh pr view "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --json closingIssuesReferences -q '.closingIssuesReferences.nodes[0].number' 2>/dev/null); then
25-
echo " ⚠️ Could not fetch closing issue for PR #${PR_NUMBER}"
22+
# Get PR details: closing issue, draft status, body and labels
23+
local PR_DATA
24+
if ! PR_DATA=$(gh pr view "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --json closingIssuesReferences,isDraft,body,labels 2>/dev/null); then
25+
echo " ⚠️ Could not fetch data for PR #${PR_NUMBER}"
26+
return 0
2627
fi
2728

29+
local ISSUE_NUMBER
30+
ISSUE_NUMBER=$(echo "${PR_DATA}" | jq -r '.closingIssuesReferences[0].number // empty')
31+
32+
# If no closing issue found, check body for references (e.g. #123)
2833
if [[ -z "${ISSUE_NUMBER}" ]]; then
29-
echo "⚠️ No linked issue found for PR #${PR_NUMBER}, adding status/need-issue label"
30-
if ! gh pr edit "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --add-label "status/need-issue" 2>/dev/null; then
31-
echo " ⚠️ Failed to add label (may already exist or have permission issues)"
34+
local REFERENCED_ISSUE
35+
# Search for # followed by digits, not preceded by alphanumeric chars
36+
REFERENCED_ISSUE=$(echo "${PR_DATA}" | jq -r '.body // empty' | grep -oE '(^|[^a-zA-Z0-9])#[0-9]+([^a-zA-Z0-9]|$)' | head -n 1 | grep -oE '[0-9]+' || echo "")
37+
if [[ -n "${REFERENCED_ISSUE}" ]]; then
38+
ISSUE_NUMBER="${REFERENCED_ISSUE}"
39+
echo "🔗 Found referenced issue #${ISSUE_NUMBER} in PR body"
3240
fi
33-
# Add PR number to the list
34-
if [[ -z "${PRS_NEEDING_COMMENT}" ]]; then
35-
PRS_NEEDING_COMMENT="${PR_NUMBER}"
41+
fi
42+
43+
local IS_DRAFT
44+
IS_DRAFT=$(echo "${PR_DATA}" | jq -r '.isDraft')
45+
46+
if [[ -z "${ISSUE_NUMBER}" ]]; then
47+
if [[ "${IS_DRAFT}" == "true" ]]; then
48+
echo "📝 PR #${PR_NUMBER} is a draft and has no linked issue, skipping status/need-issue label"
49+
# Remove status/need-issue label if it was previously added
50+
if ! gh pr edit "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --remove-label "status/need-issue" 2>/dev/null; then
51+
echo " status/need-issue label not present or could not be removed"
52+
fi
53+
echo "needs_comment=false" >> "${GITHUB_OUTPUT}"
3654
else
37-
PRS_NEEDING_COMMENT="${PRS_NEEDING_COMMENT},${PR_NUMBER}"
55+
echo "⚠️ No linked issue found for PR #${PR_NUMBER}, adding status/need-issue label"
56+
if ! gh pr edit "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --add-label "status/need-issue" 2>/dev/null; then
57+
echo " ⚠️ Failed to add label (may already exist or have permission issues)"
58+
fi
59+
# Add PR number to the list
60+
if [[ -z "${PRS_NEEDING_COMMENT}" ]]; then
61+
PRS_NEEDING_COMMENT="${PR_NUMBER}"
62+
else
63+
PRS_NEEDING_COMMENT="${PRS_NEEDING_COMMENT},${PR_NUMBER}"
64+
fi
65+
echo "needs_comment=true" >> "${GITHUB_OUTPUT}"
3866
fi
39-
echo "needs_comment=true" >> "${GITHUB_OUTPUT}"
4067
else
4168
echo "🔗 Found linked issue #${ISSUE_NUMBER}"
4269

@@ -46,33 +73,35 @@ process_pr() {
4673
fi
4774

4875
# Get issue labels
49-
echo "📥 Fetching labels from issue #${ISSUE_NUMBER}"
76+
echo "📥 Fetching area and priority labels from issue #${ISSUE_NUMBER}"
5077
local ISSUE_LABELS=""
51-
if ! ISSUE_LABELS=$(gh issue view "${ISSUE_NUMBER}" --repo "${GITHUB_REPOSITORY}" --json labels -q '.labels[].name' 2>/dev/null | tr '\n' ',' | sed 's/,$//' || echo ""); then
78+
local gh_output
79+
if ! gh_output=$(gh issue view "${ISSUE_NUMBER}" --repo "${GITHUB_REPOSITORY}" --json labels -q '.labels[].name' 2>/dev/null); then
5280
echo " ⚠️ Could not fetch issue #${ISSUE_NUMBER} (may not exist or be in different repo)"
5381
ISSUE_LABELS=""
82+
else
83+
# If grep finds no matches, it exits with 1, which pipefail would treat as an error.
84+
# `|| echo ""` ensures the command succeeds with an empty string in that case.
85+
ISSUE_LABELS=$(echo "${gh_output}" | grep -E "^(area|priority)/" | tr '\n' ',' | sed 's/,$//' || echo "")
5486
fi
5587

56-
# Get PR labels
57-
echo "📥 Fetching labels from PR #${PR_NUMBER}"
88+
# Get PR labels from already fetched PR_DATA
89+
echo "📥 Extracting labels from PR #${PR_NUMBER}"
5890
local PR_LABELS=""
59-
if ! PR_LABELS=$(gh pr view "${PR_NUMBER}" --repo "${GITHUB_REPOSITORY}" --json labels -q '.labels[].name' 2>/dev/null | tr '\n' ',' | sed 's/,$//' || echo ""); then
60-
echo " ⚠️ Could not fetch PR labels"
61-
PR_LABELS=""
62-
fi
91+
PR_LABELS=$(echo "${PR_DATA}" | jq -r '.labels[].name // empty' | tr '\n' ',' | sed 's/,$//' || echo "")
6392

64-
echo " Issue labels: ${ISSUE_LABELS}"
93+
echo " Issue labels (area/priority): ${ISSUE_LABELS}"
6594
echo " PR labels: ${PR_LABELS}"
6695

6796
# Convert comma-separated strings to arrays
6897
local ISSUE_LABEL_ARRAY PR_LABEL_ARRAY
6998
IFS=',' read -ra ISSUE_LABEL_ARRAY <<< "${ISSUE_LABELS}"
70-
IFS=',' read -ra PR_LABEL_ARRAY <<< "${PR_LABELS}"
99+
IFS=',' read -ra PR_LABEL_ARRAY <<< "${PR_LABELS:-}"
71100

72101
# Find labels to add (on issue but not on PR)
73102
local LABELS_TO_ADD=""
74103
for label in "${ISSUE_LABEL_ARRAY[@]}"; do
75-
if [[ -n "${label}" ]] && [[ " ${PR_LABEL_ARRAY[*]} " != *" ${label} "* ]]; then
104+
if [[ -n "${label}" ]] && [[ " ${PR_LABEL_ARRAY[*]:-}" != *" ${label} "* ]]; then
76105
if [[ -z "${LABELS_TO_ADD}" ]]; then
77106
LABELS_TO_ADD="${label}"
78107
else

.github/workflows/chained_e2e.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ jobs:
168168
GEMINI_API_KEY: '${{ secrets.GEMINI_API_KEY }}'
169169
KEEP_OUTPUT: 'true'
170170
VERBOSE: 'true'
171+
BUILD_SANDBOX_FLAGS: '--cache-from type=gha --cache-to type=gha,mode=max'
171172
shell: 'bash'
172173
run: |
173174
if [[ "${{ matrix.sandbox }}" == "sandbox:docker" ]]; then

.github/workflows/ci.yml

Lines changed: 44 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ jobs:
5050
runs-on: 'gemini-cli-ubuntu-16-core'
5151
needs: 'merge_queue_skipper'
5252
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
53+
env:
54+
GEMINI_LINT_TEMP_DIR: '${{ github.workspace }}/.gemini-linters'
5355
steps:
5456
- name: 'Checkout'
5557
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
@@ -63,9 +65,21 @@ jobs:
6365
node-version-file: '.nvmrc'
6466
cache: 'npm'
6567

68+
- name: 'Cache Linters'
69+
uses: 'actions/cache@v4'
70+
with:
71+
path: '${{ env.GEMINI_LINT_TEMP_DIR }}'
72+
key: "${{ runner.os }}-${{ runner.arch }}-linters-${{ hashFiles('scripts/lint.js') }}"
73+
6674
- name: 'Install dependencies'
6775
run: 'npm ci'
6876

77+
- name: 'Cache ESLint'
78+
uses: 'actions/cache@v4'
79+
with:
80+
path: '.eslintcache'
81+
key: "${{ runner.os }}-eslint-${{ hashFiles('package-lock.json', 'eslint.config.js') }}"
82+
6983
- name: 'Validate NOTICES.txt'
7084
run: 'git diff --exit-code packages/vscode-ide-companion/NOTICES.txt'
7185

@@ -111,10 +125,9 @@ jobs:
111125
args: '--verbose --accept 200,503 ./**/*.md'
112126
fail: true
113127
test_linux:
114-
name: 'Test (Linux)'
128+
name: 'Test (Linux) - ${{ matrix.node-version }}, ${{ matrix.shard }}'
115129
runs-on: 'gemini-cli-ubuntu-16-core'
116130
needs:
117-
- 'lint'
118131
- 'merge_queue_skipper'
119132
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
120133
permissions:
@@ -127,6 +140,9 @@ jobs:
127140
- '20.x'
128141
- '22.x'
129142
- '24.x'
143+
shard:
144+
- 'cli'
145+
- 'others'
130146
steps:
131147
- name: 'Checkout'
132148
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
@@ -146,7 +162,14 @@ jobs:
146162
- name: 'Run tests and generate reports'
147163
env:
148164
NO_COLOR: true
149-
run: 'npm run test:ci'
165+
run: |
166+
if [[ "${{ matrix.shard }}" == "cli" ]]; then
167+
npm run test:ci --workspace @google/gemini-cli
168+
else
169+
# Explicitly list non-cli packages to ensure they are sharded correctly
170+
npm run test:ci --workspace @google/gemini-cli-core --workspace @google/gemini-cli-a2a-server --workspace gemini-cli-vscode-ide-companion --workspace @google/gemini-cli-test-utils --if-present
171+
npm run test:scripts
172+
fi
150173
151174
- name: 'Bundle'
152175
run: 'npm run bundle'
@@ -162,7 +185,7 @@ jobs:
162185
${{ always() && (github.event.pull_request.head.repo.full_name == github.repository) }}
163186
uses: 'dorny/test-reporter@dc3a92680fcc15842eef52e8c4606ea7ce6bd3f3' # ratchet:dorny/test-reporter@v2
164187
with:
165-
name: 'Test Results (Node ${{ matrix.node-version }})'
188+
name: 'Test Results (Node ${{ runner.os }}, ${{ matrix.node-version }}, ${{ matrix.shard }})'
166189
path: 'packages/*/junit.xml'
167190
reporter: 'java-junit'
168191
fail-on-error: 'false'
@@ -172,14 +195,13 @@ jobs:
172195
${{ always() && (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }}
173196
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
174197
with:
175-
name: 'test-results-fork-${{ matrix.node-version }}-${{ runner.os }}'
198+
name: 'test-results-fork-${{ runner.os }}-${{ matrix.node-version }}-${{ matrix.shard }}'
176199
path: 'packages/*/junit.xml'
177200

178201
test_mac:
179-
name: 'Test (Mac)'
180-
runs-on: '${{ matrix.os }}'
202+
name: 'Test (Mac) - ${{ matrix.node-version }}, ${{ matrix.shard }}'
203+
runs-on: 'macos-latest'
181204
needs:
182-
- 'lint'
183205
- 'merge_queue_skipper'
184206
if: "${{needs.merge_queue_skipper.outputs.skip == 'false'}}"
185207
permissions:
@@ -189,12 +211,13 @@ jobs:
189211
continue-on-error: true
190212
strategy:
191213
matrix:
192-
os:
193-
- 'macos-latest'
194214
node-version:
195215
- '20.x'
196216
- '22.x'
197217
- '24.x'
218+
shard:
219+
- 'cli'
220+
- 'others'
198221
steps:
199222
- name: 'Checkout'
200223
uses: 'actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8' # ratchet:actions/checkout@v5
@@ -214,7 +237,14 @@ jobs:
214237
- name: 'Run tests and generate reports'
215238
env:
216239
NO_COLOR: true
217-
run: 'npm run test:ci -- --coverage.enabled=false'
240+
run: |
241+
if [[ "${{ matrix.shard }}" == "cli" ]]; then
242+
npm run test:ci --workspace @google/gemini-cli -- --coverage.enabled=false
243+
else
244+
# Explicitly list non-cli packages to ensure they are sharded correctly
245+
npm run test:ci --workspace @google/gemini-cli-core --workspace @google/gemini-cli-a2a-server --workspace gemini-cli-vscode-ide-companion --workspace @google/gemini-cli-test-utils --if-present -- --coverage.enabled=false
246+
npm run test:scripts
247+
fi
218248
219249
- name: 'Bundle'
220250
run: 'npm run bundle'
@@ -230,7 +260,7 @@ jobs:
230260
${{ always() && (github.event.pull_request.head.repo.full_name == github.repository) }}
231261
uses: 'dorny/test-reporter@dc3a92680fcc15842eef52e8c4606ea7ce6bd3f3' # ratchet:dorny/test-reporter@v2
232262
with:
233-
name: 'Test Results (Node ${{ matrix.node-version }})'
263+
name: 'Test Results (Node ${{ runner.os }}, ${{ matrix.node-version }}, ${{ matrix.shard }})'
234264
path: 'packages/*/junit.xml'
235265
reporter: 'java-junit'
236266
fail-on-error: 'false'
@@ -240,15 +270,15 @@ jobs:
240270
${{ always() && (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) }}
241271
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
242272
with:
243-
name: 'test-results-fork-${{ matrix.node-version }}-${{ runner.os }}'
273+
name: 'test-results-fork-${{ runner.os }}-${{ matrix.node-version }}-${{ matrix.shard }}'
244274
path: 'packages/*/junit.xml'
245275

246276
- name: 'Upload coverage reports'
247277
if: |-
248278
${{ always() }}
249279
uses: 'actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02' # ratchet:actions/upload-artifact@v4
250280
with:
251-
name: 'coverage-reports-${{ matrix.node-version }}-${{ matrix.os }}'
281+
name: 'coverage-reports-${{ runner.os }}-${{ matrix.node-version }}-${{ matrix.shard }}'
252282
path: 'packages/*/coverage'
253283

254284
codeql:

.github/workflows/gemini-automated-issue-dedup.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ jobs:
101101
"FIRESTORE_DATABASE_ID": "(default)",
102102
"GOOGLE_APPLICATION_CREDENTIALS": "${GOOGLE_APPLICATION_CREDENTIALS}"
103103
},
104-
"enabled": true,
105104
"timeout": 600000
106105
}
107106
},

.github/workflows/gemini-automated-issue-triage.yml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ jobs:
3939
github.event_name == 'workflow_dispatch' ||
4040
(
4141
(github.event_name == 'issues' || github.event_name == 'issue_comment') &&
42-
contains(github.event.issue.labels.*.name, 'status/need-triage') &&
4342
(github.event_name != 'issue_comment' || (
4443
contains(github.event.comment.body, '@gemini-cli /triage') &&
4544
(github.event.comment.author_association == 'OWNER' || github.event.comment.author_association == 'MEMBER' || github.event.comment.author_association == 'COLLABORATOR')
@@ -75,11 +74,6 @@ jobs:
7574
ISSUE_NUMBER_INPUT: '${{ github.event.inputs.issue_number }}'
7675
LABELS: '${{ steps.get_issue_data.outputs.labels }}'
7776
run: |
78-
if ! echo "${LABELS}" | grep -q 'status/need-triage'; then
79-
echo "Issue #${ISSUE_NUMBER_INPUT} does not have the 'status/need-triage' label. Stopping workflow."
80-
exit 1
81-
fi
82-
8377
if echo "${LABELS}" | grep -q 'area/'; then
8478
echo "Issue #${ISSUE_NUMBER_INPUT} already has 'area/' label. Stopping workflow."
8579
exit 1

.github/workflows/gemini-scheduled-issue-dedup.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ jobs:
8181
"FIRESTORE_DATABASE_ID": "(default)",
8282
"GOOGLE_APPLICATION_CREDENTIALS": "${GOOGLE_APPLICATION_CREDENTIALS}"
8383
},
84-
"enabled": true,
8584
"timeout": 600000
8685
}
8786
},

.github/workflows/gemini-scheduled-issue-triage.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ jobs:
4545
4646
echo '🔍 Finding issues without labels...'
4747
NO_LABEL_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \
48-
--search 'is:open is:issue no:label' --json number,title,body)"
48+
--search 'is:open is:issue no:label' --limit 10 --json number,title,body)"
4949
5050
echo '🏷️ Finding issues that need triage...'
5151
NEED_TRIAGE_ISSUES="$(gh issue list --repo "${GITHUB_REPOSITORY}" \
52-
--search "is:open is:issue label:\"status/need-triage\"" --limit 1000 --json number,title,body)"
52+
--search "is:open is:issue label:\"status/need-triage\"" --limit 10 --json number,title,body)"
5353
5454
echo '🔄 Merging and deduplicating issues...'
5555
ISSUES="$(echo "${NO_LABEL_ISSUES}" "${NEED_TRIAGE_ISSUES}" | jq -c -s 'add | unique_by(.number)')"

0 commit comments

Comments
 (0)