mlgym-deploy 2.7.0 → 2.8.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/index.js +106 -13
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -17,7 +17,7 @@ import crypto from 'crypto';
|
|
|
17
17
|
const execAsync = promisify(exec);
|
|
18
18
|
|
|
19
19
|
// Current version of this MCP server - INCREMENT FOR WORKFLOW FIXES
|
|
20
|
-
const CURRENT_VERSION = '2.
|
|
20
|
+
const CURRENT_VERSION = '2.8.0'; // Fixed to match CLI workflow: nested API payload, git push, deployment monitoring
|
|
21
21
|
const PACKAGE_NAME = 'mlgym-deploy';
|
|
22
22
|
|
|
23
23
|
// Version check state
|
|
@@ -945,15 +945,26 @@ async function initProject(args) {
|
|
|
945
945
|
|
|
946
946
|
console.error(`Creating project: ${name}`);
|
|
947
947
|
|
|
948
|
-
// Create project via backend API
|
|
948
|
+
// Create project via backend API with CORRECT nested structure (matching CLI)
|
|
949
949
|
const projectData = {
|
|
950
950
|
name: name,
|
|
951
|
-
description: description
|
|
952
|
-
enable_deployment: enable_deployment
|
|
951
|
+
description: description
|
|
953
952
|
};
|
|
954
953
|
|
|
955
|
-
if (enable_deployment
|
|
956
|
-
|
|
954
|
+
if (enable_deployment) {
|
|
955
|
+
// Generate a secure webhook secret for deployments
|
|
956
|
+
const webhookSecret = Array.from(
|
|
957
|
+
crypto.getRandomValues(new Uint8Array(32)),
|
|
958
|
+
byte => byte.toString(16).padStart(2, '0')
|
|
959
|
+
).join('');
|
|
960
|
+
|
|
961
|
+
// Use nested deployment_info structure like CLI does
|
|
962
|
+
projectData.deployment_info = {
|
|
963
|
+
type: 'dockerfile',
|
|
964
|
+
enabled: true,
|
|
965
|
+
webhook_secret: webhookSecret,
|
|
966
|
+
hostname: hostname
|
|
967
|
+
};
|
|
957
968
|
}
|
|
958
969
|
|
|
959
970
|
const result = await apiRequest('POST', '/api/v1/projects', projectData, true);
|
|
@@ -992,12 +1003,92 @@ async function initProject(args) {
|
|
|
992
1003
|
|
|
993
1004
|
await execAsync(`git remote add mlgym ${gitUrl}`, { cwd: absolutePath });
|
|
994
1005
|
|
|
1006
|
+
// Create initial commit and push (like CLI does)
|
|
1007
|
+
const gitSteps = [];
|
|
1008
|
+
|
|
1009
|
+
try {
|
|
1010
|
+
// Check if there are any files to commit
|
|
1011
|
+
const { stdout: statusOutput } = await execAsync('git status --porcelain', { cwd: absolutePath });
|
|
1012
|
+
|
|
1013
|
+
if (statusOutput.trim()) {
|
|
1014
|
+
// There are uncommitted changes
|
|
1015
|
+
gitSteps.push('Adding files to git');
|
|
1016
|
+
await execAsync('git add .', { cwd: absolutePath });
|
|
1017
|
+
|
|
1018
|
+
gitSteps.push('Creating initial commit');
|
|
1019
|
+
await execAsync('git commit -m "Initial MLGym deployment"', { cwd: absolutePath });
|
|
1020
|
+
} else {
|
|
1021
|
+
// Check if there are any commits at all
|
|
1022
|
+
try {
|
|
1023
|
+
await execAsync('git rev-parse HEAD', { cwd: absolutePath });
|
|
1024
|
+
gitSteps.push('Repository already has commits');
|
|
1025
|
+
} catch {
|
|
1026
|
+
// No commits yet, create an initial one
|
|
1027
|
+
gitSteps.push('Creating README for initial commit');
|
|
1028
|
+
const readmePath = path.join(absolutePath, 'README.md');
|
|
1029
|
+
if (!await fs.access(readmePath).then(() => true).catch(() => false)) {
|
|
1030
|
+
await fs.writeFile(readmePath, `# ${name}\n\n${description}\n\nDeployed with MLGym\n`);
|
|
1031
|
+
}
|
|
1032
|
+
await execAsync('git add .', { cwd: absolutePath });
|
|
1033
|
+
await execAsync('git commit -m "Initial MLGym deployment"', { cwd: absolutePath });
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
// Push to trigger webhook and deployment
|
|
1038
|
+
gitSteps.push('Pushing to GitLab to trigger deployment');
|
|
1039
|
+
await execAsync('git push -u mlgym main', { cwd: absolutePath });
|
|
1040
|
+
|
|
1041
|
+
} catch (pushError) {
|
|
1042
|
+
console.error('Git operations warning:', pushError.message);
|
|
1043
|
+
gitSteps.push(`Warning: ${pushError.message}`);
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
// Monitor deployment if enabled (like CLI does)
|
|
1047
|
+
let deploymentStatus = null;
|
|
1048
|
+
if (enable_deployment) {
|
|
1049
|
+
console.error('Monitoring deployment status...');
|
|
1050
|
+
|
|
1051
|
+
// Poll for deployment status (up to 60 seconds)
|
|
1052
|
+
for (let i = 0; i < 12; i++) {
|
|
1053
|
+
await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds
|
|
1054
|
+
|
|
1055
|
+
const statusResult = await apiRequest('GET', `/api/v1/projects/${project.id}/deployment`, null, true);
|
|
1056
|
+
if (statusResult.success && statusResult.data) {
|
|
1057
|
+
const status = statusResult.data.status;
|
|
1058
|
+
console.error(`Deployment status: ${status}`);
|
|
1059
|
+
|
|
1060
|
+
if (status === 'deployed' || status === 'running') {
|
|
1061
|
+
deploymentStatus = {
|
|
1062
|
+
status: 'deployed',
|
|
1063
|
+
url: statusResult.data.url || `https://${hostname}.ezb.net`,
|
|
1064
|
+
message: 'Application successfully deployed'
|
|
1065
|
+
};
|
|
1066
|
+
break;
|
|
1067
|
+
} else if (status === 'failed') {
|
|
1068
|
+
deploymentStatus = {
|
|
1069
|
+
status: 'failed',
|
|
1070
|
+
message: 'Deployment failed. Check Coolify logs for details.'
|
|
1071
|
+
};
|
|
1072
|
+
break;
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
if (!deploymentStatus) {
|
|
1078
|
+
deploymentStatus = {
|
|
1079
|
+
status: 'pending',
|
|
1080
|
+
message: 'Deployment is still in progress. Check status later.',
|
|
1081
|
+
expected_url: `https://${hostname}.ezb.net`
|
|
1082
|
+
};
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
|
|
995
1086
|
return {
|
|
996
1087
|
content: [{
|
|
997
1088
|
type: 'text',
|
|
998
1089
|
text: JSON.stringify({
|
|
999
1090
|
status: 'success',
|
|
1000
|
-
message: 'Project created successfully',
|
|
1091
|
+
message: 'Project created and pushed successfully',
|
|
1001
1092
|
project: {
|
|
1002
1093
|
id: project.id,
|
|
1003
1094
|
name: project.name,
|
|
@@ -1006,12 +1097,14 @@ async function initProject(args) {
|
|
|
1006
1097
|
deployment_enabled: enable_deployment,
|
|
1007
1098
|
deployment_url: hostname ? `https://${hostname}.ezb.net` : null
|
|
1008
1099
|
},
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
'git push mlgym main'
|
|
1014
|
-
|
|
1100
|
+
git_operations: gitSteps,
|
|
1101
|
+
deployment: deploymentStatus,
|
|
1102
|
+
next_steps: enable_deployment && deploymentStatus?.status === 'deployed' ? [
|
|
1103
|
+
`✅ Your application is live at: ${deploymentStatus.url}`,
|
|
1104
|
+
'Future updates: git push mlgym main'
|
|
1105
|
+
] : [
|
|
1106
|
+
'To update: git push mlgym main',
|
|
1107
|
+
enable_deployment ? 'Deployment will trigger automatically' : null
|
|
1015
1108
|
].filter(Boolean)
|
|
1016
1109
|
}, null, 2)
|
|
1017
1110
|
}]
|