@deinossrl/dgp-agent 1.0.0 → 1.2.5
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.mjs +345 -22
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* DGP Agent - Agente local para Despliegue-GPT
|
|
4
|
-
* @
|
|
4
|
+
* @deinossrl/dgp-agent
|
|
5
5
|
*
|
|
6
6
|
* Este agente corre en la máquina del desarrollador y:
|
|
7
7
|
* 1. Reporta el estado del repositorio git a la plataforma TenMinute IA
|
|
8
|
-
* 2.
|
|
8
|
+
* 2. Ejecuta comandos de deploy enviados desde la plataforma
|
|
9
9
|
*
|
|
10
10
|
* Instalación:
|
|
11
|
-
* npm install -g @
|
|
11
|
+
* npm install -g @deinossrl/dgp-agent
|
|
12
12
|
*
|
|
13
13
|
* Uso:
|
|
14
14
|
* dgp-agent # Inicia el agente (reporta cada 30s)
|
|
15
15
|
* dgp-agent status # Muestra estado una vez
|
|
16
|
+
* dgp-agent deploy # Modo deploy (escucha comandos)
|
|
16
17
|
* dgp-agent help # Muestra ayuda
|
|
17
18
|
*
|
|
18
19
|
* Variables de entorno:
|
|
@@ -22,13 +23,16 @@
|
|
|
22
23
|
* DGP_MACHINE_ID ID personalizado de la máquina
|
|
23
24
|
*/
|
|
24
25
|
|
|
25
|
-
import { execSync } from 'child_process';
|
|
26
|
+
import { execSync, spawn } from 'child_process';
|
|
26
27
|
import { hostname } from 'os';
|
|
27
28
|
|
|
28
29
|
// Configuración
|
|
29
30
|
const CONFIG = {
|
|
30
31
|
apiUrl: process.env.DGP_API_URL || 'https://asivayhbrqennwiwttds.supabase.co/functions/v1/dgp-agent-status',
|
|
32
|
+
commandsUrl: process.env.DGP_COMMANDS_URL || 'https://asivayhbrqennwiwttds.supabase.co/rest/v1/dgp_agent_commands',
|
|
33
|
+
supabaseKey: process.env.DGP_SUPABASE_KEY || 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImFzaXZheWhicnFlbm53aXd0dGRzIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjczMDAwOTcsImV4cCI6MjA4Mjg3NjA5N30.s3a7dR-dPkEXI7B2lUTUXU69923hhuX6meheNeo5EKA',
|
|
31
34
|
interval: parseInt(process.env.DGP_INTERVAL || '30', 10),
|
|
35
|
+
commandPollInterval: parseInt(process.env.DGP_COMMAND_POLL_INTERVAL || '10', 10),
|
|
32
36
|
machineId: process.env.DGP_MACHINE_ID || `${hostname()}-${process.env.USERNAME || process.env.USER || 'dev'}`,
|
|
33
37
|
authToken: process.env.DGP_AUTH_TOKEN || null,
|
|
34
38
|
};
|
|
@@ -42,6 +46,7 @@ const colors = {
|
|
|
42
46
|
red: '\x1b[31m',
|
|
43
47
|
gray: '\x1b[90m',
|
|
44
48
|
cyan: '\x1b[36m',
|
|
49
|
+
magenta: '\x1b[35m',
|
|
45
50
|
bold: '\x1b[1m',
|
|
46
51
|
};
|
|
47
52
|
|
|
@@ -62,6 +67,10 @@ function logInfo(message) {
|
|
|
62
67
|
log(message, 'blue');
|
|
63
68
|
}
|
|
64
69
|
|
|
70
|
+
function logCommand(message) {
|
|
71
|
+
log(message, 'magenta');
|
|
72
|
+
}
|
|
73
|
+
|
|
65
74
|
/**
|
|
66
75
|
* Ejecuta un comando git y retorna el resultado
|
|
67
76
|
*/
|
|
@@ -76,6 +85,64 @@ function git(command) {
|
|
|
76
85
|
}
|
|
77
86
|
}
|
|
78
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Ejecuta un comando shell y retorna el resultado
|
|
90
|
+
*/
|
|
91
|
+
function shell(command, options = {}) {
|
|
92
|
+
try {
|
|
93
|
+
return execSync(command, {
|
|
94
|
+
encoding: 'utf-8',
|
|
95
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
96
|
+
...options,
|
|
97
|
+
}).trim();
|
|
98
|
+
} catch (error) {
|
|
99
|
+
throw new Error(`Command failed: ${command}\n${error.message}`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Ejecuta un comando shell de forma asíncrona con output en tiempo real
|
|
105
|
+
*/
|
|
106
|
+
function shellAsync(command, options = {}) {
|
|
107
|
+
return new Promise((resolve, reject) => {
|
|
108
|
+
const isWindows = process.platform === 'win32';
|
|
109
|
+
const shellCmd = isWindows ? 'cmd' : '/bin/sh';
|
|
110
|
+
const shellArgs = isWindows ? ['/c', command] : ['-c', command];
|
|
111
|
+
|
|
112
|
+
const proc = spawn(shellCmd, shellArgs, {
|
|
113
|
+
...options,
|
|
114
|
+
stdio: ['inherit', 'pipe', 'pipe'],
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
let stdout = '';
|
|
118
|
+
let stderr = '';
|
|
119
|
+
|
|
120
|
+
proc.stdout.on('data', (data) => {
|
|
121
|
+
const str = data.toString();
|
|
122
|
+
stdout += str;
|
|
123
|
+
process.stdout.write(colors.gray + str + colors.reset);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
proc.stderr.on('data', (data) => {
|
|
127
|
+
const str = data.toString();
|
|
128
|
+
stderr += str;
|
|
129
|
+
process.stderr.write(colors.yellow + str + colors.reset);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
proc.on('close', (code) => {
|
|
133
|
+
if (code === 0) {
|
|
134
|
+
resolve({ stdout, stderr, code });
|
|
135
|
+
} else {
|
|
136
|
+
reject(new Error(`Command exited with code ${code}\n${stderr}`));
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
proc.on('error', (error) => {
|
|
141
|
+
reject(error);
|
|
142
|
+
});
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
79
146
|
/**
|
|
80
147
|
* Verifica si estamos en un repositorio git
|
|
81
148
|
*/
|
|
@@ -169,15 +236,20 @@ async function reportStatus(status) {
|
|
|
169
236
|
const payload = {
|
|
170
237
|
machine_id: CONFIG.machineId,
|
|
171
238
|
timestamp: new Date().toISOString(),
|
|
239
|
+
agent_version: '1.2.5',
|
|
172
240
|
status,
|
|
173
241
|
};
|
|
174
242
|
|
|
175
243
|
const headers = {
|
|
176
244
|
'Content-Type': 'application/json',
|
|
245
|
+
'apikey': CONFIG.supabaseKey,
|
|
177
246
|
};
|
|
178
247
|
|
|
248
|
+
// Usar auth token del usuario si existe, sino usar el anon key
|
|
179
249
|
if (CONFIG.authToken) {
|
|
180
250
|
headers['Authorization'] = `Bearer ${CONFIG.authToken}`;
|
|
251
|
+
} else {
|
|
252
|
+
headers['Authorization'] = `Bearer ${CONFIG.supabaseKey}`;
|
|
181
253
|
}
|
|
182
254
|
|
|
183
255
|
const response = await fetch(CONFIG.apiUrl, {
|
|
@@ -194,6 +266,195 @@ async function reportStatus(status) {
|
|
|
194
266
|
return await response.json();
|
|
195
267
|
}
|
|
196
268
|
|
|
269
|
+
/**
|
|
270
|
+
* Obtiene comandos pendientes de la plataforma
|
|
271
|
+
*/
|
|
272
|
+
async function getPendingCommands() {
|
|
273
|
+
const url = `${CONFIG.commandsUrl}?status=eq.pending&select=*&order=created_at.asc&limit=1`;
|
|
274
|
+
|
|
275
|
+
const response = await fetch(url, {
|
|
276
|
+
headers: {
|
|
277
|
+
'apikey': CONFIG.supabaseKey,
|
|
278
|
+
'Authorization': `Bearer ${CONFIG.supabaseKey}`,
|
|
279
|
+
},
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
if (!response.ok) {
|
|
283
|
+
throw new Error(`Failed to get commands: HTTP ${response.status}`);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return await response.json();
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Actualiza el estado de un comando
|
|
291
|
+
*/
|
|
292
|
+
async function updateCommandStatus(commandId, status, result = {}, errorMessage = null) {
|
|
293
|
+
const payload = {
|
|
294
|
+
status,
|
|
295
|
+
result,
|
|
296
|
+
error_message: errorMessage,
|
|
297
|
+
...(status === 'running' ? { picked_up_at: new Date().toISOString() } : {}),
|
|
298
|
+
...(status === 'success' || status === 'failed' ? { completed_at: new Date().toISOString() } : {}),
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
const url = `${CONFIG.commandsUrl}?id=eq.${commandId}`;
|
|
302
|
+
|
|
303
|
+
const response = await fetch(url, {
|
|
304
|
+
method: 'PATCH',
|
|
305
|
+
headers: {
|
|
306
|
+
'apikey': CONFIG.supabaseKey,
|
|
307
|
+
'Authorization': `Bearer ${CONFIG.supabaseKey}`,
|
|
308
|
+
'Content-Type': 'application/json',
|
|
309
|
+
'Prefer': 'return=minimal',
|
|
310
|
+
},
|
|
311
|
+
body: JSON.stringify(payload),
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
if (!response.ok) {
|
|
315
|
+
throw new Error(`Failed to update command: HTTP ${response.status}`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Ejecuta un comando de deploy
|
|
321
|
+
*/
|
|
322
|
+
async function executeDeploy(command) {
|
|
323
|
+
const { id, environment, branch, server_host, ssh_user, deploy_url } = command;
|
|
324
|
+
|
|
325
|
+
logCommand(`=== Executing Deploy Command ===`);
|
|
326
|
+
logInfo(`Environment: ${environment}`);
|
|
327
|
+
logInfo(`Branch: ${branch}`);
|
|
328
|
+
logInfo(`Server: ${ssh_user}@${server_host}`);
|
|
329
|
+
|
|
330
|
+
const steps = [];
|
|
331
|
+
let currentStep = '';
|
|
332
|
+
|
|
333
|
+
try {
|
|
334
|
+
// Mark as running
|
|
335
|
+
await updateCommandStatus(id, 'running');
|
|
336
|
+
|
|
337
|
+
// Step 1: Git fetch and checkout
|
|
338
|
+
currentStep = 'git_checkout';
|
|
339
|
+
logCommand(`[1/5] Checkout branch ${branch}...`);
|
|
340
|
+
steps.push({ step: currentStep, status: 'running' });
|
|
341
|
+
|
|
342
|
+
await shellAsync(`git fetch origin`);
|
|
343
|
+
await shellAsync(`git checkout ${branch}`);
|
|
344
|
+
await shellAsync(`git pull origin ${branch}`);
|
|
345
|
+
|
|
346
|
+
steps[steps.length - 1].status = 'success';
|
|
347
|
+
logSuccess(`Branch ${branch} updated`);
|
|
348
|
+
|
|
349
|
+
// Step 2: Install dependencies
|
|
350
|
+
currentStep = 'npm_install';
|
|
351
|
+
logCommand(`[2/5] Installing dependencies...`);
|
|
352
|
+
steps.push({ step: currentStep, status: 'running' });
|
|
353
|
+
|
|
354
|
+
await shellAsync(`npm ci`);
|
|
355
|
+
|
|
356
|
+
steps[steps.length - 1].status = 'success';
|
|
357
|
+
logSuccess(`Dependencies installed`);
|
|
358
|
+
|
|
359
|
+
// Step 3: Build
|
|
360
|
+
currentStep = 'npm_build';
|
|
361
|
+
logCommand(`[3/5] Building application...`);
|
|
362
|
+
steps.push({ step: currentStep, status: 'running' });
|
|
363
|
+
|
|
364
|
+
await shellAsync(`npm run build`);
|
|
365
|
+
|
|
366
|
+
steps[steps.length - 1].status = 'success';
|
|
367
|
+
logSuccess(`Build completed`);
|
|
368
|
+
|
|
369
|
+
// Step 4: Deploy via rsync
|
|
370
|
+
currentStep = 'rsync_deploy';
|
|
371
|
+
logCommand(`[4/5] Deploying to server...`);
|
|
372
|
+
steps.push({ step: currentStep, status: 'running' });
|
|
373
|
+
|
|
374
|
+
const deployFolder = environment === 'production'
|
|
375
|
+
? '/var/www/tenminuteia-prod/'
|
|
376
|
+
: '/var/www/tenminuteia-staging/';
|
|
377
|
+
|
|
378
|
+
// Rsync the dist folder
|
|
379
|
+
await shellAsync(`rsync -avz --delete dist/ ${ssh_user}@${server_host}:${deployFolder}`);
|
|
380
|
+
|
|
381
|
+
steps[steps.length - 1].status = 'success';
|
|
382
|
+
logSuccess(`Files deployed to ${server_host}:${deployFolder}`);
|
|
383
|
+
|
|
384
|
+
// Step 5: Reload nginx
|
|
385
|
+
currentStep = 'reload_nginx';
|
|
386
|
+
logCommand(`[5/5] Reloading Nginx...`);
|
|
387
|
+
steps.push({ step: currentStep, status: 'running' });
|
|
388
|
+
|
|
389
|
+
await shellAsync(`ssh ${ssh_user}@${server_host} "sudo nginx -t && sudo systemctl reload nginx"`);
|
|
390
|
+
|
|
391
|
+
steps[steps.length - 1].status = 'success';
|
|
392
|
+
logSuccess(`Nginx reloaded`);
|
|
393
|
+
|
|
394
|
+
// Healthcheck (optional)
|
|
395
|
+
if (deploy_url) {
|
|
396
|
+
logCommand(`Verifying deployment at ${deploy_url}...`);
|
|
397
|
+
try {
|
|
398
|
+
const healthResponse = await fetch(deploy_url);
|
|
399
|
+
if (healthResponse.ok) {
|
|
400
|
+
logSuccess(`Healthcheck passed`);
|
|
401
|
+
} else {
|
|
402
|
+
log(`Healthcheck returned ${healthResponse.status}`, 'yellow');
|
|
403
|
+
}
|
|
404
|
+
} catch (e) {
|
|
405
|
+
log(`Healthcheck failed: ${e.message}`, 'yellow');
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Mark as success
|
|
410
|
+
await updateCommandStatus(id, 'success', { steps, deploy_url });
|
|
411
|
+
|
|
412
|
+
console.log('');
|
|
413
|
+
logSuccess(`=== Deploy to ${environment} completed successfully! ===`);
|
|
414
|
+
console.log('');
|
|
415
|
+
|
|
416
|
+
return { success: true };
|
|
417
|
+
|
|
418
|
+
} catch (error) {
|
|
419
|
+
logError(`Deploy failed at step: ${currentStep}`);
|
|
420
|
+
logError(error.message);
|
|
421
|
+
|
|
422
|
+
steps[steps.length - 1].status = 'failed';
|
|
423
|
+
steps[steps.length - 1].error = error.message;
|
|
424
|
+
|
|
425
|
+
await updateCommandStatus(id, 'failed', { steps }, error.message);
|
|
426
|
+
|
|
427
|
+
return { success: false, error: error.message };
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/**
|
|
432
|
+
* Ejecuta un comando recibido
|
|
433
|
+
*/
|
|
434
|
+
async function executeCommand(command) {
|
|
435
|
+
logCommand(`Received command: ${command.command}`);
|
|
436
|
+
|
|
437
|
+
switch (command.command) {
|
|
438
|
+
case 'deploy':
|
|
439
|
+
return await executeDeploy(command);
|
|
440
|
+
|
|
441
|
+
case 'status':
|
|
442
|
+
const status = getRepoStatus();
|
|
443
|
+
await updateCommandStatus(command.id, 'success', { status });
|
|
444
|
+
return { success: true, status };
|
|
445
|
+
|
|
446
|
+
case 'rollback':
|
|
447
|
+
logError('Rollback not implemented yet');
|
|
448
|
+
await updateCommandStatus(command.id, 'failed', {}, 'Rollback not implemented');
|
|
449
|
+
return { success: false };
|
|
450
|
+
|
|
451
|
+
default:
|
|
452
|
+
logError(`Unknown command: ${command.command}`);
|
|
453
|
+
await updateCommandStatus(command.id, 'failed', {}, `Unknown command: ${command.command}`);
|
|
454
|
+
return { success: false };
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
|
|
197
458
|
/**
|
|
198
459
|
* Muestra el estado en consola
|
|
199
460
|
*/
|
|
@@ -223,11 +484,11 @@ function printStatus(status) {
|
|
|
223
484
|
/**
|
|
224
485
|
* Loop principal del agente
|
|
225
486
|
*/
|
|
226
|
-
async function runAgent() {
|
|
487
|
+
async function runAgent(deployMode = false) {
|
|
227
488
|
console.log('');
|
|
228
489
|
console.log(`${colors.green}╔═══════════════════════════════════════════════════════╗${colors.reset}`);
|
|
229
490
|
console.log(`${colors.green}║ DGP Agent - Despliegue-GPT Local Agent ║${colors.reset}`);
|
|
230
|
-
console.log(`${colors.green}║ @
|
|
491
|
+
console.log(`${colors.green}║ @deinossrl/dgp-agent v1.2.5 ║${colors.reset}`);
|
|
231
492
|
console.log(`${colors.green}╚═══════════════════════════════════════════════════════╝${colors.reset}`);
|
|
232
493
|
console.log('');
|
|
233
494
|
|
|
@@ -240,6 +501,11 @@ async function runAgent() {
|
|
|
240
501
|
logInfo(`Report interval: ${CONFIG.interval}s`);
|
|
241
502
|
logInfo(`API URL: ${CONFIG.apiUrl}`);
|
|
242
503
|
|
|
504
|
+
if (deployMode) {
|
|
505
|
+
logInfo(`Deploy mode: ACTIVE`);
|
|
506
|
+
logInfo(`Command poll interval: ${CONFIG.commandPollInterval}s`);
|
|
507
|
+
}
|
|
508
|
+
|
|
243
509
|
if (!CONFIG.authToken) {
|
|
244
510
|
log('INFO: No auth token. Reporting anonymously.', 'yellow');
|
|
245
511
|
log('Set DGP_AUTH_TOKEN to associate with your user.', 'gray');
|
|
@@ -249,7 +515,8 @@ async function runAgent() {
|
|
|
249
515
|
logInfo('Press Ctrl+C to stop');
|
|
250
516
|
console.log('');
|
|
251
517
|
|
|
252
|
-
|
|
518
|
+
// Status reporting cycle
|
|
519
|
+
const runStatusCycle = async () => {
|
|
253
520
|
try {
|
|
254
521
|
const status = getRepoStatus();
|
|
255
522
|
printStatus(status);
|
|
@@ -262,8 +529,36 @@ async function runAgent() {
|
|
|
262
529
|
}
|
|
263
530
|
};
|
|
264
531
|
|
|
265
|
-
|
|
266
|
-
|
|
532
|
+
// Command polling cycle (only in deploy mode)
|
|
533
|
+
const runCommandCycle = async () => {
|
|
534
|
+
try {
|
|
535
|
+
const commands = await getPendingCommands();
|
|
536
|
+
if (commands.length > 0) {
|
|
537
|
+
const command = commands[0];
|
|
538
|
+
logCommand(`Found pending command: ${command.id}`);
|
|
539
|
+
await executeCommand(command);
|
|
540
|
+
}
|
|
541
|
+
} catch (error) {
|
|
542
|
+
// Silent fail for command polling - don't spam logs
|
|
543
|
+
if (error.message.includes('42P01')) {
|
|
544
|
+
// Table doesn't exist yet - ignore
|
|
545
|
+
} else {
|
|
546
|
+
logError(`Command poll failed: ${error.message}`);
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
// Initial run
|
|
552
|
+
await runStatusCycle();
|
|
553
|
+
if (deployMode) {
|
|
554
|
+
await runCommandCycle();
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
// Set intervals
|
|
558
|
+
setInterval(runStatusCycle, CONFIG.interval * 1000);
|
|
559
|
+
if (deployMode) {
|
|
560
|
+
setInterval(runCommandCycle, CONFIG.commandPollInterval * 1000);
|
|
561
|
+
}
|
|
267
562
|
}
|
|
268
563
|
|
|
269
564
|
/**
|
|
@@ -309,37 +604,60 @@ async function showStatus() {
|
|
|
309
604
|
function showHelp() {
|
|
310
605
|
console.log(`
|
|
311
606
|
${colors.bold}${colors.cyan}DGP Agent - Despliegue-GPT Local Agent${colors.reset}
|
|
312
|
-
${colors.gray}@
|
|
607
|
+
${colors.gray}@deinossrl/dgp-agent v1.2.5${colors.reset}
|
|
313
608
|
|
|
314
609
|
${colors.bold}DESCRIPCIÓN${colors.reset}
|
|
315
610
|
Agente local que reporta el estado de tu repositorio Git
|
|
316
|
-
a la plataforma TenMinute IA (Despliegue-GPT)
|
|
611
|
+
a la plataforma TenMinute IA (Despliegue-GPT) y puede
|
|
612
|
+
ejecutar comandos de deploy remotos.
|
|
317
613
|
|
|
318
614
|
${colors.bold}INSTALACIÓN${colors.reset}
|
|
319
|
-
${colors.green}npm install -g @
|
|
615
|
+
${colors.green}npm install -g @deinossrl/dgp-agent${colors.reset}
|
|
320
616
|
|
|
321
617
|
${colors.bold}USO${colors.reset}
|
|
322
|
-
${colors.cyan}dgp-agent${colors.reset} Inicia el agente (reporta
|
|
618
|
+
${colors.cyan}dgp-agent${colors.reset} Inicia el agente (solo reporta estado)
|
|
619
|
+
${colors.cyan}dgp-agent deploy${colors.reset} Modo deploy (reporta + escucha comandos)
|
|
323
620
|
${colors.cyan}dgp-agent status${colors.reset} Muestra el estado actual una vez
|
|
324
621
|
${colors.cyan}dgp-agent help${colors.reset} Muestra esta ayuda
|
|
325
622
|
|
|
623
|
+
${colors.bold}MODOS DE OPERACIÓN${colors.reset}
|
|
624
|
+
${colors.yellow}Default${colors.reset} Solo reporta estado del repo cada 30s
|
|
625
|
+
${colors.yellow}Deploy${colors.reset} Reporta estado + escucha comandos de la plataforma
|
|
626
|
+
Puede ejecutar: build, deploy via rsync, reload nginx
|
|
627
|
+
|
|
326
628
|
${colors.bold}VARIABLES DE ENTORNO${colors.reset}
|
|
327
|
-
${colors.yellow}DGP_AUTH_TOKEN${colors.reset}
|
|
328
|
-
|
|
329
|
-
${colors.yellow}
|
|
330
|
-
${colors.yellow}
|
|
331
|
-
${colors.yellow}DGP_MACHINE_ID${colors.reset}
|
|
629
|
+
${colors.yellow}DGP_AUTH_TOKEN${colors.reset} Token JWT para asociar a tu usuario
|
|
630
|
+
${colors.yellow}DGP_API_URL${colors.reset} URL del endpoint API
|
|
631
|
+
${colors.yellow}DGP_INTERVAL${colors.reset} Intervalo de reporte en segundos (default: 30)
|
|
632
|
+
${colors.yellow}DGP_COMMAND_POLL_INTERVAL${colors.reset} Intervalo de polling comandos (default: 10)
|
|
633
|
+
${colors.yellow}DGP_MACHINE_ID${colors.reset} ID personalizado de la máquina
|
|
332
634
|
|
|
333
635
|
${colors.bold}EJEMPLOS${colors.reset}
|
|
334
|
-
# Iniciar agente básico
|
|
636
|
+
# Iniciar agente básico (solo reporta)
|
|
335
637
|
${colors.gray}$ dgp-agent${colors.reset}
|
|
336
638
|
|
|
639
|
+
# Iniciar en modo deploy (puede ejecutar deploys)
|
|
640
|
+
${colors.gray}$ dgp-agent deploy${colors.reset}
|
|
641
|
+
|
|
337
642
|
# Con token de autenticación
|
|
338
|
-
${colors.gray}$ DGP_AUTH_TOKEN=eyJ... dgp-agent${colors.reset}
|
|
643
|
+
${colors.gray}$ DGP_AUTH_TOKEN=eyJ... dgp-agent deploy${colors.reset}
|
|
339
644
|
|
|
340
645
|
# Intervalo personalizado (60 segundos)
|
|
341
646
|
${colors.gray}$ DGP_INTERVAL=60 dgp-agent${colors.reset}
|
|
342
647
|
|
|
648
|
+
${colors.bold}REQUISITOS PARA DEPLOY${colors.reset}
|
|
649
|
+
- SSH key configurada para acceso al servidor
|
|
650
|
+
- Node.js y npm en el PATH
|
|
651
|
+
- rsync instalado (Linux/Mac) o equivalente (Windows)
|
|
652
|
+
- Permisos sudo para reload nginx (vía sudoers sin password)
|
|
653
|
+
|
|
654
|
+
${colors.bold}CHANGELOG${colors.reset}
|
|
655
|
+
${colors.cyan}v1.2.5${colors.reset} - Sincronización de versiones y changelog
|
|
656
|
+
${colors.cyan}v1.2.4${colors.reset} - Mejoras en ejecución async de comandos shell
|
|
657
|
+
${colors.cyan}v1.2.0${colors.reset} - Modo deploy con polling de comandos remotos
|
|
658
|
+
${colors.cyan}v1.1.0${colors.reset} - Soporte para deploy via rsync y reload nginx
|
|
659
|
+
${colors.cyan}v1.0.0${colors.reset} - Versión inicial: reporte de estado git
|
|
660
|
+
|
|
343
661
|
${colors.bold}MÁS INFO${colors.reset}
|
|
344
662
|
https://github.com/DEINOS-SRL/tenminuteia
|
|
345
663
|
`);
|
|
@@ -350,6 +668,11 @@ const args = process.argv.slice(2);
|
|
|
350
668
|
const command = args[0];
|
|
351
669
|
|
|
352
670
|
switch (command) {
|
|
671
|
+
case 'deploy':
|
|
672
|
+
case '-d':
|
|
673
|
+
case '--deploy':
|
|
674
|
+
runAgent(true); // Deploy mode
|
|
675
|
+
break;
|
|
353
676
|
case 'status':
|
|
354
677
|
case '-s':
|
|
355
678
|
case '--status':
|
|
@@ -363,8 +686,8 @@ switch (command) {
|
|
|
363
686
|
case 'version':
|
|
364
687
|
case '-v':
|
|
365
688
|
case '--version':
|
|
366
|
-
console.log('@
|
|
689
|
+
console.log('@deinossrl/dgp-agent v1.2.5');
|
|
367
690
|
break;
|
|
368
691
|
default:
|
|
369
|
-
runAgent();
|
|
692
|
+
runAgent(false); // Status-only mode
|
|
370
693
|
}
|