autoforce 0.1.22 → 0.1.24
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/.autoforce.json +1 -1
- package/CHANGELOG.md +14 -0
- package/README.md +30 -8
- package/lib/auto.d.ts +1 -1
- package/lib/auto.js +15 -16
- package/lib/helpers/context.d.ts +3 -1
- package/lib/helpers/context.js +27 -14
- package/lib/helpers/github-project-graphql.d.ts +1 -0
- package/lib/helpers/github-project-graphql.js +15 -0
- package/lib/helpers/gitlab-graphql.d.ts +1 -0
- package/lib/helpers/gitlab-graphql.js +4 -0
- package/lib/helpers/taskFunctions.js +8 -2
- package/lib/helpers/util.d.ts +1 -0
- package/lib/helpers/util.js +4 -3
- package/models/dev/npm/tasks/publish.json +1 -1
- package/models/dev/npm/tasks/start.json +3 -3
- package/package.json +1 -1
package/.autoforce.json
CHANGED
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# Versiones
|
2
2
|
|
3
|
+
0.1.23
|
4
|
+
## Version 0.1.23
|
5
|
+
- Fecha:
|
6
|
+
- Paquete: [Descargar](https://www.npmjs.com/package/autoforce/v/0.1.23)
|
7
|
+
- Cambios:
|
8
|
+
* Bugfixing para la suit de test autoforce-test
|
9
|
+
|
10
|
+
## Version 0.1.22
|
11
|
+
- Fecha:
|
12
|
+
- Paquete: [Descargar](https://www.npmjs.com/package/autoforce/v/0.1.22)
|
13
|
+
- Cambios:
|
14
|
+
* [publish] que cierre el milestone de la version
|
15
|
+
- https://github.com/sebastianclaros/autoforce/issues/35
|
16
|
+
|
3
17
|
## Version 0.1.20
|
4
18
|
- Fecha:
|
5
19
|
- Paquete: [Descargar](https://www.npmjs.com/package/autoforce/v/0.1.20)
|
package/README.md
CHANGED
@@ -35,19 +35,32 @@ En cada una de ellas buscamos automatizar o integrar las siguientes gestiones:
|
|
35
35
|
- Calidad de codigo (PMD)
|
36
36
|
- Uso de IA ( OpenAI, )
|
37
37
|
|
38
|
+
## Tipos de Modelos
|
39
|
+
|
40
|
+
Al principio habia pensando en una lista de modelos, ejemplo paquetes de appexchange y otro para proyectos sobre salesforce.
|
41
|
+
|
42
|
+
Pero al final vi que los modelos son combinaciones de acuerdo a las siguientes variables:
|
43
|
+
- Branching strategy: En este sentido, el start y finish van a hacer task distintas, si quiero un gitflow o main
|
44
|
+
- Tipo de desarrollo: Si estoy desarrollando paquetes o usango scratch en el start voy a buscar que me arme un ambiente nuevo
|
45
|
+
- Tipo de Projecto: Si el projecto maneja milestones como releases, cambian o se agregan mas preguntas en algunos steps
|
46
|
+
- Modelo de documentacion: La documentacion estaria muy relacionada con el tipo de desarrollo, pero quedo como una variable aparte por orden.
|
47
|
+
|
48
|
+
|
38
49
|
## Roadmap Status
|
39
50
|
|
40
|
-
1.
|
41
|
-
-
|
51
|
+
1. Implementaciones
|
52
|
+
- "Procesos de Negocio en Clientes de Salesforce": 70%
|
42
53
|
Salesforce: Scratchs con Tracking y deploys usando sf cli
|
43
54
|
Documentacion: Markdowns de Procesos con Github pages
|
44
|
-
Gestion de Proyecto:
|
45
|
-
Source Control: Github
|
55
|
+
Gestion de Proyecto: Project con milestones
|
46
56
|
Branching Strategy: Github workflow
|
47
57
|
|
48
|
-
-
|
58
|
+
- "Desarrollo de Producto": 30%
|
59
|
+
Salesforce: Scratchs con Tracking y deploys con second generation package
|
60
|
+
Documentacion: Markdowns de Procesos con Github pages
|
61
|
+
Gestion de Proyecto: Project con milestones
|
62
|
+
Branching Strategy: Gitflow workflow
|
49
63
|
|
50
|
-
- [Custom] "Modelo personalizado"
|
51
64
|
|
52
65
|
2. Github Services
|
53
66
|
- Github: Listo
|
@@ -72,9 +85,17 @@ En cada una de ellas buscamos automatizar o integrar las siguientes gestiones:
|
|
72
85
|
- Documentation: 0%
|
73
86
|
|
74
87
|
|
88
|
+
## Repositorio de Ejemplo
|
89
|
+
En el siguiente [repositorio](https://github.com/sebastianclaros/autoforce-test) tomamos como ejemplo un proyecto de Salesforce.
|
90
|
+
En la carpeta scripts/test hay una serie de comandos (all.sh), que hace de forma autamtizada lo siguiente:
|
91
|
+
|
92
|
+
* Hace un upgrade de autoforce
|
93
|
+
* Crea un Milestone representando un release nuevo
|
94
|
+
* Crea 3 issues dentro de ese Milestone
|
75
95
|
|
76
96
|
|
77
|
-
##
|
97
|
+
## Uso
|
98
|
+
|
78
99
|
Una vez instalado se puede crear scripts a medida o bien ejecutar
|
79
100
|
|
80
101
|
```
|
@@ -102,7 +123,8 @@ https://github.com/sebastianclaros/autoforce-test
|
|
102
123
|
La guia del readme sirve de ejemplo.
|
103
124
|
|
104
125
|
|
105
|
-
|
126
|
+
|
127
|
+
## Testear una version en forma local
|
106
128
|
|
107
129
|
Para hacer un testeo local se puede generar una version nueva
|
108
130
|
|
package/lib/auto.d.ts
CHANGED
package/lib/auto.js
CHANGED
@@ -27,23 +27,22 @@ export default async function main() {
|
|
27
27
|
try {
|
28
28
|
const config = getConfigFromArgs(process.argv.slice(2));
|
29
29
|
const taskCommandKeys = Object.keys(taskCommand);
|
30
|
-
if (taskCommandKeys.includes(config.command)) {
|
31
|
-
const tasks = getTasks(config.subfolder);
|
32
|
-
const taskName = await askForTaskName(config.taskName, tasks);
|
33
|
-
if (taskName) {
|
34
|
-
const task = tasks[taskName];
|
35
|
-
context.options = config.arguments && task.arguments ? { ...config.options, ...createObject(task.arguments, config.arguments) } : config.options;
|
36
|
-
// Valida los json de task y subtask
|
37
|
-
if (validateTask(task)) {
|
38
|
-
await taskCommand[config.command](task, context.options);
|
39
|
-
}
|
40
|
-
else {
|
41
|
-
logError('Verifique que los json de task y subtask esten validos');
|
42
|
-
}
|
43
|
-
}
|
44
|
-
}
|
45
|
-
else {
|
30
|
+
if (!taskCommandKeys.includes(config.command)) {
|
46
31
|
await proxyCommand[config.command](config.taskName, config.options);
|
32
|
+
return true;
|
33
|
+
}
|
34
|
+
const tasks = getTasks(config.subfolder);
|
35
|
+
const taskName = await askForTaskName(config.taskName, tasks);
|
36
|
+
if (taskName) {
|
37
|
+
const task = tasks[taskName];
|
38
|
+
context.options = config.arguments && task.arguments ? { ...config.options, ...createObject(task.arguments, config.arguments) } : config.options;
|
39
|
+
// Valida los json de task y subtask
|
40
|
+
if (validateTask(task)) {
|
41
|
+
await taskCommand[config.command](task, context.options);
|
42
|
+
}
|
43
|
+
else {
|
44
|
+
logError('Verifique que los json de task y subtask esten validos');
|
45
|
+
}
|
47
46
|
}
|
48
47
|
}
|
49
48
|
catch (error) {
|
package/lib/helpers/context.d.ts
CHANGED
@@ -23,6 +23,7 @@ declare class Context implements IObjectRecord {
|
|
23
23
|
devModel: string | undefined;
|
24
24
|
gitModel: string | undefined;
|
25
25
|
docModel: string | undefined;
|
26
|
+
errorMessage: string;
|
26
27
|
projectModel: string | undefined;
|
27
28
|
gitServices: GitServices;
|
28
29
|
isGitApi: boolean;
|
@@ -69,7 +70,8 @@ declare class Context implements IObjectRecord {
|
|
69
70
|
loadProjectApi(): void;
|
70
71
|
loadGitApi(): void;
|
71
72
|
loadPackage(): void;
|
72
|
-
|
73
|
+
createConfig(): Promise<boolean | undefined>;
|
74
|
+
loadConfig(): true | undefined;
|
73
75
|
init(): void;
|
74
76
|
get targetOrg(): string;
|
75
77
|
get existBranchScratch(): boolean;
|
package/lib/helpers/context.js
CHANGED
@@ -30,7 +30,7 @@ const filterProcesses = (fullPath) => fullPath.endsWith(".md"); // && !fullPath.
|
|
30
30
|
const ISSUES_TYPES = [{ value: 'feature', title: 'feature' }, { value: 'bug', title: 'bug' }, { value: 'documentation', title: 'documentation' }, { value: 'automation', title: 'automation' }];
|
31
31
|
function searchInFolderHierarchy(element, parentFolder) {
|
32
32
|
if (fs.existsSync(`${parentFolder}/${element}`)) {
|
33
|
-
return
|
33
|
+
return parentFolder;
|
34
34
|
}
|
35
35
|
else {
|
36
36
|
const lastIndex = parentFolder.lastIndexOf('/');
|
@@ -46,9 +46,10 @@ function searchInFolderHierarchy(element, parentFolder) {
|
|
46
46
|
function getDataFromPackage() {
|
47
47
|
const data = {};
|
48
48
|
try {
|
49
|
-
const
|
50
|
-
|
51
|
-
|
49
|
+
const PROJECT_FOLDER = searchInFolderHierarchy('package.json', process.cwd() || '.');
|
50
|
+
const filename = `${PROJECT_FOLDER}/package.json`;
|
51
|
+
if (!fs.existsSync(filename)) {
|
52
|
+
throw new Error("No se encontro el package.json en " + PROJECT_FOLDER);
|
52
53
|
}
|
53
54
|
const content = fs.readFileSync(filename, "utf8");
|
54
55
|
const packageJson = JSON.parse(content);
|
@@ -89,6 +90,7 @@ class Context {
|
|
89
90
|
devModel; // Default Model de commands
|
90
91
|
gitModel;
|
91
92
|
docModel;
|
93
|
+
errorMessage = '';
|
92
94
|
projectModel;
|
93
95
|
gitServices = GitServices.None;
|
94
96
|
isGitApi = false;
|
@@ -234,7 +236,7 @@ class Context {
|
|
234
236
|
this.repositoryOwner = data.repositoryOwner;
|
235
237
|
this.repositoryRepo = data.repositoryRepo;
|
236
238
|
}
|
237
|
-
async
|
239
|
+
async createConfig() {
|
238
240
|
if (!fs.existsSync(CONFIG_FILE)) {
|
239
241
|
logWarning('Bienvenido! La herramienta Autoforce necesita un primer paso de configuracion antes de usarla.');
|
240
242
|
logWarning('- Podes usar el asistente ejecutando npx autoforce config');
|
@@ -252,19 +254,24 @@ class Context {
|
|
252
254
|
}
|
253
255
|
return false;
|
254
256
|
}
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
257
|
+
}
|
258
|
+
loadConfig() {
|
259
|
+
if (fs.existsSync(CONFIG_FILE)) {
|
260
|
+
const content = fs.readFileSync(CONFIG_FILE, "utf8");
|
261
|
+
try {
|
262
|
+
const config = JSON.parse(content);
|
263
|
+
for (const key in config) {
|
264
|
+
this.set(key, config[key]);
|
265
|
+
}
|
260
266
|
}
|
267
|
+
catch {
|
268
|
+
throw new Error(`Verifique que el ${CONFIG_FILE} sea json valido`);
|
269
|
+
}
|
270
|
+
return true;
|
261
271
|
}
|
262
|
-
catch {
|
263
|
-
throw new Error(`Verifique que el ${CONFIG_FILE} sea json valido`);
|
264
|
-
}
|
265
|
-
return true;
|
266
272
|
}
|
267
273
|
init() {
|
274
|
+
this.createConfig();
|
268
275
|
this.loadProjectApi();
|
269
276
|
this.loadGitApi();
|
270
277
|
//
|
@@ -447,6 +454,12 @@ class Context {
|
|
447
454
|
return this.newBranchName;
|
448
455
|
}
|
449
456
|
async askFornewIssueNumber() {
|
457
|
+
if (this.options.issue && this.projectApi) {
|
458
|
+
const issues = await this.projectApi.searchIssues(this.options.issue);
|
459
|
+
if (issues.length === 1) {
|
460
|
+
return `${issues[0].number}`;
|
461
|
+
}
|
462
|
+
}
|
450
463
|
const answer = await prompts([
|
451
464
|
{
|
452
465
|
type: "text",
|
@@ -49,6 +49,7 @@ export declare class GitHubProjectApi extends GitHubApi implements IProjectApi {
|
|
49
49
|
id: string;
|
50
50
|
title: string;
|
51
51
|
}[]>;
|
52
|
+
searchIssues(title: string): Promise<IIssueObject[]>;
|
52
53
|
getIssuesWithFilter(filterBy: string): Promise<{
|
53
54
|
id: string;
|
54
55
|
title: string;
|
@@ -213,6 +213,21 @@ export class GitHubProjectApi extends GitHubApi {
|
|
213
213
|
async getIssues() {
|
214
214
|
return await this.getIssuesWithFilter(`{ states: OPEN }`);
|
215
215
|
}
|
216
|
+
async searchIssues(title) {
|
217
|
+
const query = `query getIssues() {
|
218
|
+
search(query: "repo:${this.repoVar.owner}/${this.repoVar.repo} in:title ${title}", type: ISSUE, first: 10) {
|
219
|
+
nodes {
|
220
|
+
... on Issue {
|
221
|
+
id
|
222
|
+
number
|
223
|
+
title
|
224
|
+
}
|
225
|
+
}
|
226
|
+
}
|
227
|
+
}`;
|
228
|
+
const { search } = await this.graphqlAuth(query, this.repoVar);
|
229
|
+
return search.nodes;
|
230
|
+
}
|
216
231
|
async getIssuesWithFilter(filterBy) {
|
217
232
|
const query = `
|
218
233
|
query getIssues($owner:String!, $repo: String!) {
|
@@ -24,6 +24,7 @@ export declare class GitLabApi implements IGitApi, IProjectApi {
|
|
24
24
|
state: string;
|
25
25
|
url: string;
|
26
26
|
}>;
|
27
|
+
searchIssues(title: string): Promise<IIssueObject[]>;
|
27
28
|
updateMilestone(title: string, state?: string, description?: string, dueOn?: string): Promise<{
|
28
29
|
id: string;
|
29
30
|
title: string;
|
@@ -35,6 +35,10 @@ export class GitLabApi {
|
|
35
35
|
console.log(title, state, description, dueOn);
|
36
36
|
return { id: '', title: '', state: '', url: '' };
|
37
37
|
}
|
38
|
+
async searchIssues(title) {
|
39
|
+
console.log(title);
|
40
|
+
return [];
|
41
|
+
}
|
38
42
|
async updateMilestone(title, state = 'open', description, dueOn) {
|
39
43
|
console.log(title, state, description, dueOn);
|
40
44
|
return { id: '', title: '', state: '', url: '' };
|
@@ -316,7 +316,6 @@ export const taskFunctions = {
|
|
316
316
|
if (context.projectApi === undefined || context.gitApi === undefined) {
|
317
317
|
return false;
|
318
318
|
}
|
319
|
-
console.log(title, state, description, dueOn);
|
320
319
|
const result = await context.gitApi.updateMilestone(title, state, description, dueOn);
|
321
320
|
return result?.id ? true : false;
|
322
321
|
},
|
@@ -376,14 +375,21 @@ export const taskFunctions = {
|
|
376
375
|
},
|
377
376
|
async validateIssue(issueNumber, states) {
|
378
377
|
if (context.projectApi === undefined) {
|
378
|
+
context.errorMessage = 'context.projectApi esta undefined';
|
379
379
|
return false;
|
380
380
|
}
|
381
381
|
const issue = await context.projectApi.getIssue(issueNumber);
|
382
382
|
if (!issue.state) {
|
383
|
+
context.errorMessage = 'El state del issue es undefined';
|
383
384
|
return false;
|
384
385
|
}
|
385
386
|
const arrayStates = states.toLocaleLowerCase().replace(' ', '').split(',');
|
386
|
-
|
387
|
+
const validate = arrayStates.includes(issue.state.toLocaleLowerCase().replace(' ', ''));
|
388
|
+
if (!validate) {
|
389
|
+
context.errorMessage = `El state del issue es "${issue.state}", mientras deberia ser ${states}`;
|
390
|
+
return false;
|
391
|
+
}
|
392
|
+
return true;
|
387
393
|
},
|
388
394
|
async validaNoseaBranchActual(newBranchName) {
|
389
395
|
return getBranchName() !== newBranchName;
|
package/lib/helpers/util.d.ts
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import { Choice } from "prompts";
|
2
2
|
import { AnyValue, CommandOptions } from "../types/auto.js";
|
3
3
|
export declare const WORKING_FOLDER: string;
|
4
|
+
export declare const PROJECT_FOLDER: string;
|
4
5
|
export declare const CONFIG_FILE: string;
|
5
6
|
export declare const DICTIONARY_FOLDER: string;
|
6
7
|
export declare const filterJson: (fullPath: string) => boolean;
|
package/lib/helpers/util.js
CHANGED
@@ -3,9 +3,10 @@ import { fileURLToPath } from 'url';
|
|
3
3
|
import prompts from "prompts";
|
4
4
|
import context, { ProjectServices, GitServices } from "./context.js";
|
5
5
|
import { logInfo, logWarning } from "./color.js";
|
6
|
-
const MODELS_FOLDER = searchInFolderHierarchy('models', fileURLToPath(import.meta.url));
|
6
|
+
const MODELS_FOLDER = searchInFolderHierarchy('models', fileURLToPath(import.meta.url)) + '/models';
|
7
7
|
export const WORKING_FOLDER = process.env.INIT_CWD || ".";
|
8
|
-
export const
|
8
|
+
export const PROJECT_FOLDER = searchInFolderHierarchy('package.json', WORKING_FOLDER);
|
9
|
+
export const CONFIG_FILE = PROJECT_FOLDER + '/.autoforce.json';
|
9
10
|
export const DICTIONARY_FOLDER = process.cwd() + "/docs"; // context.dictionaryFolder;
|
10
11
|
export const filterJson = (fullPath) => fullPath.endsWith(".json");
|
11
12
|
export const filterDirectory = (fullPath) => fs.lstatSync(fullPath).isDirectory();
|
@@ -259,7 +260,7 @@ export function addNewItems(baseArray, newArray) {
|
|
259
260
|
}
|
260
261
|
export function searchInFolderHierarchy(element, parentFolder) {
|
261
262
|
if (fs.existsSync(`${parentFolder}/${element}`)) {
|
262
|
-
return
|
263
|
+
return parentFolder;
|
263
264
|
}
|
264
265
|
else {
|
265
266
|
const lastIndex = parentFolder.lastIndexOf('/');
|
@@ -8,8 +8,8 @@
|
|
8
8
|
"steps": [
|
9
9
|
{ "name": "Actualiza la version", "function": "storeConfig", "arguments": ["version", "${newVersion}"] },
|
10
10
|
{ "name": "Paquetiza", "subtask": "pack" },
|
11
|
+
{ "name": "Salida para el Changelog.md", "task": "list", "arguments": {"filter": "milestone", "template": "changelog", "milestone": "v${newVersion}"} },
|
11
12
|
{ "name": "Publica", "command": "yarn publish ", "arguments": {"--new-version": "${newVersion}"} },
|
12
|
-
{ "name": "Salida para el Changelog.md", "task": "list", "arguments": {"filter": "milestone", "template": "changelog", "milestone": "${newVersion}"} },
|
13
13
|
{ "name": "Actualiza el milestone", "function": "updateMilestone", "arguments": ["v${newVersion}", "closed"] }
|
14
14
|
]
|
15
15
|
}
|
@@ -7,9 +7,9 @@
|
|
7
7
|
{
|
8
8
|
"name": "validate issue",
|
9
9
|
"function": "validateIssue",
|
10
|
-
"arguments": ["${newIssueNumber}", "
|
11
|
-
"description": "Valida que Issue este en la Columna
|
12
|
-
"errorMessage": "Por favor verifique que el issue ${newIssueNumber} este en la columna
|
10
|
+
"arguments": ["${newIssueNumber}", "Todo"],
|
11
|
+
"description": "Valida que Issue este en la Columna Todo",
|
12
|
+
"errorMessage": "Por favor verifique que el issue ${newIssueNumber} este en la columna Todo. \n ${errorMessage}"
|
13
13
|
},
|
14
14
|
{
|
15
15
|
"name": "check Issue type based on Labels",
|