init project
This commit is contained in:
Vendored
+97
@@ -0,0 +1,97 @@
|
||||
import fs from 'node:fs';
|
||||
import { z } from 'zod';
|
||||
import { config } from '../../config.js';
|
||||
import { resolveWorkspacePath } from '../../lib/sandbox.js';
|
||||
import { runCommand } from '../../lib/runCommand.js';
|
||||
import { errorResult, jsonResult, targetSchema, toErrorMessage } from '../shared.js';
|
||||
/**
|
||||
* Deploy is deliberately opt-in and project-defined: rather than guessing at
|
||||
* Vercel/Netlify/Forge credentials, it runs a script the project itself
|
||||
* defines (deploy.ps1 on Windows, deploy.sh elsewhere) at the workspace
|
||||
* root. Optionally pushes a Docker image when registryPush is set.
|
||||
*/
|
||||
export function registerDeployProjectTool(server) {
|
||||
server.registerTool('deploy_project', {
|
||||
title: 'Deploy Project',
|
||||
description: 'Run the project-defined deploy step: deploy.ps1 (Windows) or deploy.sh (macOS/Linux) at the workspace root. ' +
|
||||
'Requires confirm: true. Optional registryPush runs `docker push` after the deploy script (also confirm-gated). ' +
|
||||
'The server never holds deployment credentials itself.',
|
||||
inputSchema: {
|
||||
target: targetSchema,
|
||||
confirm: z
|
||||
.boolean()
|
||||
.optional()
|
||||
.describe('Must be true; deliberate opt-in for a destructive/external-effect operation.'),
|
||||
registryPush: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe('Optional Docker image reference to push after the deploy script succeeds.'),
|
||||
},
|
||||
}, async ({ confirm, target, registryPush }) => {
|
||||
void target;
|
||||
if (confirm !== true)
|
||||
return errorResult('confirm: true is required to run deploy_project.');
|
||||
try {
|
||||
let deployResult;
|
||||
if (process.platform === 'win32') {
|
||||
const scriptPath = resolveWorkspacePath(config.workspaceRoot, 'deploy.ps1');
|
||||
if (!fs.existsSync(scriptPath)) {
|
||||
return errorResult(`No deploy.ps1 found at the workspace root (${config.workspaceRoot}). Add one that performs your deployment, then retry.`);
|
||||
}
|
||||
const result = await runCommand('powershell', ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', scriptPath], { cwd: config.workspaceRoot, timeoutMs: config.scaffoldCommandTimeoutMs });
|
||||
deployResult = {
|
||||
ranScript: 'deploy.ps1',
|
||||
exitCode: result.exitCode,
|
||||
timedOut: result.timedOut,
|
||||
failed: result.failed,
|
||||
output: result.output,
|
||||
cwd: result.cwd,
|
||||
};
|
||||
if (result.failed)
|
||||
return jsonResult({ ...deployResult, registryPush: null });
|
||||
}
|
||||
else {
|
||||
const scriptPath = resolveWorkspacePath(config.workspaceRoot, 'deploy.sh');
|
||||
if (!fs.existsSync(scriptPath)) {
|
||||
return errorResult(`No deploy.sh found at the workspace root (${config.workspaceRoot}). Add one that performs your deployment, then retry.`);
|
||||
}
|
||||
const result = await runCommand('sh', [scriptPath], {
|
||||
cwd: config.workspaceRoot,
|
||||
timeoutMs: config.scaffoldCommandTimeoutMs,
|
||||
});
|
||||
deployResult = {
|
||||
ranScript: 'deploy.sh',
|
||||
exitCode: result.exitCode,
|
||||
timedOut: result.timedOut,
|
||||
failed: result.failed,
|
||||
output: result.output,
|
||||
cwd: result.cwd,
|
||||
};
|
||||
if (result.failed)
|
||||
return jsonResult({ ...deployResult, registryPush: null });
|
||||
}
|
||||
let pushResult = null;
|
||||
if (registryPush) {
|
||||
if (registryPush.includes('--force') || /\s/.test(registryPush)) {
|
||||
return errorResult('Invalid registryPush image reference.');
|
||||
}
|
||||
const pushed = await runCommand('docker', ['push', registryPush], {
|
||||
cwd: config.workspaceRoot,
|
||||
timeoutMs: config.scaffoldCommandTimeoutMs,
|
||||
});
|
||||
pushResult = {
|
||||
image: registryPush,
|
||||
exitCode: pushed.exitCode,
|
||||
failed: pushed.failed,
|
||||
timedOut: pushed.timedOut,
|
||||
output: pushed.output,
|
||||
};
|
||||
}
|
||||
return jsonResult({ ...deployResult, registryPush: pushResult });
|
||||
}
|
||||
catch (error) {
|
||||
return errorResult(toErrorMessage(error));
|
||||
}
|
||||
});
|
||||
}
|
||||
//# sourceMappingURL=deployProject.js.map
|
||||
Reference in New Issue
Block a user