pypeline 1.0.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/README.md +448 -0
- package/lib/commands/pypeline/build.d.ts +18 -0
- package/lib/commands/pypeline/build.js +86 -0
- package/lib/commands/pypeline/build.js.map +1 -0
- package/lib/commands/pypeline/deploy/training.d.ts +15 -0
- package/lib/commands/pypeline/deploy/training.js +62 -0
- package/lib/commands/pypeline/deploy/training.js.map +1 -0
- package/lib/commands/pypeline/package.d.ts +11 -0
- package/lib/commands/pypeline/package.js +27 -0
- package/lib/commands/pypeline/package.js.map +1 -0
- package/lib/commands/pypeline/prd.d.ts +16 -0
- package/lib/commands/pypeline/prd.js +78 -0
- package/lib/commands/pypeline/prd.js.map +1 -0
- package/lib/commands/pypeline/quickdeploy.d.ts +18 -0
- package/lib/commands/pypeline/quickdeploy.js +116 -0
- package/lib/commands/pypeline/quickdeploy.js.map +1 -0
- package/lib/commands/pypeline/run.d.ts +19 -0
- package/lib/commands/pypeline/run.js +161 -0
- package/lib/commands/pypeline/run.js.map +1 -0
- package/lib/commands/pypeline/training.d.ts +15 -0
- package/lib/commands/pypeline/training.js +67 -0
- package/lib/commands/pypeline/training.js.map +1 -0
- package/lib/commands/pypeline/validate/prd.d.ts +16 -0
- package/lib/commands/pypeline/validate/prd.js +78 -0
- package/lib/commands/pypeline/validate/prd.js.map +1 -0
- package/lib/config.d.ts +23 -0
- package/lib/config.js +72 -0
- package/lib/config.js.map +1 -0
- package/lib/fileUtils.d.ts +2 -0
- package/lib/fileUtils.js +78 -0
- package/lib/fileUtils.js.map +1 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -0
- package/messages/pypeline.build.md +16 -0
- package/messages/pypeline.deploy.training.md +15 -0
- package/messages/pypeline.package.md +8 -0
- package/messages/pypeline.quickdeploy.md +22 -0
- package/messages/pypeline.run.md +26 -0
- package/messages/pypeline.validate.prd.md +15 -0
- package/oclif.lock +7808 -0
- package/oclif.manifest.json +544 -0
- package/package.json +163 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package.js","sourceRoot":"","sources":["../../../src/commands/pypeline/package.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,QAAQ,CAAC,kCAAkC,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,YAAY,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;AAOvE,MAAM,CAAC,OAAO,OAAO,eAAgB,SAAQ,SAAgC;IACpE,MAAM,CAAU,OAAO,GAAG,QAAQ,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IACzD,MAAM,CAAU,WAAW,GAAG,QAAQ,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IACjE,MAAM,CAAU,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IAE5D,KAAK,CAAC,GAAG;QACd,MAAM,QAAQ,GAAG,SAAS,EAAE,CAAC;QAC7B,IAAI,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;QAEnC,MAAM,QAAQ,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;YACrD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE;gBACtF,KAAK,EAAE,SAAS;aACjB,CAAC,CAAC;YACH,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,IAAI,QAAQ,KAAK,CAAC,EAAE,CAAC;YACnB,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QAC5C,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;QAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACrC,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
2
|
+
export type PypelineValidatePrdResult = {
|
|
3
|
+
success: boolean;
|
|
4
|
+
jobId: string | null;
|
|
5
|
+
logPath: string;
|
|
6
|
+
};
|
|
7
|
+
export default class PypelineValidatePrd extends SfCommand<PypelineValidatePrdResult> {
|
|
8
|
+
static readonly summary: string;
|
|
9
|
+
static readonly description: string;
|
|
10
|
+
static readonly examples: string[];
|
|
11
|
+
static readonly flags: {
|
|
12
|
+
'target-org': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
wait: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
};
|
|
15
|
+
run(): Promise<PypelineValidatePrdResult>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
|
|
4
|
+
import { Messages } from '@salesforce/core';
|
|
5
|
+
import { JOB_ID_FILE, LOG_PRD, SOURCE_DIR, unlinkIfExists, writeFile, } from '../../config.js';
|
|
6
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
7
|
+
const messages = Messages.loadMessages('pypeline', 'pypeline.validate.prd');
|
|
8
|
+
const JOB_ID_REGEX = /\b(0Af[0-9A-Za-z]{15})\b/;
|
|
9
|
+
export default class PypelineValidatePrd extends SfCommand {
|
|
10
|
+
static summary = messages.getMessage('summary');
|
|
11
|
+
static description = messages.getMessage('description');
|
|
12
|
+
static examples = messages.getMessages('examples');
|
|
13
|
+
static flags = {
|
|
14
|
+
'target-org': Flags.string({
|
|
15
|
+
summary: messages.getMessage('flags.target-org.summary'),
|
|
16
|
+
default: 'devops',
|
|
17
|
+
}),
|
|
18
|
+
wait: Flags.integer({
|
|
19
|
+
char: 'w',
|
|
20
|
+
summary: messages.getMessage('flags.wait.summary'),
|
|
21
|
+
default: 240,
|
|
22
|
+
}),
|
|
23
|
+
};
|
|
24
|
+
async run() {
|
|
25
|
+
const { flags } = await this.parse(PypelineValidatePrd);
|
|
26
|
+
const logPath = LOG_PRD();
|
|
27
|
+
const jobIdFile = JOB_ID_FILE();
|
|
28
|
+
const sourceDir = SOURCE_DIR();
|
|
29
|
+
unlinkIfExists(logPath);
|
|
30
|
+
unlinkIfExists(jobIdFile);
|
|
31
|
+
this.log('Iniciando validação em PRD...');
|
|
32
|
+
const cmd = [
|
|
33
|
+
'project', 'deploy', 'validate',
|
|
34
|
+
'--source-dir', sourceDir,
|
|
35
|
+
'--target-org', flags['target-org'] ?? 'devops',
|
|
36
|
+
'-w', String(flags['wait'] ?? 240),
|
|
37
|
+
'--verbose',
|
|
38
|
+
];
|
|
39
|
+
let jobId = null;
|
|
40
|
+
const exitCode = await new Promise((resolve) => {
|
|
41
|
+
const proc = spawn('sf', cmd, { stdio: ['inherit', 'pipe', 'pipe'] });
|
|
42
|
+
const log = fs.createWriteStream(logPath, { flags: 'a' });
|
|
43
|
+
const handleChunk = (chunk, isErr = false) => {
|
|
44
|
+
const text = chunk.toString();
|
|
45
|
+
(isErr ? process.stderr : process.stdout).write(text);
|
|
46
|
+
log.write(text);
|
|
47
|
+
if (!jobId) {
|
|
48
|
+
for (const line of text.split('\n')) {
|
|
49
|
+
const match = JOB_ID_REGEX.exec(line);
|
|
50
|
+
if (match?.[1]) {
|
|
51
|
+
jobId = match[1];
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
if (proc.stdout)
|
|
58
|
+
proc.stdout.on('data', (c) => handleChunk(c));
|
|
59
|
+
if (proc.stderr)
|
|
60
|
+
proc.stderr.on('data', (c) => handleChunk(c, true));
|
|
61
|
+
proc.on('close', (code) => { log.close(); resolve(code ?? 1); });
|
|
62
|
+
});
|
|
63
|
+
if (exitCode !== 0) {
|
|
64
|
+
this.error(`Validate em PRD falhou com exit code ${exitCode}.`);
|
|
65
|
+
}
|
|
66
|
+
if (jobId !== null) {
|
|
67
|
+
const safeJobId = jobId;
|
|
68
|
+
writeFile(jobIdFile, safeJobId + '\n');
|
|
69
|
+
this.log(`[INFO] Job ID salvo em prd_job_id.txt: ${safeJobId}`);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
this.warn('Job ID não encontrado no log. Quick deploy deverá ser feito manualmente.');
|
|
73
|
+
}
|
|
74
|
+
this.log('Validação em PRD concluída.');
|
|
75
|
+
return { success: true, jobId, logPath };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=prd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prd.js","sourceRoot":"","sources":["../../../src/commands/pypeline/prd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
2
|
+
export type PypelineQuickdeployResult = {
|
|
3
|
+
success: boolean;
|
|
4
|
+
jobId: string;
|
|
5
|
+
logPath: string;
|
|
6
|
+
};
|
|
7
|
+
export default class PypelineQuickdeploy extends SfCommand<PypelineQuickdeployResult> {
|
|
8
|
+
static readonly summary: string;
|
|
9
|
+
static readonly description: string;
|
|
10
|
+
static readonly examples: string[];
|
|
11
|
+
static readonly flags: {
|
|
12
|
+
'target-org': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
'job-id': import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
wait: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
'no-prompt': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
|
+
};
|
|
17
|
+
run(): Promise<PypelineQuickdeployResult>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
|
|
4
|
+
import { Messages } from '@salesforce/core';
|
|
5
|
+
import { JOB_ID_FILE, LOG_QUICK_DEPLOY, fileExists, readFileTrimmed, unlinkIfExists, } from '../../config.js';
|
|
6
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
7
|
+
const messages = Messages.loadMessages('pypeline', 'pypeline.quickdeploy');
|
|
8
|
+
const JOB_ID_FORMAT = /^0Af[0-9A-Za-z]{15}$/;
|
|
9
|
+
const ERROR_PATTERN = /deploy failed|error|exception/i;
|
|
10
|
+
export default class PypelineQuickdeploy extends SfCommand {
|
|
11
|
+
static summary = messages.getMessage('summary');
|
|
12
|
+
static description = messages.getMessage('description');
|
|
13
|
+
static examples = messages.getMessages('examples');
|
|
14
|
+
static flags = {
|
|
15
|
+
'target-org': Flags.string({
|
|
16
|
+
summary: messages.getMessage('flags.target-org.summary'),
|
|
17
|
+
default: 'devops',
|
|
18
|
+
}),
|
|
19
|
+
'job-id': Flags.string({
|
|
20
|
+
char: 'j',
|
|
21
|
+
summary: messages.getMessage('flags.job-id.summary'),
|
|
22
|
+
}),
|
|
23
|
+
wait: Flags.integer({
|
|
24
|
+
char: 'w',
|
|
25
|
+
summary: messages.getMessage('flags.wait.summary'),
|
|
26
|
+
default: 240,
|
|
27
|
+
}),
|
|
28
|
+
'no-prompt': Flags.boolean({
|
|
29
|
+
summary: messages.getMessage('flags.no-prompt.summary'),
|
|
30
|
+
default: false,
|
|
31
|
+
}),
|
|
32
|
+
};
|
|
33
|
+
async run() {
|
|
34
|
+
const { flags } = await this.parse(PypelineQuickdeploy);
|
|
35
|
+
const jobIdFile = JOB_ID_FILE();
|
|
36
|
+
const logPath = LOG_QUICK_DEPLOY();
|
|
37
|
+
this.log('');
|
|
38
|
+
this.log('╔══════════════════════════════════════════════╗');
|
|
39
|
+
this.log('║ QUICK DEPLOY EM PRODUÇÃO ║');
|
|
40
|
+
this.log('╚══════════════════════════════════════════════╝');
|
|
41
|
+
this.log('');
|
|
42
|
+
let jobId = flags['job-id'];
|
|
43
|
+
if (!jobId) {
|
|
44
|
+
if (!fileExists(jobIdFile)) {
|
|
45
|
+
this.error('prd_job_id.txt não encontrado. Execute sf pypeline run (ou sf pypeline validate prd) antes.');
|
|
46
|
+
}
|
|
47
|
+
jobId = readFileTrimmed(jobIdFile);
|
|
48
|
+
}
|
|
49
|
+
if (!jobId)
|
|
50
|
+
this.error('Job ID vazio. Nenhum Job ID disponível.');
|
|
51
|
+
if (!JOB_ID_FORMAT.test(jobId)) {
|
|
52
|
+
this.error(`Job ID com formato inválido: ${jobId}\nEsperado: 18 caracteres começando com 0Af`);
|
|
53
|
+
}
|
|
54
|
+
this.log(`[INFO] Job ID: ${jobId}`);
|
|
55
|
+
this.log('[INFO] Validate expira em 10 horas após a geração.');
|
|
56
|
+
this.log('');
|
|
57
|
+
this.log(` Org alvo : ${flags['target-org'] ?? 'devops'}`);
|
|
58
|
+
this.log(` Job ID : ${jobId}`);
|
|
59
|
+
this.log('');
|
|
60
|
+
if (!flags['no-prompt']) {
|
|
61
|
+
const confirmed = await this.confirm({ message: 'Confirma o quick deploy em PRODUÇÃO?' });
|
|
62
|
+
if (!confirmed) {
|
|
63
|
+
this.log('[CANCELADO] Quick deploy não executado.');
|
|
64
|
+
return { success: false, jobId, logPath };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
unlinkIfExists(logPath);
|
|
68
|
+
this.log('[INFO] Iniciando quick deploy em PRD...');
|
|
69
|
+
const cmd = [
|
|
70
|
+
'project', 'deploy', 'quick',
|
|
71
|
+
'--job-id', jobId,
|
|
72
|
+
'--target-org', flags['target-org'] ?? 'devops',
|
|
73
|
+
'-w', String(flags['wait'] ?? 240),
|
|
74
|
+
'--verbose',
|
|
75
|
+
];
|
|
76
|
+
const exitCode = await new Promise((resolve) => {
|
|
77
|
+
const proc = spawn('sf', cmd, { stdio: ['inherit', 'pipe', 'pipe'] });
|
|
78
|
+
const log = fs.createWriteStream(logPath, { flags: 'a' });
|
|
79
|
+
const handle = (chunk, isErr = false) => {
|
|
80
|
+
const text = chunk.toString();
|
|
81
|
+
(isErr ? process.stderr : process.stdout).write(text);
|
|
82
|
+
log.write(text);
|
|
83
|
+
};
|
|
84
|
+
if (proc.stdout)
|
|
85
|
+
proc.stdout.on('data', (c) => handle(c));
|
|
86
|
+
if (proc.stderr)
|
|
87
|
+
proc.stderr.on('data', (c) => handle(c, true));
|
|
88
|
+
proc.on('close', (code) => { log.close(); resolve(code ?? 1); });
|
|
89
|
+
});
|
|
90
|
+
this.log('');
|
|
91
|
+
if (exitCode === 0) {
|
|
92
|
+
const logContent = fs.readFileSync(logPath, 'utf8');
|
|
93
|
+
if (ERROR_PATTERN.test(logContent)) {
|
|
94
|
+
this.log('╔══════════════════════════════════════════════╗');
|
|
95
|
+
this.log('║ [AVISO] Deploy concluído com warnings. ║');
|
|
96
|
+
this.log(`║ Verifique : ${logPath.split('/').pop()?.padEnd(32) ?? ''}║`);
|
|
97
|
+
this.log('╚══════════════════════════════════════════════╝');
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
unlinkIfExists(jobIdFile);
|
|
101
|
+
this.log('╔══════════════════════════════════════════════╗');
|
|
102
|
+
this.log('║ QUICK DEPLOY EM PRD CONCLUÍDO COM SUCESSO ║');
|
|
103
|
+
this.log('║ prd_job_id.txt removido (evita reuso) ║');
|
|
104
|
+
this.log('╚══════════════════════════════════════════════╝');
|
|
105
|
+
}
|
|
106
|
+
return { success: true, jobId, logPath };
|
|
107
|
+
}
|
|
108
|
+
this.log('╔══════════════════════════════════════════════╗');
|
|
109
|
+
this.log('║ [ERRO] Quick deploy falhou. ║');
|
|
110
|
+
this.log(`║ Exit code : ${String(exitCode).padEnd(32)}║`);
|
|
111
|
+
this.log(`║ Verifique : ${logPath.split('/').pop()?.padEnd(32) ?? ''}║`);
|
|
112
|
+
this.log('╚══════════════════════════════════════════════╝');
|
|
113
|
+
this.error(`Quick deploy falhou com exit code ${exitCode}.`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=quickdeploy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quickdeploy.js","sourceRoot":"","sources":["../../../src/commands/pypeline/quickdeploy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
2
|
+
export type PypelineRunResult = {
|
|
3
|
+
success: boolean;
|
|
4
|
+
jobId: string | null;
|
|
5
|
+
baselineUpdated: string | null;
|
|
6
|
+
};
|
|
7
|
+
export default class PypelineRun extends SfCommand<PypelineRunResult> {
|
|
8
|
+
static readonly summary: string;
|
|
9
|
+
static readonly description: string;
|
|
10
|
+
static readonly examples: string[];
|
|
11
|
+
static readonly flags: {
|
|
12
|
+
branch: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
'skip-training': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
14
|
+
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
15
|
+
'prd-org': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
|
+
'training-org': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
|
+
};
|
|
18
|
+
run(): Promise<PypelineRunResult>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
|
|
4
|
+
import { Messages } from '@salesforce/core';
|
|
5
|
+
import { BASELINE_FILE, JOB_ID_FILE, LOG_PRD, LOG_TRAINING, SCRIPT_DIR, fileExists, readFileTrimmed, writeFile, } from '../../config.js';
|
|
6
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
7
|
+
const messages = Messages.loadMessages('pypeline', 'pypeline.run');
|
|
8
|
+
const ERROR_PATTERN = /error|failed|exception|deploy failed/i;
|
|
9
|
+
function logHasErrors(logPath) {
|
|
10
|
+
if (!fs.existsSync(logPath))
|
|
11
|
+
return false;
|
|
12
|
+
return fs.readFileSync(logPath, 'utf8').split('\n').some((l) => ERROR_PATTERN.test(l));
|
|
13
|
+
}
|
|
14
|
+
function extractJobId(logPath) {
|
|
15
|
+
if (!fs.existsSync(logPath))
|
|
16
|
+
return null;
|
|
17
|
+
for (const line of fs.readFileSync(logPath, 'utf8').split('\n')) {
|
|
18
|
+
const match = /\b(0Af[0-9A-Za-z]{15})\b/.exec(line);
|
|
19
|
+
if (match)
|
|
20
|
+
return match[1];
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
async function runSubcommand(args) {
|
|
25
|
+
return new Promise((resolve) => {
|
|
26
|
+
const proc = spawn('sf', args, { stdio: 'inherit' });
|
|
27
|
+
proc.on('close', (code) => resolve(code ?? 1));
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
export default class PypelineRun extends SfCommand {
|
|
31
|
+
static summary = messages.getMessage('summary');
|
|
32
|
+
static description = messages.getMessage('description');
|
|
33
|
+
static examples = messages.getMessages('examples');
|
|
34
|
+
static flags = {
|
|
35
|
+
branch: Flags.string({
|
|
36
|
+
char: 'b',
|
|
37
|
+
summary: messages.getMessage('flags.branch.summary'),
|
|
38
|
+
}),
|
|
39
|
+
'skip-training': Flags.boolean({
|
|
40
|
+
summary: messages.getMessage('flags.skip-training.summary'),
|
|
41
|
+
default: false,
|
|
42
|
+
}),
|
|
43
|
+
'dry-run': Flags.boolean({
|
|
44
|
+
summary: messages.getMessage('flags.dry-run.summary'),
|
|
45
|
+
default: false,
|
|
46
|
+
}),
|
|
47
|
+
'prd-org': Flags.string({
|
|
48
|
+
summary: messages.getMessage('flags.prd-org.summary'),
|
|
49
|
+
default: 'devops',
|
|
50
|
+
}),
|
|
51
|
+
'training-org': Flags.string({
|
|
52
|
+
summary: messages.getMessage('flags.training-org.summary'),
|
|
53
|
+
default: 'treino',
|
|
54
|
+
}),
|
|
55
|
+
};
|
|
56
|
+
async run() {
|
|
57
|
+
const { flags } = await this.parse(PypelineRun);
|
|
58
|
+
// Resolve todos os caminhos uma única vez no início do run
|
|
59
|
+
const baselineFile = BASELINE_FILE();
|
|
60
|
+
const jobIdFile = JOB_ID_FILE();
|
|
61
|
+
const logPrd = LOG_PRD();
|
|
62
|
+
const logTraining = LOG_TRAINING();
|
|
63
|
+
if (!fileExists(baselineFile)) {
|
|
64
|
+
this.error('baseline.txt não encontrado. Abortando.');
|
|
65
|
+
}
|
|
66
|
+
const baselineBackup = readFileTrimmed(baselineFile);
|
|
67
|
+
this.log(`[INFO] Baseline salvo para rollback: ${baselineBackup}`);
|
|
68
|
+
this.log(`[INFO] Diretório de trabalho: ${process.cwd()}`);
|
|
69
|
+
this.log(`[INFO] Script dir: ${SCRIPT_DIR}`);
|
|
70
|
+
const rollback = (etapa) => {
|
|
71
|
+
this.log('');
|
|
72
|
+
this.log('╔══════════════════════════════════════════════╗');
|
|
73
|
+
this.log(`║ ERRO NA ETAPA: ${etapa.padEnd(28)}║`);
|
|
74
|
+
this.log(`║ Restaurando baseline → ${baselineBackup.slice(0, 20)}... ║`);
|
|
75
|
+
this.log('╚══════════════════════════════════════════════╝');
|
|
76
|
+
writeFile(baselineFile, baselineBackup + '\n');
|
|
77
|
+
this.log('[INFO] Rollback concluído. Nenhuma alteração foi promovida.');
|
|
78
|
+
this.error(`Pipeline abortado na etapa: ${etapa}`);
|
|
79
|
+
};
|
|
80
|
+
// ── ETAPA 1: Build ───────────────────────────────────────────────────
|
|
81
|
+
this.log('');
|
|
82
|
+
this.log('==> [1/4] Executando build...');
|
|
83
|
+
const buildArgs = [
|
|
84
|
+
'pypeline', 'build',
|
|
85
|
+
...(flags['branch'] ? ['--branch', flags['branch']] : []),
|
|
86
|
+
...(flags['dry-run'] ? ['--dry-run'] : []),
|
|
87
|
+
];
|
|
88
|
+
if ((await runSubcommand(buildArgs)) !== 0)
|
|
89
|
+
rollback('pypeline build');
|
|
90
|
+
// ── ETAPA 2: package.xml ─────────────────────────────────────────────
|
|
91
|
+
this.log('');
|
|
92
|
+
this.log('==> [2/4] Gerando package.xml...');
|
|
93
|
+
if ((await runSubcommand(['pypeline', 'package'])) !== 0)
|
|
94
|
+
rollback('pypeline package');
|
|
95
|
+
// ── ETAPA 3: Training em background ─────────────────────────────────
|
|
96
|
+
let trainingPromise = null;
|
|
97
|
+
if (!flags['skip-training']) {
|
|
98
|
+
this.log('');
|
|
99
|
+
this.log('==> [3/4] Disparando deploy em Training (paralelo ao PRD)...');
|
|
100
|
+
trainingPromise = runSubcommand(['pypeline', 'deploy', 'training', '--target-org', flags['training-org'] ?? 'treino']);
|
|
101
|
+
this.log('[INFO] Training rodando em background...');
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
this.log('==> [3/4] Training ignorado (--skip-training).');
|
|
105
|
+
}
|
|
106
|
+
// ── ETAPA 4: Validação PRD (síncrono) ────────────────────────────────
|
|
107
|
+
this.log('');
|
|
108
|
+
this.log('==> [4/4] Validação em PRD...');
|
|
109
|
+
const prdExit = await runSubcommand(['pypeline', 'validate', 'prd', '--target-org', flags['prd-org'] ?? 'devops']);
|
|
110
|
+
const trainingExit = trainingPromise ? await trainingPromise : null;
|
|
111
|
+
if (prdExit !== 0)
|
|
112
|
+
rollback('pypeline validate prd (exit code diferente de 0)');
|
|
113
|
+
if (logHasErrors(logPrd)) {
|
|
114
|
+
this.log('[ERRO] Erros detectados no deploy_prd_output.log:');
|
|
115
|
+
let shown = 0;
|
|
116
|
+
for (const l of fs.readFileSync(logPrd, 'utf8').split('\n')) {
|
|
117
|
+
if (ERROR_PATTERN.test(l)) {
|
|
118
|
+
this.log(` ${l}`);
|
|
119
|
+
if (++shown >= 20)
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
rollback('validate PRD (erros encontrados no log)');
|
|
124
|
+
}
|
|
125
|
+
this.log('[OK] Validação em PRD concluída sem erros.');
|
|
126
|
+
this.log('');
|
|
127
|
+
if (trainingExit === null) {
|
|
128
|
+
this.log('[INFO] Training não executado nesta run.');
|
|
129
|
+
}
|
|
130
|
+
else if (trainingExit !== 0) {
|
|
131
|
+
this.warn(`Training terminou com exit code ${trainingExit} — verifique deploy_training_output.log`);
|
|
132
|
+
}
|
|
133
|
+
else if (logHasErrors(logTraining)) {
|
|
134
|
+
this.warn('Training concluído mas com erros no log — verifique deploy_training_output.log');
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
this.log('[OK] Deploy em Training concluído sem erros.');
|
|
138
|
+
}
|
|
139
|
+
const novoBaseline = readFileTrimmed(baselineFile);
|
|
140
|
+
writeFile(baselineFile, novoBaseline + '\n');
|
|
141
|
+
this.log(`[INFO] baseline.txt atualizado para: ${novoBaseline}`);
|
|
142
|
+
const jobId = extractJobId(logPrd);
|
|
143
|
+
if (jobId) {
|
|
144
|
+
writeFile(jobIdFile, jobId + '\n');
|
|
145
|
+
this.log('');
|
|
146
|
+
this.log('╔══════════════════════════════════════════════════════════════╗');
|
|
147
|
+
this.log('║ PIPELINE CONCLUÍDO COM SUCESSO ║');
|
|
148
|
+
this.log(`║ Job ID para quick deploy: ${jobId.padEnd(34)}║`);
|
|
149
|
+
this.log('║ Execute: sf pypeline quickdeploy ║');
|
|
150
|
+
this.log('╚══════════════════════════════════════════════════════════════╝');
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
this.warn('Job ID não encontrado no log. Verifique deploy_prd_output.log manualmente.');
|
|
154
|
+
this.log('[INFO] Pipeline concluído. Baseline atualizado.');
|
|
155
|
+
}
|
|
156
|
+
this.log('');
|
|
157
|
+
this.log('Fim da execução.');
|
|
158
|
+
return { success: true, jobId, baselineUpdated: novoBaseline };
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../../src/commands/pypeline/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
2
|
+
export type PypelineDeployTrainingResult = {
|
|
3
|
+
success: boolean;
|
|
4
|
+
logPath: string;
|
|
5
|
+
};
|
|
6
|
+
export default class PypelineDeployTraining extends SfCommand<PypelineDeployTrainingResult> {
|
|
7
|
+
static readonly summary: string;
|
|
8
|
+
static readonly description: string;
|
|
9
|
+
static readonly examples: string[];
|
|
10
|
+
static readonly flags: {
|
|
11
|
+
'target-org': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
|
+
wait: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
};
|
|
14
|
+
run(): Promise<PypelineDeployTrainingResult>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
|
|
4
|
+
import { Messages } from '@salesforce/core';
|
|
5
|
+
import { LOG_TRAINING, SOURCE_DIR, unlinkIfExists } from '../../config.js';
|
|
6
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
7
|
+
const messages = Messages.loadMessages('pypeline', 'pypeline.deploy.training');
|
|
8
|
+
export default class PypelineDeployTraining extends SfCommand {
|
|
9
|
+
static summary = messages.getMessage('summary');
|
|
10
|
+
static description = messages.getMessage('description');
|
|
11
|
+
static examples = messages.getMessages('examples');
|
|
12
|
+
static flags = {
|
|
13
|
+
'target-org': Flags.string({
|
|
14
|
+
summary: messages.getMessage('flags.target-org.summary'),
|
|
15
|
+
default: 'treino',
|
|
16
|
+
}),
|
|
17
|
+
wait: Flags.integer({
|
|
18
|
+
char: 'w',
|
|
19
|
+
summary: messages.getMessage('flags.wait.summary'),
|
|
20
|
+
default: 240,
|
|
21
|
+
}),
|
|
22
|
+
};
|
|
23
|
+
async run() {
|
|
24
|
+
const { flags } = await this.parse(PypelineDeployTraining);
|
|
25
|
+
const logPath = LOG_TRAINING();
|
|
26
|
+
const sourceDir = SOURCE_DIR();
|
|
27
|
+
unlinkIfExists(logPath);
|
|
28
|
+
this.log('Iniciando deploy em Training...');
|
|
29
|
+
const cmd = [
|
|
30
|
+
'project', 'deploy', 'start',
|
|
31
|
+
'--source-dir', sourceDir,
|
|
32
|
+
'--target-org', flags['target-org'] ?? 'treino',
|
|
33
|
+
'--test-level', 'RunLocalTests',
|
|
34
|
+
'-w', String(flags['wait'] ?? 240),
|
|
35
|
+
'--ignore-conflicts',
|
|
36
|
+
'--verbose',
|
|
37
|
+
];
|
|
38
|
+
const exitCode = await new Promise((resolve) => {
|
|
39
|
+
const proc = spawn('sf', cmd, { stdio: ['inherit', 'pipe', 'pipe'] });
|
|
40
|
+
const log = fs.createWriteStream(logPath, { flags: 'a' });
|
|
41
|
+
if (proc.stdout) {
|
|
42
|
+
proc.stdout.on('data', (chunk) => {
|
|
43
|
+
const text = chunk.toString();
|
|
44
|
+
process.stdout.write(text);
|
|
45
|
+
log.write(text);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (proc.stderr) {
|
|
49
|
+
proc.stderr.on('data', (chunk) => {
|
|
50
|
+
const text = chunk.toString();
|
|
51
|
+
process.stderr.write(text);
|
|
52
|
+
log.write(text);
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
proc.on('close', (code) => {
|
|
56
|
+
log.close();
|
|
57
|
+
resolve(code ?? 1);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
if (exitCode !== 0) {
|
|
61
|
+
this.error(`Deploy em Training falhou com exit code ${exitCode}.`);
|
|
62
|
+
}
|
|
63
|
+
this.log('Deploy em Training concluído com sucesso.');
|
|
64
|
+
return { success: true, logPath };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=training.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"training.js","sourceRoot":"","sources":["../../../src/commands/pypeline/training.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
2
|
+
export type PypelineValidatePrdResult = {
|
|
3
|
+
success: boolean;
|
|
4
|
+
jobId: string | null;
|
|
5
|
+
logPath: string;
|
|
6
|
+
};
|
|
7
|
+
export default class PypelineValidatePrd extends SfCommand<PypelineValidatePrdResult> {
|
|
8
|
+
static readonly summary: string;
|
|
9
|
+
static readonly description: string;
|
|
10
|
+
static readonly examples: string[];
|
|
11
|
+
static readonly flags: {
|
|
12
|
+
'target-org': import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
wait: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
};
|
|
15
|
+
run(): Promise<PypelineValidatePrdResult>;
|
|
16
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
|
|
4
|
+
import { Messages } from '@salesforce/core';
|
|
5
|
+
import { JOB_ID_FILE, LOG_PRD, SOURCE_DIR, unlinkIfExists, writeFile, } from '../../../config.js';
|
|
6
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
7
|
+
const messages = Messages.loadMessages('pypeline', 'pypeline.validate.prd');
|
|
8
|
+
const JOB_ID_REGEX = /\b(0Af[0-9A-Za-z]{15})\b/;
|
|
9
|
+
export default class PypelineValidatePrd extends SfCommand {
|
|
10
|
+
static summary = messages.getMessage('summary');
|
|
11
|
+
static description = messages.getMessage('description');
|
|
12
|
+
static examples = messages.getMessages('examples');
|
|
13
|
+
static flags = {
|
|
14
|
+
'target-org': Flags.string({
|
|
15
|
+
summary: messages.getMessage('flags.target-org.summary'),
|
|
16
|
+
default: 'devops',
|
|
17
|
+
}),
|
|
18
|
+
wait: Flags.integer({
|
|
19
|
+
char: 'w',
|
|
20
|
+
summary: messages.getMessage('flags.wait.summary'),
|
|
21
|
+
default: 240,
|
|
22
|
+
}),
|
|
23
|
+
};
|
|
24
|
+
async run() {
|
|
25
|
+
const { flags } = await this.parse(PypelineValidatePrd);
|
|
26
|
+
const logPath = LOG_PRD();
|
|
27
|
+
const jobIdFile = JOB_ID_FILE();
|
|
28
|
+
const sourceDir = SOURCE_DIR();
|
|
29
|
+
unlinkIfExists(logPath);
|
|
30
|
+
unlinkIfExists(jobIdFile);
|
|
31
|
+
this.log('Iniciando validação em PRD...');
|
|
32
|
+
const cmd = [
|
|
33
|
+
'project', 'deploy', 'validate',
|
|
34
|
+
'--source-dir', sourceDir,
|
|
35
|
+
'--target-org', flags['target-org'] ?? 'devops',
|
|
36
|
+
'-w', String(flags['wait'] ?? 240),
|
|
37
|
+
'--verbose',
|
|
38
|
+
];
|
|
39
|
+
let jobId = null;
|
|
40
|
+
const exitCode = await new Promise((resolve) => {
|
|
41
|
+
const proc = spawn('sf', cmd, { stdio: ['inherit', 'pipe', 'pipe'] });
|
|
42
|
+
const log = fs.createWriteStream(logPath, { flags: 'a' });
|
|
43
|
+
const handleChunk = (chunk, isErr = false) => {
|
|
44
|
+
const text = chunk.toString();
|
|
45
|
+
(isErr ? process.stderr : process.stdout).write(text);
|
|
46
|
+
log.write(text);
|
|
47
|
+
if (!jobId) {
|
|
48
|
+
for (const line of text.split('\n')) {
|
|
49
|
+
const match = JOB_ID_REGEX.exec(line);
|
|
50
|
+
if (match?.[1]) {
|
|
51
|
+
jobId = match[1];
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
if (proc.stdout)
|
|
58
|
+
proc.stdout.on('data', (c) => handleChunk(c));
|
|
59
|
+
if (proc.stderr)
|
|
60
|
+
proc.stderr.on('data', (c) => handleChunk(c, true));
|
|
61
|
+
proc.on('close', (code) => { log.close(); resolve(code ?? 1); });
|
|
62
|
+
});
|
|
63
|
+
if (exitCode !== 0) {
|
|
64
|
+
this.error(`Validate em PRD falhou com exit code ${exitCode}.`);
|
|
65
|
+
}
|
|
66
|
+
if (jobId !== null) {
|
|
67
|
+
const safeJobId = jobId;
|
|
68
|
+
writeFile(jobIdFile, safeJobId + '\n');
|
|
69
|
+
this.log(`[INFO] Job ID salvo em prd_job_id.txt: ${safeJobId}`);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
this.warn('Job ID não encontrado no log. Quick deploy deverá ser feito manualmente.');
|
|
73
|
+
}
|
|
74
|
+
this.log('Validação em PRD concluída.');
|
|
75
|
+
return { success: true, jobId, logPath };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=prd.js.map
|