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
package/README.md
ADDED
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
# pypeline — SF CLI Plugin
|
|
2
|
+
|
|
3
|
+
Pipeline DevOps Salesforce completo como plugin nativo do `sf` CLI. Orquestra build, geração de package.xml, validação em PRD e quick deploy a partir de um repositório git.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Índice
|
|
8
|
+
|
|
9
|
+
- [Pré-requisitos](#pré-requisitos)
|
|
10
|
+
- [Instalação](#instalação)
|
|
11
|
+
- [Configuração inicial](#configuração-inicial)
|
|
12
|
+
- [Como buildar o plugin](#como-buildar-o-plugin)
|
|
13
|
+
- [Comandos disponíveis](#comandos-disponíveis)
|
|
14
|
+
- [Fluxo completo de uso](#fluxo-completo-de-uso)
|
|
15
|
+
- [Testes](#testes)
|
|
16
|
+
- [Estrutura do projeto](#estrutura-do-projeto)
|
|
17
|
+
- [Solução de problemas](#solução-de-problemas)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Pré-requisitos
|
|
22
|
+
|
|
23
|
+
Antes de começar, certifique-se de ter instalado:
|
|
24
|
+
|
|
25
|
+
- **Node.js** >= 18.0.0
|
|
26
|
+
- **Yarn** (recomendado) ou npm
|
|
27
|
+
- **Salesforce CLI** (`sf`) >= 2.x — instale com `npm install -g @salesforce/cli`
|
|
28
|
+
- **Git** configurado no PATH
|
|
29
|
+
- **Python 3** (apenas se você ainda usar os scripts `.py` originais em paralelo)
|
|
30
|
+
|
|
31
|
+
Verifique as versões:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
node --version # deve ser >= 18
|
|
35
|
+
sf --version # deve ser >= 2
|
|
36
|
+
git --version
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Instalação
|
|
42
|
+
|
|
43
|
+
### Opção 1 — Link local (desenvolvimento)
|
|
44
|
+
|
|
45
|
+
É o modo recomendado enquanto você está desenvolvendo o plugin:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# 1. Entre na pasta do plugin
|
|
49
|
+
cd pypeline
|
|
50
|
+
|
|
51
|
+
# 2. Instale as dependências
|
|
52
|
+
yarn install
|
|
53
|
+
|
|
54
|
+
# 3. Compile o TypeScript
|
|
55
|
+
yarn build
|
|
56
|
+
|
|
57
|
+
# 4. Linke o plugin no sf CLI local
|
|
58
|
+
sf plugins link .
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Após o link, o plugin fica disponível globalmente no seu `sf`:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
sf pypeline --help
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Para atualizar o plugin após alterar código, recompile e o link já pega automaticamente:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
yarn build
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Opção 2 — Instalação a partir de um diretório (sem publicar no npm)
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
sf plugins install /caminho/absoluto/para/pypeline
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Opção 3 — Publicar no npm e instalar
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Dentro da pasta do plugin
|
|
83
|
+
npm publish
|
|
84
|
+
|
|
85
|
+
# Em qualquer máquina
|
|
86
|
+
sf plugins install pypeline
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Configuração inicial
|
|
92
|
+
|
|
93
|
+
Antes de usar o pipeline, você precisa de dois arquivos na pasta `workspace_bash`:
|
|
94
|
+
|
|
95
|
+
### 1. `baseline.txt`
|
|
96
|
+
|
|
97
|
+
Contém o hash do commit git que serve como ponto de partida do diff. O pipeline copia apenas os arquivos alterados **a partir desse commit**.
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Criar com o hash atual (ponto zero)
|
|
101
|
+
git rev-parse HEAD > baseline.txt
|
|
102
|
+
|
|
103
|
+
# Ou com um commit específico
|
|
104
|
+
echo "abc1234def5678..." > baseline.txt
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 2. Autenticação das orgs no sf CLI
|
|
108
|
+
|
|
109
|
+
O pipeline usa dois aliases de org por padrão:
|
|
110
|
+
|
|
111
|
+
| Alias | Finalidade |
|
|
112
|
+
|-------|-----------|
|
|
113
|
+
| `devops` | Org de produção (PRD) |
|
|
114
|
+
| `treino` | Org de treinamento |
|
|
115
|
+
|
|
116
|
+
Autentique cada uma:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
sf org login web --alias devops
|
|
120
|
+
sf org login web --alias treino
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Para usar aliases diferentes, passe as flags `--prd-org` e `--training-org` nos comandos.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Como buildar o plugin
|
|
128
|
+
|
|
129
|
+
O projeto usa **TypeScript** compilado via `tsc` com **wireit** para cache incremental.
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Build completo (compila + lint)
|
|
133
|
+
yarn build
|
|
134
|
+
|
|
135
|
+
# Apenas compilar TypeScript (mais rápido, sem lint)
|
|
136
|
+
yarn compile
|
|
137
|
+
|
|
138
|
+
# Limpar os artefatos de build
|
|
139
|
+
yarn clean
|
|
140
|
+
|
|
141
|
+
# Limpar tudo (incluindo node_modules)
|
|
142
|
+
yarn clean-all
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Os arquivos compilados ficam em `lib/` — é o que o sf CLI carrega em produção.
|
|
146
|
+
|
|
147
|
+
> **Atenção:** nunca edite arquivos em `lib/` diretamente. Sempre edite em `src/` e recompile.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Comandos disponíveis
|
|
152
|
+
|
|
153
|
+
### `sf pypeline run` — Pipeline completo
|
|
154
|
+
|
|
155
|
+
Executa todas as 4 etapas em sequência. O deploy em Training roda em paralelo ao validate PRD. Em caso de falha em qualquer etapa, faz rollback automático do `baseline.txt`.
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
# Execução padrão
|
|
159
|
+
sf pypeline run
|
|
160
|
+
|
|
161
|
+
# Com branch customizada
|
|
162
|
+
sf pypeline run --branch release-v5.0.0
|
|
163
|
+
|
|
164
|
+
# Pulando o deploy em Training
|
|
165
|
+
sf pypeline run --skip-training
|
|
166
|
+
|
|
167
|
+
# Com orgs customizadas
|
|
168
|
+
sf pypeline run --prd-org minha-producao --training-org minha-homolog
|
|
169
|
+
|
|
170
|
+
# Simulando o build sem copiar arquivos
|
|
171
|
+
sf pypeline run --dry-run
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Flags disponíveis:**
|
|
175
|
+
|
|
176
|
+
| Flag | Padrão | Descrição |
|
|
177
|
+
|------|--------|-----------|
|
|
178
|
+
| `--branch, -b` | valor em `config.ts` | Branch git para checkout no build |
|
|
179
|
+
| `--skip-training` | `false` | Pula o deploy em Training |
|
|
180
|
+
| `--dry-run` | `false` | Simula o build sem tocar em arquivos |
|
|
181
|
+
| `--prd-org` | `devops` | Alias da org de produção |
|
|
182
|
+
| `--training-org` | `treino` | Alias da org de treinamento |
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
### `sf pypeline build` — Etapa 1
|
|
187
|
+
|
|
188
|
+
Faz checkout da branch, git pull, calcula o diff desde o baseline e copia os arquivos alterados para a pasta `build_deploy/`.
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
sf pypeline build
|
|
192
|
+
sf pypeline build --branch release-v5.0.0
|
|
193
|
+
sf pypeline build --dry-run
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Arquivos gerados após a execução:
|
|
197
|
+
|
|
198
|
+
```
|
|
199
|
+
workspace_bash/
|
|
200
|
+
├── build_deploy/ ← pasta com os arquivos do deploy
|
|
201
|
+
├── commitlist.txt ← lista de commits desde o baseline
|
|
202
|
+
├── lista_arquivos_adicionados.txt
|
|
203
|
+
├── lista_arquivos_modificados.txt
|
|
204
|
+
├── lista_arquivos_deletados.txt
|
|
205
|
+
└── lista_arquivos_naodeletados.txt
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
### `sf pypeline package` — Etapa 2
|
|
211
|
+
|
|
212
|
+
Gera o `package.xml` a partir da pasta de build usando `sf project generate manifest`.
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
sf pypeline package
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
### `sf pypeline deploy training` — Etapa 3
|
|
221
|
+
|
|
222
|
+
Deploy na org de treinamento com `RunLocalTests`. Grava output em `deploy_training_output.log`.
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
sf pypeline deploy training
|
|
226
|
+
sf pypeline deploy training --target-org minha-org-treino
|
|
227
|
+
sf pypeline deploy training --wait 120
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
| Flag | Padrão | Descrição |
|
|
231
|
+
|------|--------|-----------|
|
|
232
|
+
| `--target-org, -o` | `treino` | Alias da org de treinamento |
|
|
233
|
+
| `--wait, -w` | `240` | Minutos de espera pelo resultado |
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
### `sf pypeline validate prd` — Etapa 4
|
|
238
|
+
|
|
239
|
+
Valida o deploy em produção (sem efetivá-lo). Extrai o Job ID do output e salva em `prd_job_id.txt`. Grava output em `deploy_prd_output.log`.
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
sf pypeline validate prd
|
|
243
|
+
sf pypeline validate prd --target-org minha-producao
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
| Flag | Padrão | Descrição |
|
|
247
|
+
|------|--------|-----------|
|
|
248
|
+
| `--target-org, -o` | `devops` | Alias da org de produção |
|
|
249
|
+
| `--wait, -w` | `240` | Minutos de espera pela validação |
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
### `sf pypeline quickdeploy` — Quick deploy
|
|
254
|
+
|
|
255
|
+
Executa o quick deploy em produção usando o Job ID salvo. O Job ID expira **10 horas** após o validate. Remove `prd_job_id.txt` após sucesso para evitar reuso.
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
# Lê o Job ID de prd_job_id.txt automaticamente
|
|
259
|
+
sf pypeline quickdeploy
|
|
260
|
+
|
|
261
|
+
# Passando o Job ID diretamente (sem precisar do arquivo)
|
|
262
|
+
sf pypeline quickdeploy --job-id 0Af000000000001AAA
|
|
263
|
+
|
|
264
|
+
# Sem confirmação interativa (para CI/CD)
|
|
265
|
+
sf pypeline quickdeploy --no-prompt
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
| Flag | Padrão | Descrição |
|
|
269
|
+
|------|--------|-----------|
|
|
270
|
+
| `--target-org, -o` | `devops` | Alias da org de produção |
|
|
271
|
+
| `--job-id, -j` | lê do arquivo | Job ID da validação |
|
|
272
|
+
| `--wait, -w` | `240` | Minutos de espera |
|
|
273
|
+
| `--no-prompt` | `false` | Pula a confirmação interativa |
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## Fluxo completo de uso
|
|
278
|
+
|
|
279
|
+
### Fluxo padrão (recomendado)
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
# 1. Execute o pipeline completo
|
|
283
|
+
sf pypeline run
|
|
284
|
+
|
|
285
|
+
# 2. Quando o pipeline terminar com sucesso, o Job ID fica salvo.
|
|
286
|
+
# Execute o quick deploy (feito pelo time de PRD):
|
|
287
|
+
sf pypeline quickdeploy
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Fluxo manual (etapa por etapa)
|
|
291
|
+
|
|
292
|
+
Útil para depurar ou reexecutar apenas uma etapa:
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
# Etapa 1: build
|
|
296
|
+
sf pypeline build
|
|
297
|
+
|
|
298
|
+
# Etapa 2: gerar package.xml
|
|
299
|
+
sf pypeline package
|
|
300
|
+
|
|
301
|
+
# Etapa 3: deploy em Training (em background, se quiser)
|
|
302
|
+
sf pypeline deploy training &
|
|
303
|
+
|
|
304
|
+
# Etapa 4: validar em PRD (síncrono)
|
|
305
|
+
sf pypeline validate prd
|
|
306
|
+
|
|
307
|
+
# Após validação bem-sucedida:
|
|
308
|
+
sf pypeline quickdeploy
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Fluxo com rollback
|
|
312
|
+
|
|
313
|
+
Se qualquer etapa do `sf pypeline run` falhar, o `baseline.txt` é restaurado automaticamente para o valor anterior. Nenhuma alteração é promovida.
|
|
314
|
+
|
|
315
|
+
Você pode verificar o motivo da falha nos logs:
|
|
316
|
+
|
|
317
|
+
```bash
|
|
318
|
+
cat deploy_prd_output.log
|
|
319
|
+
cat deploy_training_output.log
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
## Testes
|
|
325
|
+
|
|
326
|
+
### Instalar dependências de teste
|
|
327
|
+
|
|
328
|
+
As dependências de teste (mocha, sinon, chai, nyc) já estão no `package.json`. Basta instalar:
|
|
329
|
+
|
|
330
|
+
```bash
|
|
331
|
+
yarn install
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Rodar os unit tests
|
|
335
|
+
|
|
336
|
+
Rápidos, sem necessidade de org ou internet. Testam toda a lógica do plugin com mocks.
|
|
337
|
+
|
|
338
|
+
```bash
|
|
339
|
+
# Rodar unit tests
|
|
340
|
+
yarn test:only
|
|
341
|
+
|
|
342
|
+
# Rodar com relatório de cobertura (exige >= 90%)
|
|
343
|
+
yarn test:coverage
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
O relatório de cobertura é gerado em `coverage/lcov-report/index.html`.
|
|
347
|
+
|
|
348
|
+
### Rodar todos os testes (unit + lint + type-check)
|
|
349
|
+
|
|
350
|
+
```bash
|
|
351
|
+
yarn test
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Rodar os NUT tests (integração com org real)
|
|
355
|
+
|
|
356
|
+
Os NUT tests rodam o plugin de verdade contra uma org Salesforce. São lentos e opcionais.
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
# NUTs básicos (build + package — não tocam em nenhuma org)
|
|
360
|
+
NUT_ORG_ALIAS=treino yarn test:nuts
|
|
361
|
+
|
|
362
|
+
# Habilitar o validate prd no NUT (cuidado: roda contra a org real)
|
|
363
|
+
RUN_VALIDATE_NUT=1 NUT_ORG_ALIAS=treino yarn test:nuts
|
|
364
|
+
|
|
365
|
+
# Habilitar o quick deploy no NUT (só roda se prd_job_id.txt existir)
|
|
366
|
+
RUN_QUICKDEPLOY_NUT=1 NUT_ORG_ALIAS=treino yarn test:nuts
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
> **Atenção:** nunca sete `RUN_VALIDATE_NUT` ou `RUN_QUICKDEPLOY_NUT` em pipelines de CI/CD automáticos sem revisão, pois esses testes fazem operações reais em orgs Salesforce.
|
|
370
|
+
|
|
371
|
+
### Estrutura dos testes
|
|
372
|
+
|
|
373
|
+
```
|
|
374
|
+
test/
|
|
375
|
+
├── helpers.ts ← stubs reutilizáveis (fs, spawn, git)
|
|
376
|
+
├── unit/
|
|
377
|
+
│ ├── config.test.ts ← readFileTrimmed, gitDiffFiles...
|
|
378
|
+
│ ├── fileUtils.test.ts ← cleanFilename, copyFile
|
|
379
|
+
│ └── commands/pypeline/
|
|
380
|
+
│ ├── build.test.ts
|
|
381
|
+
│ ├── package.test.ts
|
|
382
|
+
│ ├── quickdeploy.test.ts
|
|
383
|
+
│ ├── run.test.ts ← rollback, paralelismo, flags
|
|
384
|
+
│ ├── deploy/training.test.ts
|
|
385
|
+
│ └── validate/prd.test.ts ← extração do Job ID
|
|
386
|
+
└── nuts/
|
|
387
|
+
└── pypeline.nut.ts ← testes contra org real
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
## Estrutura do projeto
|
|
393
|
+
|
|
394
|
+
```
|
|
395
|
+
pypeline/
|
|
396
|
+
├── src/
|
|
397
|
+
│ ├── config.ts ← caminhos, constantes, utilitários git/fs
|
|
398
|
+
│ ├── fileUtils.ts ← lógica de cópia de arquivos Salesforce
|
|
399
|
+
│ └── commands/pypeline/
|
|
400
|
+
│ ├── run.ts ← sf pypeline run
|
|
401
|
+
│ ├── build.ts ← sf pypeline build
|
|
402
|
+
│ ├── package.ts ← sf pypeline package
|
|
403
|
+
│ ├── quickdeploy.ts ← sf pypeline quickdeploy
|
|
404
|
+
│ ├── deploy/
|
|
405
|
+
│ │ └── training.ts ← sf pypeline deploy training
|
|
406
|
+
│ └── validate/
|
|
407
|
+
│ └── prd.ts ← sf pypeline validate prd
|
|
408
|
+
├── messages/
|
|
409
|
+
│ ├── pypeline.run.md
|
|
410
|
+
│ ├── pypeline.build.md
|
|
411
|
+
│ ├── pypeline.package.md
|
|
412
|
+
│ ├── pypeline.quickdeploy.md
|
|
413
|
+
│ ├── pypeline.deploy.training.md
|
|
414
|
+
│ └── pypeline.validate.prd.md
|
|
415
|
+
├── test/
|
|
416
|
+
│ ├── helpers.ts
|
|
417
|
+
│ ├── unit/
|
|
418
|
+
│ └── nuts/
|
|
419
|
+
├── lib/ ← compilado pelo tsc (não editar)
|
|
420
|
+
├── .mocharc.json ← configuração do runner de testes
|
|
421
|
+
├── .nycrc ← configuração de cobertura (mínimo 90%)
|
|
422
|
+
├── package.json
|
|
423
|
+
└── tsconfig.json
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
---
|
|
427
|
+
|
|
428
|
+
## Solução de problemas
|
|
429
|
+
|
|
430
|
+
**`sf: command not found` ao linkar o plugin**
|
|
431
|
+
|
|
432
|
+
Verifique se o sf CLI está instalado globalmente: `npm install -g @salesforce/cli`
|
|
433
|
+
|
|
434
|
+
**`Pasta raiz 'workspace_bash' não encontrada`**
|
|
435
|
+
|
|
436
|
+
O `config.ts` sobe na árvore de diretórios procurando uma pasta chamada `workspace_bash`. Certifique-se de que o plugin está dentro dessa estrutura ou ajuste o `marker` em `src/config.ts`.
|
|
437
|
+
|
|
438
|
+
**`baseline.txt não encontrado`**
|
|
439
|
+
|
|
440
|
+
Crie o arquivo com `git rev-parse HEAD > baseline.txt` na raiz de `workspace_bash`.
|
|
441
|
+
|
|
442
|
+
**Job ID não encontrado após o validate**
|
|
443
|
+
|
|
444
|
+
O Job ID é extraído por regex do output do `sf project deploy validate`. Se o formato do output mudar em versões futuras do sf CLI, ajuste o pattern `0Af[0-9A-Za-z]{15}` em `src/commands/pypeline/validate/prd.ts`.
|
|
445
|
+
|
|
446
|
+
**Cobertura abaixo de 90%**
|
|
447
|
+
|
|
448
|
+
Rode `yarn test:coverage` para ver o relatório detalhado e identificar quais linhas não estão cobertas. O limite mínimo está configurado em `.nycrc`.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
2
|
+
export type PypelineBuildResult = {
|
|
3
|
+
commitHash: string;
|
|
4
|
+
novoBaseline: string;
|
|
5
|
+
added: string[];
|
|
6
|
+
modified: string[];
|
|
7
|
+
deleted: string[];
|
|
8
|
+
};
|
|
9
|
+
export default class PypelineBuild extends SfCommand<PypelineBuildResult> {
|
|
10
|
+
static readonly summary: string;
|
|
11
|
+
static readonly description: string;
|
|
12
|
+
static readonly examples: string[];
|
|
13
|
+
static readonly flags: {
|
|
14
|
+
branch: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
|
+
};
|
|
17
|
+
run(): Promise<PypelineBuildResult>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { execSync, spawnSync } from 'node:child_process';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
|
|
5
|
+
import { Messages } from '@salesforce/core';
|
|
6
|
+
import { BASELINE_FILE, BRANCH, BUILD_DIR, PROJECT_DIR, PROJECT_NAME, SCRIPT_DIR, fileExists, readFileTrimmed, writeFile, gitDiffFiles, } from '../../config.js';
|
|
7
|
+
import { copyFile } from '../../fileUtils.js';
|
|
8
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
9
|
+
const messages = Messages.loadMessages('pypeline', 'pypeline.build');
|
|
10
|
+
export default class PypelineBuild extends SfCommand {
|
|
11
|
+
static summary = messages.getMessage('summary');
|
|
12
|
+
static description = messages.getMessage('description');
|
|
13
|
+
static examples = messages.getMessages('examples');
|
|
14
|
+
static flags = {
|
|
15
|
+
branch: Flags.string({
|
|
16
|
+
char: 'b',
|
|
17
|
+
summary: messages.getMessage('flags.branch.summary'),
|
|
18
|
+
default: BRANCH,
|
|
19
|
+
}),
|
|
20
|
+
'dry-run': Flags.boolean({
|
|
21
|
+
summary: messages.getMessage('flags.dry-run.summary'),
|
|
22
|
+
default: false,
|
|
23
|
+
}),
|
|
24
|
+
};
|
|
25
|
+
async run() {
|
|
26
|
+
const { flags } = await this.parse(PypelineBuild);
|
|
27
|
+
const branch = flags['branch'];
|
|
28
|
+
const dryRun = flags['dry-run'];
|
|
29
|
+
this.log(`SCRIPT_DIR : ${SCRIPT_DIR}`);
|
|
30
|
+
this.log(`PROJECT_DIR : ${PROJECT_DIR()}`);
|
|
31
|
+
if (!dryRun) {
|
|
32
|
+
const gen = spawnSync('sf', ['project', 'generate', '--name', PROJECT_NAME, '--output-dir', PROJECT_DIR()], {
|
|
33
|
+
encoding: 'utf8',
|
|
34
|
+
stdio: 'inherit',
|
|
35
|
+
});
|
|
36
|
+
if (gen.status !== 0)
|
|
37
|
+
this.error('Falha ao gerar estrutura do projeto sf.');
|
|
38
|
+
}
|
|
39
|
+
if (!fileExists(BASELINE_FILE()))
|
|
40
|
+
this.error('baseline.txt não encontrado!');
|
|
41
|
+
const commitHash = readFileTrimmed(BASELINE_FILE());
|
|
42
|
+
this.log(`Baseline : ${commitHash}`);
|
|
43
|
+
if (!dryRun) {
|
|
44
|
+
for (const cmd of [
|
|
45
|
+
['git', 'checkout', branch ?? BRANCH],
|
|
46
|
+
['git', 'fetch'],
|
|
47
|
+
['git', 'pull'],
|
|
48
|
+
]) {
|
|
49
|
+
const r = spawnSync(cmd[0], cmd.slice(1), { stdio: 'inherit' });
|
|
50
|
+
if (r.status !== 0)
|
|
51
|
+
this.error(`Falha ao executar: ${cmd.join(' ')}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const commits = execSync(`git rev-list ${commitHash}..HEAD --oneline`, { encoding: 'utf8' });
|
|
55
|
+
writeFile(path.join(PROJECT_DIR(), 'commitlist.txt'), commits);
|
|
56
|
+
if (fs.existsSync(BUILD_DIR()))
|
|
57
|
+
fs.rmSync(BUILD_DIR(), { recursive: true, force: true });
|
|
58
|
+
fs.mkdirSync(BUILD_DIR(), { recursive: true });
|
|
59
|
+
const diff = gitDiffFiles(commitHash);
|
|
60
|
+
writeFile(path.join(PROJECT_DIR(), 'lista_arquivos_naodeletados.txt'), diff.notDeleted.join('\n'));
|
|
61
|
+
writeFile(path.join(PROJECT_DIR(), 'lista_arquivos_deletados.txt'), diff.deleted.join('\n'));
|
|
62
|
+
writeFile(path.join(PROJECT_DIR(), 'lista_arquivos_adicionados.txt'), diff.added.join('\n'));
|
|
63
|
+
writeFile(path.join(PROJECT_DIR(), 'lista_arquivos_modificados.txt'), diff.modified.join('\n'));
|
|
64
|
+
this.log('Arquivos modificados ou adicionados:');
|
|
65
|
+
for (const file of diff.notDeleted) {
|
|
66
|
+
this.log(` Arquivo a ser avaliado: ${file}`);
|
|
67
|
+
if (!dryRun) {
|
|
68
|
+
try {
|
|
69
|
+
copyFile(file, BUILD_DIR());
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
this.warn(`Erro ao copiar '${file}': ${err.message}`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const novoBaseline = execSync('git rev-parse HEAD', { encoding: 'utf8' }).trim();
|
|
77
|
+
this.log(`[INFO] Novo baseline calculado: ${novoBaseline}`);
|
|
78
|
+
this.log('[INFO] baseline.txt será atualizado pelo comando run após validate PRD.');
|
|
79
|
+
process.env['NOVO_BASELINE'] = novoBaseline;
|
|
80
|
+
const branchInfo = execSync('git branch', { encoding: 'utf8' });
|
|
81
|
+
this.log(`Branches:\n${branchInfo}`);
|
|
82
|
+
this.log(`Build project criado em ${BUILD_DIR()}.`);
|
|
83
|
+
return { commitHash, novoBaseline, added: diff.added, modified: diff.modified, deleted: diff.deleted };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/commands/pypeline/build.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,62 @@
|
|
|
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
|
+
if (proc.stderr)
|
|
48
|
+
proc.stderr.on('data', (chunk) => {
|
|
49
|
+
const text = chunk.toString();
|
|
50
|
+
process.stderr.write(text);
|
|
51
|
+
log.write(text);
|
|
52
|
+
});
|
|
53
|
+
proc.on('close', (code) => { log.close(); resolve(code ?? 1); });
|
|
54
|
+
});
|
|
55
|
+
if (exitCode !== 0) {
|
|
56
|
+
this.error(`Deploy em Training falhou com exit code ${exitCode}.`);
|
|
57
|
+
}
|
|
58
|
+
this.log('Deploy em Training concluído com sucesso.');
|
|
59
|
+
return { success: true, logPath };
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=training.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"training.js","sourceRoot":"","sources":["../../../../src/commands/pypeline/deploy/training.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
2
|
+
export type PypelinePackageResult = {
|
|
3
|
+
success: boolean;
|
|
4
|
+
buildDir: string;
|
|
5
|
+
};
|
|
6
|
+
export default class PypelinePackage extends SfCommand<PypelinePackageResult> {
|
|
7
|
+
static readonly summary: string;
|
|
8
|
+
static readonly description: string;
|
|
9
|
+
static readonly examples: string[];
|
|
10
|
+
run(): Promise<PypelinePackageResult>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { SfCommand } from '@salesforce/sf-plugins-core';
|
|
3
|
+
import { Messages } from '@salesforce/core';
|
|
4
|
+
import { BUILD_DIR } from '../../config.js';
|
|
5
|
+
Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
|
|
6
|
+
const messages = Messages.loadMessages('pypeline', 'pypeline.package');
|
|
7
|
+
export default class PypelinePackage extends SfCommand {
|
|
8
|
+
static summary = messages.getMessage('summary');
|
|
9
|
+
static description = messages.getMessage('description');
|
|
10
|
+
static examples = messages.getMessages('examples');
|
|
11
|
+
async run() {
|
|
12
|
+
const buildDir = BUILD_DIR();
|
|
13
|
+
this.log('Gerando package.xml...');
|
|
14
|
+
const exitCode = await new Promise((resolve) => {
|
|
15
|
+
const proc = spawn('sf', ['project', 'generate', 'manifest', '--source-dir', buildDir], {
|
|
16
|
+
stdio: 'inherit',
|
|
17
|
+
});
|
|
18
|
+
proc.on('close', (code) => resolve(code ?? 1));
|
|
19
|
+
});
|
|
20
|
+
if (exitCode !== 0) {
|
|
21
|
+
this.error('Falha ao gerar package.xml.');
|
|
22
|
+
}
|
|
23
|
+
this.log('package.xml gerado com sucesso.');
|
|
24
|
+
return { success: true, buildDir };
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=package.js.map
|