Skip to content

Commit 29d9de1

Browse files
committed
Merge remote-tracking branch 'upstream/main'
2 parents 5788210 + 0cf01df commit 29d9de1

File tree

12 files changed

+313
-305
lines changed

12 files changed

+313
-305
lines changed

.github/actions/verify-release/action.yml

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,5 @@ runs:
6868
exit 1
6969
fi
7070
71-
- name: 'Install dependencies for integration tests'
72-
shell: 'bash'
73-
working-directory: './verify'
74-
run: 'npm install'
75-
76-
- name: '🔬 Run integration tests against NPM release'
77-
working-directory: './verify'
78-
env:
79-
GEMINI_API_KEY: '${{ inputs.gemini_api_key }}'
80-
INTEGRATION_TEST_USE_INSTALLED_GEMINI: 'true'
81-
shell: 'bash'
82-
run: 'npm run test:integration:sandbox:none'
71+
# TODO: Add back integration tests once we resolve
72+
# https://github.com/google-gemini/gemini-cli/issues/10517

packages/cli/src/commands/extensions/update.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,13 @@ export async function handleUpdate(args: UpdateArgs) {
5353
console.log(`Extension "${args.name}" not found.`);
5454
return;
5555
}
56-
let updateState: ExtensionUpdateState | undefined;
5756
if (!extension.installMetadata) {
5857
console.log(
5958
`Unable to install extension "${args.name}" due to missing install metadata`,
6059
);
6160
return;
6261
}
63-
await checkForExtensionUpdate(extension, (newState) => {
64-
updateState = newState;
65-
});
62+
const updateState = await checkForExtensionUpdate(extension);
6663
if (updateState !== ExtensionUpdateState.UPDATE_AVAILABLE) {
6764
console.log(`Extension "${args.name}" is already up to date.`);
6865
return;
@@ -92,14 +89,17 @@ export async function handleUpdate(args: UpdateArgs) {
9289
if (args.all) {
9390
try {
9491
const extensionState = new Map();
95-
await checkForAllExtensionUpdates(extensions, (action) => {
96-
if (action.type === 'SET_STATE') {
97-
extensionState.set(action.payload.name, {
98-
status: action.payload.state,
99-
processed: true, // No need to process as we will force the update.
100-
});
101-
}
102-
});
92+
await checkForAllExtensionUpdates(
93+
extensions,
94+
(action) => {
95+
if (action.type === 'SET_STATE') {
96+
extensionState.set(action.payload.name, {
97+
status: action.payload.state,
98+
});
99+
}
100+
},
101+
workingDir,
102+
);
103103
let updateInfos = await updateAllUpdatableExtensions(
104104
workingDir,
105105
requestConsentNonInteractive,

packages/cli/src/config/extensions/github.test.ts

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,7 @@ describe('git extension helpers', () => {
132132
source: '',
133133
},
134134
};
135-
let result: ExtensionUpdateState | undefined = undefined;
136-
await checkForExtensionUpdate(
137-
extension,
138-
(newState) => (result = newState),
139-
);
135+
const result = await checkForExtensionUpdate(extension);
140136
expect(result).toBe(ExtensionUpdateState.NOT_UPDATABLE);
141137
});
142138

@@ -152,11 +148,7 @@ describe('git extension helpers', () => {
152148
},
153149
};
154150
mockGit.getRemotes.mockResolvedValue([]);
155-
let result: ExtensionUpdateState | undefined = undefined;
156-
await checkForExtensionUpdate(
157-
extension,
158-
(newState) => (result = newState),
159-
);
151+
const result = await checkForExtensionUpdate(extension);
160152
expect(result).toBe(ExtensionUpdateState.ERROR);
161153
});
162154

@@ -177,11 +169,7 @@ describe('git extension helpers', () => {
177169
mockGit.listRemote.mockResolvedValue('remote-hash\tHEAD');
178170
mockGit.revparse.mockResolvedValue('local-hash');
179171

180-
let result: ExtensionUpdateState | undefined = undefined;
181-
await checkForExtensionUpdate(
182-
extension,
183-
(newState) => (result = newState),
184-
);
172+
const result = await checkForExtensionUpdate(extension);
185173
expect(result).toBe(ExtensionUpdateState.UPDATE_AVAILABLE);
186174
});
187175

@@ -202,11 +190,7 @@ describe('git extension helpers', () => {
202190
mockGit.listRemote.mockResolvedValue('same-hash\tHEAD');
203191
mockGit.revparse.mockResolvedValue('same-hash');
204192

205-
let result: ExtensionUpdateState | undefined = undefined;
206-
await checkForExtensionUpdate(
207-
extension,
208-
(newState) => (result = newState),
209-
);
193+
const result = await checkForExtensionUpdate(extension);
210194
expect(result).toBe(ExtensionUpdateState.UP_TO_DATE);
211195
});
212196

@@ -223,11 +207,7 @@ describe('git extension helpers', () => {
223207
};
224208
mockGit.getRemotes.mockRejectedValue(new Error('git error'));
225209

226-
let result: ExtensionUpdateState | undefined = undefined;
227-
await checkForExtensionUpdate(
228-
extension,
229-
(newState) => (result = newState),
230-
);
210+
const result = await checkForExtensionUpdate(extension);
231211
expect(result).toBe(ExtensionUpdateState.ERROR);
232212
});
233213
});

packages/cli/src/config/extensions/github.ts

Lines changed: 15 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,8 @@ async function fetchReleaseFromGithub(
119119

120120
export async function checkForExtensionUpdate(
121121
extension: GeminiCLIExtension,
122-
setExtensionUpdateState: (updateState: ExtensionUpdateState) => void,
123122
cwd: string = process.cwd(),
124-
): Promise<void> {
125-
setExtensionUpdateState(ExtensionUpdateState.CHECKING_FOR_UPDATES);
123+
): Promise<ExtensionUpdateState> {
126124
const installMetadata = extension.installMetadata;
127125
if (installMetadata?.type === 'local') {
128126
const newExtension = loadExtension({
@@ -133,38 +131,32 @@ export async function checkForExtensionUpdate(
133131
console.error(
134132
`Failed to check for update for local extension "${extension.name}". Could not load extension from source path: ${installMetadata.source}`,
135133
);
136-
setExtensionUpdateState(ExtensionUpdateState.ERROR);
137-
return;
134+
return ExtensionUpdateState.ERROR;
138135
}
139136
if (newExtension.config.version !== extension.version) {
140-
setExtensionUpdateState(ExtensionUpdateState.UPDATE_AVAILABLE);
141-
return;
137+
return ExtensionUpdateState.UPDATE_AVAILABLE;
142138
}
143-
setExtensionUpdateState(ExtensionUpdateState.UP_TO_DATE);
144-
return;
139+
return ExtensionUpdateState.UP_TO_DATE;
145140
}
146141
if (
147142
!installMetadata ||
148143
(installMetadata.type !== 'git' &&
149144
installMetadata.type !== 'github-release')
150145
) {
151-
setExtensionUpdateState(ExtensionUpdateState.NOT_UPDATABLE);
152-
return;
146+
return ExtensionUpdateState.NOT_UPDATABLE;
153147
}
154148
try {
155149
if (installMetadata.type === 'git') {
156150
const git = simpleGit(extension.path);
157151
const remotes = await git.getRemotes(true);
158152
if (remotes.length === 0) {
159153
console.error('No git remotes found.');
160-
setExtensionUpdateState(ExtensionUpdateState.ERROR);
161-
return;
154+
return ExtensionUpdateState.ERROR;
162155
}
163156
const remoteUrl = remotes[0].refs.fetch;
164157
if (!remoteUrl) {
165158
console.error(`No fetch URL found for git remote ${remotes[0].name}.`);
166-
setExtensionUpdateState(ExtensionUpdateState.ERROR);
167-
return;
159+
return ExtensionUpdateState.ERROR;
168160
}
169161

170162
// Determine the ref to check on the remote.
@@ -174,8 +166,7 @@ export async function checkForExtensionUpdate(
174166

175167
if (typeof lsRemoteOutput !== 'string' || lsRemoteOutput.trim() === '') {
176168
console.error(`Git ref ${refToCheck} not found.`);
177-
setExtensionUpdateState(ExtensionUpdateState.ERROR);
178-
return;
169+
return ExtensionUpdateState.ERROR;
179170
}
180171

181172
const remoteHash = lsRemoteOutput.split('\t')[0];
@@ -185,21 +176,17 @@ export async function checkForExtensionUpdate(
185176
console.error(
186177
`Unable to parse hash from git ls-remote output "${lsRemoteOutput}"`,
187178
);
188-
setExtensionUpdateState(ExtensionUpdateState.ERROR);
189-
return;
179+
return ExtensionUpdateState.ERROR;
190180
}
191181
if (remoteHash === localHash) {
192-
setExtensionUpdateState(ExtensionUpdateState.UP_TO_DATE);
193-
return;
182+
return ExtensionUpdateState.UP_TO_DATE;
194183
}
195-
setExtensionUpdateState(ExtensionUpdateState.UPDATE_AVAILABLE);
196-
return;
184+
return ExtensionUpdateState.UPDATE_AVAILABLE;
197185
} else {
198186
const { source, releaseTag } = installMetadata;
199187
if (!source) {
200188
console.error(`No "source" provided for extension.`);
201-
setExtensionUpdateState(ExtensionUpdateState.ERROR);
202-
return;
189+
return ExtensionUpdateState.ERROR;
203190
}
204191
const { owner, repo } = parseGitHubRepoForReleases(source);
205192

@@ -209,18 +196,15 @@ export async function checkForExtensionUpdate(
209196
installMetadata.ref,
210197
);
211198
if (releaseData.tag_name !== releaseTag) {
212-
setExtensionUpdateState(ExtensionUpdateState.UPDATE_AVAILABLE);
213-
return;
199+
return ExtensionUpdateState.UPDATE_AVAILABLE;
214200
}
215-
setExtensionUpdateState(ExtensionUpdateState.UP_TO_DATE);
216-
return;
201+
return ExtensionUpdateState.UP_TO_DATE;
217202
}
218203
} catch (error) {
219204
console.error(
220205
`Failed to check for updates for extension "${installMetadata.source}": ${getErrorMessage(error)}`,
221206
);
222-
setExtensionUpdateState(ExtensionUpdateState.ERROR);
223-
return;
207+
return ExtensionUpdateState.ERROR;
224208
}
225209
}
226210
export interface GitHubDownloadResult {

packages/cli/src/config/extensions/update.test.ts

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -302,7 +302,11 @@ describe('update tests', () => {
302302
mockGit.revparse.mockResolvedValue('localHash');
303303

304304
const dispatch = vi.fn();
305-
await checkForAllExtensionUpdates([extension], dispatch);
305+
await checkForAllExtensionUpdates(
306+
[extension],
307+
dispatch,
308+
tempWorkspaceDir,
309+
);
306310
expect(dispatch).toHaveBeenCalledWith({
307311
type: 'SET_STATE',
308312
payload: {
@@ -340,7 +344,11 @@ describe('update tests', () => {
340344
mockGit.revparse.mockResolvedValue('sameHash');
341345

342346
const dispatch = vi.fn();
343-
await checkForAllExtensionUpdates([extension], dispatch);
347+
await checkForAllExtensionUpdates(
348+
[extension],
349+
dispatch,
350+
tempWorkspaceDir,
351+
);
344352
expect(dispatch).toHaveBeenCalledWith({
345353
type: 'SET_STATE',
346354
payload: {
@@ -375,7 +383,11 @@ describe('update tests', () => {
375383
new ExtensionEnablementManager(ExtensionStorage.getUserExtensionsDir()),
376384
)[0];
377385
const dispatch = vi.fn();
378-
await checkForAllExtensionUpdates([extension], dispatch);
386+
await checkForAllExtensionUpdates(
387+
[extension],
388+
dispatch,
389+
tempWorkspaceDir,
390+
);
379391
expect(dispatch).toHaveBeenCalledWith({
380392
type: 'SET_STATE',
381393
payload: {
@@ -410,7 +422,11 @@ describe('update tests', () => {
410422
new ExtensionEnablementManager(ExtensionStorage.getUserExtensionsDir()),
411423
)[0];
412424
const dispatch = vi.fn();
413-
await checkForAllExtensionUpdates([extension], dispatch);
425+
await checkForAllExtensionUpdates(
426+
[extension],
427+
dispatch,
428+
tempWorkspaceDir,
429+
);
414430
expect(dispatch).toHaveBeenCalledWith({
415431
type: 'SET_STATE',
416432
payload: {
@@ -444,7 +460,11 @@ describe('update tests', () => {
444460
mockGit.getRemotes.mockRejectedValue(new Error('Git error'));
445461

446462
const dispatch = vi.fn();
447-
await checkForAllExtensionUpdates([extension], dispatch);
463+
await checkForAllExtensionUpdates(
464+
[extension],
465+
dispatch,
466+
tempWorkspaceDir,
467+
);
448468
expect(dispatch).toHaveBeenCalledWith({
449469
type: 'SET_STATE',
450470
payload: {

packages/cli/src/config/extensions/update.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ export interface ExtensionUpdateCheckResult {
154154
export async function checkForAllExtensionUpdates(
155155
extensions: GeminiCLIExtension[],
156156
dispatch: (action: ExtensionUpdateAction) => void,
157+
cwd: string = process.cwd(),
157158
): Promise<void> {
158159
dispatch({ type: 'BATCH_CHECK_START' });
159160
const promises: Array<Promise<void>> = [];
@@ -168,13 +169,20 @@ export async function checkForAllExtensionUpdates(
168169
});
169170
continue;
170171
}
172+
dispatch({
173+
type: 'SET_STATE',
174+
payload: {
175+
name: extension.name,
176+
state: ExtensionUpdateState.CHECKING_FOR_UPDATES,
177+
},
178+
});
171179
promises.push(
172-
checkForExtensionUpdate(extension, (updatedState) => {
180+
checkForExtensionUpdate(extension, cwd).then((state) =>
173181
dispatch({
174182
type: 'SET_STATE',
175-
payload: { name: extension.name, state: updatedState },
176-
});
177-
}),
183+
payload: { name: extension.name, state },
184+
}),
185+
),
178186
);
179187
}
180188
await Promise.all(promises);

0 commit comments

Comments
 (0)