Skip to content

Commit dcc0015

Browse files
authored
Merge branch 'main' into renovate/major-github-actions
2 parents c37bd4f + afaa3b5 commit dcc0015

56 files changed

Lines changed: 3808 additions & 3141 deletions

Some content is hidden

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

DEVELOPER.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# DEVELOPER.md
22

33
This document provides instructions for setting up your development environment
4-
and contributing to the Cloud SQL for PostgreSQL Gemini CLI Extension project.
4+
and contributing to the Cloud SQL for PostgreSQL Agent skills project.
55

66
## Prerequisites
77

@@ -61,7 +61,7 @@ be successfully installed by the Gemini CLI.
6161

6262
Currently, there are no automated unit or integration test suites
6363
within this repository. All functional testing must be performed manually. All tools
64-
are currently tested in the [MCP Toolbox GitHub](https://github.com/googleapis/genai-toolbox).
64+
are currently tested in the [MCP Toolbox GitHub](https://github.com/googleapis/mcp-toolbox).
6565

6666
### Other GitHub Checks
6767

@@ -102,7 +102,7 @@ The release process is automated using `release-please`. It consists of an autom
102102
#### Automated Changelog Enrichment
103103
104104
Before a Release PR is even created, a special workflow automatically mirrors
105-
relevant changelogs from the core `googleapis/genai-toolbox` dependency. This
105+
relevant changelogs from the core `googleapis/mcp-toolbox` dependency. This
106106
ensures that the release notes for this extension accurately reflect important
107107
upstream changes.
108108

README.md

Lines changed: 181 additions & 76 deletions
Large diffs are not rendered by default.

release-please-config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"release-type": "simple",
2929
"package-name": "cloud-sql-postgresql",
3030
"extra-files": [
31+
"README.md",
3132
{
3233
"type": "json",
3334
"path": "gemini-extension.json",

skills/cloud-sql-postgres-admin/scripts/clone_instance.js

Lines changed: 71 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -17,78 +17,89 @@
1717
const { spawn, execSync } = require('child_process');
1818
const path = require('path');
1919
const fs = require('fs');
20+
const os = require('os');
2021

2122
const toolName = "clone_instance";
2223
const configArgs = ["--prebuilt", "cloud-sql-postgres"];
2324

24-
function getToolboxPath() {
25-
if (process.env.GEMINI_CLI === '1') {
26-
const localPath = path.resolve(__dirname, '../../../toolbox');
27-
if (fs.existsSync(localPath)) {
28-
return localPath;
29-
}
30-
}
31-
try {
32-
const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
33-
const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
34-
if (globalPath) {
35-
return globalPath.split('\n')[0].trim();
36-
}
37-
throw new Error("Toolbox binary not found");
38-
} catch (e) {
39-
throw new Error("Toolbox binary not found");
40-
}
41-
}
25+
const OPTIONAL_VARS_TO_OMIT_IF_EMPTY = [
26+
'CLOUD_SQL_POSTGRES_USER',
27+
'CLOUD_SQL_POSTGRES_PASSWORD',
28+
'CLOUD_SQL_POSTGRES_IP_TYPE',
29+
];
4230

43-
let toolboxBinary;
44-
try {
45-
toolboxBinary = getToolboxPath();
46-
} catch (err) {
47-
console.error("Error:", err.message);
48-
process.exit(1);
31+
32+
function mergeEnvVars(env) {
33+
if (process.env.GEMINI_CLI === '1') {
34+
const envPath = path.resolve(__dirname, '../../../.env');
35+
if (fs.existsSync(envPath)) {
36+
const envContent = fs.readFileSync(envPath, 'utf-8');
37+
envContent.split('\n').forEach(line => {
38+
const trimmed = line.trim();
39+
if (trimmed && !trimmed.startsWith('#')) {
40+
const splitIdx = trimmed.indexOf('=');
41+
if (splitIdx !== -1) {
42+
const key = trimmed.slice(0, splitIdx).trim();
43+
let value = trimmed.slice(splitIdx + 1).trim();
44+
value = value.replace(/(^['"]|['"]$)/g, '');
45+
if (env[key] === undefined) {
46+
env[key] = value;
47+
}
48+
}
49+
}
50+
});
51+
}
52+
} else if (process.env.CLAUDECODE === '1') {
53+
const prefix = 'CLAUDE_PLUGIN_OPTION_';
54+
for (const key in process.env) {
55+
if (key.startsWith(prefix)) {
56+
env[key.substring(prefix.length)] = process.env[key];
57+
}
58+
}
59+
}
4960
}
5061

51-
function getEnv() {
52-
const envPath = path.resolve(__dirname, '../../../.env');
53-
const env = { ...process.env };
54-
if (fs.existsSync(envPath)) {
55-
const envContent = fs.readFileSync(envPath, 'utf-8');
56-
envContent.split('\n').forEach(line => {
57-
const trimmed = line.trim();
58-
if (trimmed && !trimmed.startsWith('#')) {
59-
const splitIdx = trimmed.indexOf('=');
60-
if (splitIdx !== -1) {
61-
const key = trimmed.slice(0, splitIdx).trim();
62-
let value = trimmed.slice(splitIdx + 1).trim();
63-
value = value.replace(/(^['"]|['"]$)/g, '');
64-
if (env[key] === undefined) {
65-
env[key] = value;
66-
}
67-
}
68-
}
69-
});
62+
function prepareEnvironment() {
63+
let env = { ...process.env };
64+
let userAgent = "skills";
65+
if (process.env.GEMINI_CLI === '1') {
66+
userAgent = "skills-geminicli";
67+
} else if (process.env.CLAUDECODE === '1') {
68+
userAgent = "skills-claudecode";
69+
} else if (process.env.CODEX_CI === '1') {
70+
userAgent = "skills-codex";
7071
}
71-
return env;
72-
}
72+
mergeEnvVars(env);
73+
74+
OPTIONAL_VARS_TO_OMIT_IF_EMPTY.forEach(varName => {
75+
if (env[varName] === '') {
76+
delete env[varName];
77+
}
78+
});
79+
7380

74-
let env = process.env;
75-
let userAgent = "skills";
76-
if (process.env.GEMINI_CLI === '1') {
77-
env = getEnv();
78-
userAgent = "skills-geminicli";
81+
return { env, userAgent };
7982
}
8083

81-
const args = process.argv.slice(2);
84+
function main() {
85+
const { env, userAgent } = prepareEnvironment();
86+
const args = process.argv.slice(2);
87+
88+
const command = os.platform() === 'win32' ? 'npx.cmd' : 'npx';
89+
const processedArgs = os.platform() === 'win32' ? args.map(arg => arg.includes('"') ? '"' + arg.replace(/"/g, '""') + '"' : arg) : args;
90+
const npxArgs = ["--yes", "@toolbox-sdk/server@1.0.0", "--log-level", "error", ...configArgs, "invoke", toolName, "--user-agent-metadata", userAgent, ...processedArgs];
8291

83-
const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, "--user-agent-metadata", userAgent, ...args];
92+
const child = spawn(command, npxArgs, { shell: os.platform() === 'win32', stdio: 'inherit', env });
93+
8494

85-
const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
95+
child.on('close', (code) => {
96+
process.exit(code);
97+
});
8698

87-
child.on('close', (code) => {
88-
process.exit(code);
89-
});
99+
child.on('error', (err) => {
100+
console.error("Error executing toolbox:", err);
101+
process.exit(1);
102+
});
103+
}
90104

91-
child.on('error', (err) => {
92-
console.error("Error executing toolbox:", err);
93-
process.exit(1);
94-
});
105+
main();

skills/cloud-sql-postgres-admin/scripts/create_database.js

Lines changed: 71 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -17,78 +17,89 @@
1717
const { spawn, execSync } = require('child_process');
1818
const path = require('path');
1919
const fs = require('fs');
20+
const os = require('os');
2021

2122
const toolName = "create_database";
2223
const configArgs = ["--prebuilt", "cloud-sql-postgres"];
2324

24-
function getToolboxPath() {
25-
if (process.env.GEMINI_CLI === '1') {
26-
const localPath = path.resolve(__dirname, '../../../toolbox');
27-
if (fs.existsSync(localPath)) {
28-
return localPath;
29-
}
30-
}
31-
try {
32-
const checkCommand = process.platform === 'win32' ? 'where toolbox' : 'which toolbox';
33-
const globalPath = execSync(checkCommand, { stdio: 'pipe', encoding: 'utf-8' }).trim();
34-
if (globalPath) {
35-
return globalPath.split('\n')[0].trim();
36-
}
37-
throw new Error("Toolbox binary not found");
38-
} catch (e) {
39-
throw new Error("Toolbox binary not found");
40-
}
41-
}
25+
const OPTIONAL_VARS_TO_OMIT_IF_EMPTY = [
26+
'CLOUD_SQL_POSTGRES_USER',
27+
'CLOUD_SQL_POSTGRES_PASSWORD',
28+
'CLOUD_SQL_POSTGRES_IP_TYPE',
29+
];
4230

43-
let toolboxBinary;
44-
try {
45-
toolboxBinary = getToolboxPath();
46-
} catch (err) {
47-
console.error("Error:", err.message);
48-
process.exit(1);
31+
32+
function mergeEnvVars(env) {
33+
if (process.env.GEMINI_CLI === '1') {
34+
const envPath = path.resolve(__dirname, '../../../.env');
35+
if (fs.existsSync(envPath)) {
36+
const envContent = fs.readFileSync(envPath, 'utf-8');
37+
envContent.split('\n').forEach(line => {
38+
const trimmed = line.trim();
39+
if (trimmed && !trimmed.startsWith('#')) {
40+
const splitIdx = trimmed.indexOf('=');
41+
if (splitIdx !== -1) {
42+
const key = trimmed.slice(0, splitIdx).trim();
43+
let value = trimmed.slice(splitIdx + 1).trim();
44+
value = value.replace(/(^['"]|['"]$)/g, '');
45+
if (env[key] === undefined) {
46+
env[key] = value;
47+
}
48+
}
49+
}
50+
});
51+
}
52+
} else if (process.env.CLAUDECODE === '1') {
53+
const prefix = 'CLAUDE_PLUGIN_OPTION_';
54+
for (const key in process.env) {
55+
if (key.startsWith(prefix)) {
56+
env[key.substring(prefix.length)] = process.env[key];
57+
}
58+
}
59+
}
4960
}
5061

51-
function getEnv() {
52-
const envPath = path.resolve(__dirname, '../../../.env');
53-
const env = { ...process.env };
54-
if (fs.existsSync(envPath)) {
55-
const envContent = fs.readFileSync(envPath, 'utf-8');
56-
envContent.split('\n').forEach(line => {
57-
const trimmed = line.trim();
58-
if (trimmed && !trimmed.startsWith('#')) {
59-
const splitIdx = trimmed.indexOf('=');
60-
if (splitIdx !== -1) {
61-
const key = trimmed.slice(0, splitIdx).trim();
62-
let value = trimmed.slice(splitIdx + 1).trim();
63-
value = value.replace(/(^['"]|['"]$)/g, '');
64-
if (env[key] === undefined) {
65-
env[key] = value;
66-
}
67-
}
68-
}
69-
});
62+
function prepareEnvironment() {
63+
let env = { ...process.env };
64+
let userAgent = "skills";
65+
if (process.env.GEMINI_CLI === '1') {
66+
userAgent = "skills-geminicli";
67+
} else if (process.env.CLAUDECODE === '1') {
68+
userAgent = "skills-claudecode";
69+
} else if (process.env.CODEX_CI === '1') {
70+
userAgent = "skills-codex";
7071
}
71-
return env;
72-
}
72+
mergeEnvVars(env);
73+
74+
OPTIONAL_VARS_TO_OMIT_IF_EMPTY.forEach(varName => {
75+
if (env[varName] === '') {
76+
delete env[varName];
77+
}
78+
});
79+
7380

74-
let env = process.env;
75-
let userAgent = "skills";
76-
if (process.env.GEMINI_CLI === '1') {
77-
env = getEnv();
78-
userAgent = "skills-geminicli";
81+
return { env, userAgent };
7982
}
8083

81-
const args = process.argv.slice(2);
84+
function main() {
85+
const { env, userAgent } = prepareEnvironment();
86+
const args = process.argv.slice(2);
87+
88+
const command = os.platform() === 'win32' ? 'npx.cmd' : 'npx';
89+
const processedArgs = os.platform() === 'win32' ? args.map(arg => arg.includes('"') ? '"' + arg.replace(/"/g, '""') + '"' : arg) : args;
90+
const npxArgs = ["--yes", "@toolbox-sdk/server@1.0.0", "--log-level", "error", ...configArgs, "invoke", toolName, "--user-agent-metadata", userAgent, ...processedArgs];
8291

83-
const toolboxArgs = ["--log-level", "error", ...configArgs, "invoke", toolName, "--user-agent-metadata", userAgent, ...args];
92+
const child = spawn(command, npxArgs, { shell: os.platform() === 'win32', stdio: 'inherit', env });
93+
8494

85-
const child = spawn(toolboxBinary, toolboxArgs, { stdio: 'inherit', env });
95+
child.on('close', (code) => {
96+
process.exit(code);
97+
});
8698

87-
child.on('close', (code) => {
88-
process.exit(code);
89-
});
99+
child.on('error', (err) => {
100+
console.error("Error executing toolbox:", err);
101+
process.exit(1);
102+
});
103+
}
90104

91-
child.on('error', (err) => {
92-
console.error("Error executing toolbox:", err);
93-
process.exit(1);
94-
});
105+
main();

0 commit comments

Comments
 (0)