@google-cloud/cloud-run-mcp 1.0.0 → 1.3.0
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/.github/workflows/local-tests.yml +17 -0
- package/.github/workflows/npm-publish.yml +23 -0
- package/CONTRIBUTING.md +14 -0
- package/README.md +8 -7
- package/gemini-extension/GEMINI.md +57 -0
- package/gemini-extension.json +3 -2
- package/lib/cloud-run-deploy.js +90 -107
- package/lib/cloud-run-services.js +16 -4
- package/lib/gcp-api-helpers.js +143 -0
- package/lib/gcp-auth-check.js +4 -4
- package/lib/gcp-projects.js +1 -1
- package/mcp-server.js +5 -2
- package/package.json +9 -9
- package/test/local/gemini-extension.test.js +35 -0
- package/test/local/npx.test.js +36 -0
- package/test/{test-prompts.js → local/prompts.test.js} +1 -1
- package/test/{test-tools.js → local/tools.test.js} +62 -31
- package/test/{test-deploy.js → need-gcp/cloud-run-deploy.test.js} +1 -1
- package/test/{test-service-logs.js → need-gcp/cloud-run-services.test.js} +1 -1
- package/test/{test-gcp-auth.js → need-gcp/gcp-auth-check.test.js} +17 -106
- package/test/{test-create-project.js → need-gcp/gcp-projects.test.js} +1 -1
- package/tools.js +215 -182
- package/test/run-all-tests.js +0 -19
- /package/test/{test-mcp-server.js → local/mcp-server.test.js} +0 -0
package/lib/gcp-auth-check.js
CHANGED
|
@@ -19,10 +19,9 @@ import { GoogleAuth } from 'google-auth-library';
|
|
|
19
19
|
/**
|
|
20
20
|
* Checks for the presence of properly setup Google Cloud Platform (GCP) authentication
|
|
21
21
|
* using the official Google Auth Library for Node.js. If GCP auth is not found, it logs an
|
|
22
|
-
* error message and
|
|
23
|
-
* This check is primarily for local/stdio environments where explicit setup is often needed.
|
|
22
|
+
* error message and returns false.
|
|
24
23
|
* @async
|
|
25
|
-
* @returns {Promise<
|
|
24
|
+
* @returns {Promise<boolean>} A promise that resolves to true if GCP auth are found, and false otherwise.
|
|
26
25
|
*/
|
|
27
26
|
export async function ensureGCPCredentials() {
|
|
28
27
|
console.error('Checking for Google Cloud Application Default Credentials...');
|
|
@@ -35,6 +34,7 @@ export async function ensureGCPCredentials() {
|
|
|
35
34
|
await client.getAccessToken();
|
|
36
35
|
|
|
37
36
|
console.log('Application Default Credentials found.');
|
|
37
|
+
return true;
|
|
38
38
|
} catch (error) {
|
|
39
39
|
console.error(
|
|
40
40
|
'ERROR: Google Cloud Application Default Credentials are not set up.'
|
|
@@ -74,6 +74,6 @@ export async function ensureGCPCredentials() {
|
|
|
74
74
|
if (error.stack) {
|
|
75
75
|
console.error('Error stack:', error.stack);
|
|
76
76
|
}
|
|
77
|
-
|
|
77
|
+
return false;
|
|
78
78
|
}
|
|
79
79
|
}
|
package/lib/gcp-projects.js
CHANGED
|
@@ -72,7 +72,7 @@ export async function createProject(projectId) {
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
try {
|
|
75
|
-
const projectPayload = { projectId: projectIdToUse
|
|
75
|
+
const projectPayload = { projectId: projectIdToUse };
|
|
76
76
|
|
|
77
77
|
console.log(`Attempting to create project with ID: ${projectIdToUse}`);
|
|
78
78
|
|
package/mcp-server.js
CHANGED
|
@@ -30,6 +30,7 @@ import { ensureGCPCredentials } from './lib/gcp-auth-check.js';
|
|
|
30
30
|
import 'dotenv/config';
|
|
31
31
|
|
|
32
32
|
const gcpInfo = await checkGCP();
|
|
33
|
+
let gcpCredentialsAvailable = false;
|
|
33
34
|
|
|
34
35
|
/**
|
|
35
36
|
* Ensure that console.log and console.error are compatible with stdio.
|
|
@@ -52,7 +53,6 @@ function shouldStartStdio() {
|
|
|
52
53
|
|
|
53
54
|
if (shouldStartStdio()) {
|
|
54
55
|
makeLoggingCompatibleWithStdio();
|
|
55
|
-
await ensureGCPCredentials();
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
// Read default configurations from environment variables
|
|
@@ -88,6 +88,7 @@ async function getServer() {
|
|
|
88
88
|
defaultRegion: effectiveRegion,
|
|
89
89
|
defaultServiceName,
|
|
90
90
|
skipIamCheck,
|
|
91
|
+
gcpCredentialsAvailable,
|
|
91
92
|
});
|
|
92
93
|
} else {
|
|
93
94
|
console.log(
|
|
@@ -99,6 +100,7 @@ async function getServer() {
|
|
|
99
100
|
defaultRegion: effectiveRegion,
|
|
100
101
|
defaultServiceName,
|
|
101
102
|
skipIamCheck,
|
|
103
|
+
gcpCredentialsAvailable,
|
|
102
104
|
});
|
|
103
105
|
}
|
|
104
106
|
|
|
@@ -110,13 +112,14 @@ async function getServer() {
|
|
|
110
112
|
|
|
111
113
|
// stdio
|
|
112
114
|
if (shouldStartStdio()) {
|
|
115
|
+
gcpCredentialsAvailable = await ensureGCPCredentials();
|
|
113
116
|
const stdioTransport = new StdioServerTransport();
|
|
114
117
|
const server = await getServer();
|
|
115
118
|
await server.connect(stdioTransport);
|
|
116
119
|
console.log('Cloud Run MCP server stdio transport connected');
|
|
117
120
|
} else {
|
|
118
121
|
console.log('Running on GCP, stdio transport will not be started.');
|
|
119
|
-
await ensureGCPCredentials();
|
|
122
|
+
gcpCredentialsAvailable = await ensureGCPCredentials();
|
|
120
123
|
const app = express();
|
|
121
124
|
app.use(express.json());
|
|
122
125
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@google-cloud/cloud-run-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Cloud Run MCP deployment tool",
|
|
6
6
|
"main": "mcp-server.js",
|
|
@@ -9,14 +9,14 @@
|
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
11
|
"deploy": "gcloud run deploy cloud-run-mcp --source . --no-invoker-iam-check",
|
|
12
|
-
"test:deploy": "node test/
|
|
13
|
-
"test:create-project": "node test/
|
|
14
|
-
"test:service-logs": "node test/
|
|
15
|
-
"test:gcp-auth": "node test/
|
|
16
|
-
"test:prompts": "node --test test/
|
|
17
|
-
"test:mcp": "node --test test/
|
|
18
|
-
"test:tools": "node --test test/
|
|
19
|
-
"test": "node test/
|
|
12
|
+
"test:deploy": "node test/need-gcp/cloud-run-deploy.test.js",
|
|
13
|
+
"test:create-project": "node test/need-gcp/gcp-projects.test.js",
|
|
14
|
+
"test:service-logs": "node test/need-gcp/cloud-run-services.test.js",
|
|
15
|
+
"test:gcp-auth": "node test/need-gcp/gcp-auth-check.test.js",
|
|
16
|
+
"test:prompts": "node --test test/local/prompts.test.js",
|
|
17
|
+
"test:mcp": "node --test test/local/mcp-server.test.js",
|
|
18
|
+
"test:tools": "node --test test/local/tools.test.js",
|
|
19
|
+
"test": "node --test test/local/*.test.js",
|
|
20
20
|
"mcp-inspector": "npx @modelcontextprotocol/inspector node mcp-server.js",
|
|
21
21
|
"start": "node mcp-server.js",
|
|
22
22
|
"lint:check": "prettier --check .",
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { test, describe } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
const rootDir = path.resolve(__dirname, '..', '..');
|
|
10
|
+
const geminiExtensionJsonPath = path.resolve(rootDir, 'gemini-extension.json');
|
|
11
|
+
|
|
12
|
+
describe('Gemini CLI extension', () => {
|
|
13
|
+
test('gemini-extension.json should be at the root', () => {
|
|
14
|
+
assert.ok(
|
|
15
|
+
fs.existsSync(geminiExtensionJsonPath),
|
|
16
|
+
'gemini-extension.json not found at the project root'
|
|
17
|
+
);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('contextFileName from gemini-extension.json should exist', () => {
|
|
21
|
+
const geminiExtensionJson = JSON.parse(
|
|
22
|
+
fs.readFileSync(geminiExtensionJsonPath, 'utf-8')
|
|
23
|
+
);
|
|
24
|
+
const contextFileName = geminiExtensionJson.contextFileName;
|
|
25
|
+
assert.ok(
|
|
26
|
+
contextFileName,
|
|
27
|
+
'contextFileName not found in gemini-extension.json'
|
|
28
|
+
);
|
|
29
|
+
const contextFilePath = path.resolve(rootDir, contextFileName);
|
|
30
|
+
assert.ok(
|
|
31
|
+
fs.existsSync(contextFilePath),
|
|
32
|
+
`context file name '${contextFileName}' not found`
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { test, describe } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
const packageJsonPath = path.resolve(__dirname, '..', '..', 'package.json');
|
|
10
|
+
const mcpServerPath = path.resolve(__dirname, '..', '..', 'mcp-server.js');
|
|
11
|
+
|
|
12
|
+
describe('The repository is properly structured to be executed using npx', () => {
|
|
13
|
+
test('package.json should be at the root', () => {
|
|
14
|
+
assert.ok(
|
|
15
|
+
fs.existsSync(packageJsonPath),
|
|
16
|
+
'package.json not found at the project root'
|
|
17
|
+
);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('package.json should have a bin attribute for cloud-run-mcp', () => {
|
|
21
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
22
|
+
assert.ok(packageJson.bin, 'bin attribute not found in package.json');
|
|
23
|
+
assert.ok(
|
|
24
|
+
packageJson.bin['cloud-run-mcp'],
|
|
25
|
+
'cloud-run-mcp not found in bin attribute'
|
|
26
|
+
);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('mcp-server.js should start with #!/usr/bin/env node', () => {
|
|
30
|
+
const mcpServerContent = fs.readFileSync(mcpServerPath, 'utf-8');
|
|
31
|
+
assert.ok(
|
|
32
|
+
mcpServerContent.startsWith('#!/usr/bin/env node'),
|
|
33
|
+
'mcp-server.js does not start with #!/usr/bin/env node'
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -16,7 +16,7 @@ limitations under the License.
|
|
|
16
16
|
|
|
17
17
|
import assert from 'node:assert/strict';
|
|
18
18
|
import { describe, it, mock } from 'node:test';
|
|
19
|
-
import { registerPrompts } from '
|
|
19
|
+
import { registerPrompts } from '../../prompts.js';
|
|
20
20
|
|
|
21
21
|
describe('registerPrompts', () => {
|
|
22
22
|
it('should register deploy and logs prompts', () => {
|
|
@@ -8,7 +8,7 @@ describe('registerTools', () => {
|
|
|
8
8
|
registerTool: mock.fn(),
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
const { registerTools } = await esmock('
|
|
11
|
+
const { registerTools } = await esmock('../../tools.js', {});
|
|
12
12
|
|
|
13
13
|
registerTools(server);
|
|
14
14
|
|
|
@@ -38,14 +38,14 @@ describe('registerTools', () => {
|
|
|
38
38
|
registerTool: mock.fn(),
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
const { registerTools } = await esmock('
|
|
42
|
-
'
|
|
41
|
+
const { registerTools } = await esmock('../../tools.js', {
|
|
42
|
+
'../../lib/gcp-projects.js': {
|
|
43
43
|
listProjects: () =>
|
|
44
44
|
Promise.resolve([{ id: 'project1' }, { id: 'project2' }]),
|
|
45
45
|
},
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
registerTools(server);
|
|
48
|
+
registerTools(server, { gcpCredentialsAvailable: true });
|
|
49
49
|
|
|
50
50
|
const handler = server.registerTool.mock.calls.find(
|
|
51
51
|
(call) => call.arguments[0] === 'list_projects'
|
|
@@ -69,8 +69,8 @@ describe('registerTools', () => {
|
|
|
69
69
|
registerTool: mock.fn(),
|
|
70
70
|
};
|
|
71
71
|
|
|
72
|
-
const { registerTools } = await esmock('
|
|
73
|
-
'
|
|
72
|
+
const { registerTools } = await esmock('../../tools.js', {
|
|
73
|
+
'../../lib/gcp-projects.js': {
|
|
74
74
|
createProjectAndAttachBilling: (projectId) =>
|
|
75
75
|
Promise.resolve({
|
|
76
76
|
projectId: projectId,
|
|
@@ -79,7 +79,7 @@ describe('registerTools', () => {
|
|
|
79
79
|
},
|
|
80
80
|
});
|
|
81
81
|
|
|
82
|
-
registerTools(server);
|
|
82
|
+
registerTools(server, { gcpCredentialsAvailable: true });
|
|
83
83
|
|
|
84
84
|
const handler = server.registerTool.mock.calls.find(
|
|
85
85
|
(call) => call.arguments[0] === 'create_project'
|
|
@@ -101,8 +101,8 @@ describe('registerTools', () => {
|
|
|
101
101
|
registerTool: mock.fn(),
|
|
102
102
|
};
|
|
103
103
|
|
|
104
|
-
const { registerTools } = await esmock('
|
|
105
|
-
'
|
|
104
|
+
const { registerTools } = await esmock('../../tools.js', {
|
|
105
|
+
'../../lib/gcp-projects.js': {
|
|
106
106
|
createProjectAndAttachBilling: () =>
|
|
107
107
|
Promise.resolve({
|
|
108
108
|
projectId: 'generated-project',
|
|
@@ -111,7 +111,7 @@ describe('registerTools', () => {
|
|
|
111
111
|
},
|
|
112
112
|
});
|
|
113
113
|
|
|
114
|
-
registerTools(server);
|
|
114
|
+
registerTools(server, { gcpCredentialsAvailable: true });
|
|
115
115
|
|
|
116
116
|
const handler = server.registerTool.mock.calls.find(
|
|
117
117
|
(call) => call.arguments[0] === 'create_project'
|
|
@@ -135,8 +135,8 @@ describe('registerTools', () => {
|
|
|
135
135
|
registerTool: mock.fn(),
|
|
136
136
|
};
|
|
137
137
|
|
|
138
|
-
const { registerTools } = await esmock('
|
|
139
|
-
'
|
|
138
|
+
const { registerTools } = await esmock('../../tools.js', {
|
|
139
|
+
'../../lib/cloud-run-services.js': {
|
|
140
140
|
listServices: () =>
|
|
141
141
|
Promise.resolve([
|
|
142
142
|
{ name: 'service1', uri: 'uri1' },
|
|
@@ -145,7 +145,7 @@ describe('registerTools', () => {
|
|
|
145
145
|
},
|
|
146
146
|
});
|
|
147
147
|
|
|
148
|
-
registerTools(server);
|
|
148
|
+
registerTools(server, { gcpCredentialsAvailable: true });
|
|
149
149
|
|
|
150
150
|
const handler = server.registerTool.mock.calls.find(
|
|
151
151
|
(call) => call.arguments[0] === 'list_services'
|
|
@@ -172,8 +172,8 @@ describe('registerTools', () => {
|
|
|
172
172
|
registerTool: mock.fn(),
|
|
173
173
|
};
|
|
174
174
|
|
|
175
|
-
const { registerTools } = await esmock('
|
|
176
|
-
'
|
|
175
|
+
const { registerTools } = await esmock('../../tools.js', {
|
|
176
|
+
'../../lib/cloud-run-services.js': {
|
|
177
177
|
getService: () =>
|
|
178
178
|
Promise.resolve({
|
|
179
179
|
name: 'my-service',
|
|
@@ -183,7 +183,7 @@ describe('registerTools', () => {
|
|
|
183
183
|
},
|
|
184
184
|
});
|
|
185
185
|
|
|
186
|
-
registerTools(server);
|
|
186
|
+
registerTools(server, { gcpCredentialsAvailable: true });
|
|
187
187
|
|
|
188
188
|
const handler = server.registerTool.mock.calls.find(
|
|
189
189
|
(call) => call.arguments[0] === 'get_service'
|
|
@@ -223,13 +223,13 @@ describe('registerTools', () => {
|
|
|
223
223
|
return Promise.resolve({ logs: 'log3\nlog4', requestOptions: null });
|
|
224
224
|
};
|
|
225
225
|
|
|
226
|
-
const { registerTools } = await esmock('
|
|
227
|
-
'
|
|
226
|
+
const { registerTools } = await esmock('../../tools.js', {
|
|
227
|
+
'../../lib/cloud-run-services.js': {
|
|
228
228
|
getServiceLogs: getServiceLogs,
|
|
229
229
|
},
|
|
230
230
|
});
|
|
231
231
|
|
|
232
|
-
registerTools(server);
|
|
232
|
+
registerTools(server, { gcpCredentialsAvailable: true });
|
|
233
233
|
|
|
234
234
|
const handler = server.registerTool.mock.calls.find(
|
|
235
235
|
(call) => call.arguments[0] === 'get_service_log'
|
|
@@ -257,13 +257,13 @@ describe('registerTools', () => {
|
|
|
257
257
|
registerTool: mock.fn(),
|
|
258
258
|
};
|
|
259
259
|
|
|
260
|
-
const { registerTools } = await esmock('
|
|
261
|
-
'
|
|
260
|
+
const { registerTools } = await esmock('../../tools.js', {
|
|
261
|
+
'../../lib/cloud-run-deploy.js': {
|
|
262
262
|
deploy: () => Promise.resolve({ uri: 'my-uri' }),
|
|
263
263
|
},
|
|
264
264
|
});
|
|
265
265
|
|
|
266
|
-
registerTools(server);
|
|
266
|
+
registerTools(server, { gcpCredentialsAvailable: true });
|
|
267
267
|
|
|
268
268
|
const handler = server.registerTool.mock.calls.find(
|
|
269
269
|
(call) => call.arguments[0] === 'deploy_local_files'
|
|
@@ -292,13 +292,13 @@ describe('registerTools', () => {
|
|
|
292
292
|
registerTool: mock.fn(),
|
|
293
293
|
};
|
|
294
294
|
|
|
295
|
-
const { registerTools } = await esmock('
|
|
296
|
-
'
|
|
295
|
+
const { registerTools } = await esmock('../../tools.js', {
|
|
296
|
+
'../../lib/cloud-run-deploy.js': {
|
|
297
297
|
deploy: () => Promise.resolve({ uri: 'my-uri' }),
|
|
298
298
|
},
|
|
299
299
|
});
|
|
300
300
|
|
|
301
|
-
registerTools(server);
|
|
301
|
+
registerTools(server, { gcpCredentialsAvailable: true });
|
|
302
302
|
|
|
303
303
|
const handler = server.registerTool.mock.calls.find(
|
|
304
304
|
(call) => call.arguments[0] === 'deploy_local_folder'
|
|
@@ -327,13 +327,13 @@ describe('registerTools', () => {
|
|
|
327
327
|
registerTool: mock.fn(),
|
|
328
328
|
};
|
|
329
329
|
|
|
330
|
-
const { registerTools } = await esmock('
|
|
331
|
-
'
|
|
330
|
+
const { registerTools } = await esmock('../../tools.js', {
|
|
331
|
+
'../../lib/cloud-run-deploy.js': {
|
|
332
332
|
deploy: () => Promise.resolve({ uri: 'my-uri' }),
|
|
333
333
|
},
|
|
334
334
|
});
|
|
335
335
|
|
|
336
|
-
registerTools(server);
|
|
336
|
+
registerTools(server, { gcpCredentialsAvailable: true });
|
|
337
337
|
|
|
338
338
|
const handler = server.registerTool.mock.calls.find(
|
|
339
339
|
(call) => call.arguments[0] === 'deploy_file_contents'
|
|
@@ -362,13 +362,13 @@ describe('registerTools', () => {
|
|
|
362
362
|
registerTool: mock.fn(),
|
|
363
363
|
};
|
|
364
364
|
|
|
365
|
-
const { registerTools } = await esmock('
|
|
366
|
-
'
|
|
365
|
+
const { registerTools } = await esmock('../../tools.js', {
|
|
366
|
+
'../../lib/cloud-run-deploy.js': {
|
|
367
367
|
deployImage: () => Promise.resolve({ uri: 'my-uri' }),
|
|
368
368
|
},
|
|
369
369
|
});
|
|
370
370
|
|
|
371
|
-
registerTools(server);
|
|
371
|
+
registerTools(server, { gcpCredentialsAvailable: true });
|
|
372
372
|
|
|
373
373
|
const handler = server.registerTool.mock.calls.find(
|
|
374
374
|
(call) => call.arguments[0] === 'deploy_container_image'
|
|
@@ -390,4 +390,35 @@ describe('registerTools', () => {
|
|
|
390
390
|
});
|
|
391
391
|
});
|
|
392
392
|
});
|
|
393
|
+
|
|
394
|
+
describe('when gcp credentials are not available', () => {
|
|
395
|
+
it('should return an error for all tools', async () => {
|
|
396
|
+
const server = {
|
|
397
|
+
registerTool: mock.fn(),
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
const { registerTools } = await esmock('../../tools.js', {});
|
|
401
|
+
|
|
402
|
+
registerTools(server, { gcpCredentialsAvailable: false });
|
|
403
|
+
|
|
404
|
+
const toolNames = server.registerTool.mock.calls.map(
|
|
405
|
+
(call) => call.arguments[0]
|
|
406
|
+
);
|
|
407
|
+
|
|
408
|
+
for (const toolName of toolNames) {
|
|
409
|
+
const handler = server.registerTool.mock.calls.find(
|
|
410
|
+
(call) => call.arguments[0] === toolName
|
|
411
|
+
).arguments[2];
|
|
412
|
+
const result = await handler({});
|
|
413
|
+
assert.deepStrictEqual(result, {
|
|
414
|
+
content: [
|
|
415
|
+
{
|
|
416
|
+
type: 'text',
|
|
417
|
+
text: 'GCP credentials are not available. Please configure your environment.',
|
|
418
|
+
},
|
|
419
|
+
],
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
});
|
|
393
424
|
});
|
|
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { deploy, deployImage } from '
|
|
17
|
+
import { deploy, deployImage } from '../../lib/cloud-run-deploy.js';
|
|
18
18
|
import readline from 'readline/promises';
|
|
19
19
|
import { stdin as input, stdout as output } from 'process';
|
|
20
20
|
import fs from 'fs/promises';
|
|
@@ -16,7 +16,7 @@ limitations under the License.
|
|
|
16
16
|
|
|
17
17
|
import readline from 'readline/promises';
|
|
18
18
|
import { stdin as input, stdout as output } from 'process';
|
|
19
|
-
import { getServiceLogs } from '
|
|
19
|
+
import { getServiceLogs } from '../../lib/cloud-run-services.js';
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* Prompts the user for required service information
|