@atomicsolutions/proton5-cli 5.0.1

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.
Files changed (77) hide show
  1. package/README.md +590 -0
  2. package/bin/dev.cmd +3 -0
  3. package/bin/dev.js +5 -0
  4. package/bin/run.cmd +3 -0
  5. package/bin/run.js +5 -0
  6. package/dist/commands/config/add.d.ts +14 -0
  7. package/dist/commands/config/add.js +122 -0
  8. package/dist/commands/config/edit.d.ts +15 -0
  9. package/dist/commands/config/edit.js +63 -0
  10. package/dist/commands/config/list.d.ts +6 -0
  11. package/dist/commands/config/list.js +31 -0
  12. package/dist/commands/config/remove.d.ts +9 -0
  13. package/dist/commands/config/remove.js +35 -0
  14. package/dist/commands/connect.d.ts +9 -0
  15. package/dist/commands/connect.js +41 -0
  16. package/dist/commands/disconnect.d.ts +9 -0
  17. package/dist/commands/disconnect.js +30 -0
  18. package/dist/commands/runner/list-run.d.ts +6 -0
  19. package/dist/commands/runner/list-run.js +71 -0
  20. package/dist/commands/runner/status.d.ts +6 -0
  21. package/dist/commands/runner/status.js +24 -0
  22. package/dist/commands/runner/stop-run.d.ts +9 -0
  23. package/dist/commands/runner/stop-run.js +34 -0
  24. package/dist/commands/settings/index.d.ts +6 -0
  25. package/dist/commands/settings/index.js +25 -0
  26. package/dist/commands/settings/set.d.ts +10 -0
  27. package/dist/commands/settings/set.js +39 -0
  28. package/dist/commands/settings/unset.d.ts +10 -0
  29. package/dist/commands/settings/unset.js +35 -0
  30. package/dist/core/fileSystem/index.d.ts +10 -0
  31. package/dist/core/fileSystem/index.js +107 -0
  32. package/dist/core/manager/index.d.ts +31 -0
  33. package/dist/core/manager/index.js +287 -0
  34. package/dist/core/proton/api.d.ts +7 -0
  35. package/dist/core/proton/api.js +122 -0
  36. package/dist/core/proton/maven.d.ts +5 -0
  37. package/dist/core/proton/maven.js +74 -0
  38. package/dist/core/proton/npm.d.ts +1 -0
  39. package/dist/core/proton/npm.js +22 -0
  40. package/dist/core/proton/playwright.d.ts +5 -0
  41. package/dist/core/proton/playwright.js +47 -0
  42. package/dist/core/proton/pyTest.d.ts +5 -0
  43. package/dist/core/proton/pyTest.js +52 -0
  44. package/dist/core/proton/vbs.d.ts +5 -0
  45. package/dist/core/proton/vbs.js +46 -0
  46. package/dist/core/runner/index.d.ts +16 -0
  47. package/dist/core/runner/index.js +76 -0
  48. package/dist/core/services/api.d.ts +2 -0
  49. package/dist/core/services/api.js +20 -0
  50. package/dist/core/socket/index.d.ts +2 -0
  51. package/dist/core/socket/index.js +99 -0
  52. package/dist/core/store/index.d.ts +14 -0
  53. package/dist/core/store/index.js +212 -0
  54. package/dist/core/system/index.d.ts +12 -0
  55. package/dist/core/system/index.js +48 -0
  56. package/dist/daemon/index.d.ts +1 -0
  57. package/dist/daemon/index.js +5 -0
  58. package/dist/daemon/server.d.ts +1 -0
  59. package/dist/daemon/server.js +40 -0
  60. package/dist/daemon/state.d.ts +7 -0
  61. package/dist/daemon/state.js +15 -0
  62. package/dist/index.d.ts +1 -0
  63. package/dist/index.js +1 -0
  64. package/dist/ipc/client.d.ts +1 -0
  65. package/dist/ipc/client.js +16 -0
  66. package/dist/ipc/ensureDaemon.d.ts +1 -0
  67. package/dist/ipc/ensureDaemon.js +42 -0
  68. package/dist/ipc/protocol.d.ts +14 -0
  69. package/dist/ipc/protocol.js +1 -0
  70. package/dist/shared/constants.d.ts +4 -0
  71. package/dist/shared/constants.js +4 -0
  72. package/dist/shared/socketPath.d.ts +1 -0
  73. package/dist/shared/socketPath.js +5 -0
  74. package/dist/shared/types.d.ts +130 -0
  75. package/dist/shared/types.js +1 -0
  76. package/oclif.manifest.json +409 -0
  77. package/package.json +86 -0
@@ -0,0 +1,35 @@
1
+ import { Command, Flags } from '@oclif/core';
2
+ import { getStoreValue, setStoreValue } from '../../core/store/index.js';
3
+ import ora from 'ora';
4
+ export default class SettingsUnset extends Command {
5
+ static description = 'Unset Proton server settings';
6
+ static examples = [
7
+ '<%= config.bin %> <%= command.id %>',
8
+ ];
9
+ static flags = {
10
+ mavenPath: Flags.boolean({
11
+ description: 'Caminho do Maven (ex: C:\\maven\\bin\\mvn.cmd)',
12
+ required: false
13
+ }),
14
+ parallelRuns: Flags.boolean({
15
+ description: 'Número de execuções paralelas',
16
+ required: false
17
+ })
18
+ };
19
+ async run() {
20
+ const { flags } = await this.parse(SettingsUnset);
21
+ const spinner = ora('Updating settings...').start();
22
+ try {
23
+ const settings = getStoreValue('settings');
24
+ const newSettings = {
25
+ mavenPath: flags.mavenPath ? "" : settings.mavenPath,
26
+ parallelRuns: flags.parallelRuns ? 1 : settings.parallelRuns,
27
+ };
28
+ setStoreValue('settings', newSettings);
29
+ spinner.succeed('Settings redefined successfully');
30
+ }
31
+ catch (err) {
32
+ spinner.fail('Failed to update settings');
33
+ }
34
+ }
35
+ }
@@ -0,0 +1,10 @@
1
+ export declare function dirExists(dir: string): boolean;
2
+ export declare function cloneRepo(authorization: string, repo: string, branch: string, dir: string): Promise<void>;
3
+ /**
4
+ * Verifica se o arquivo TestProtonScript.java existe no diretório do repositório local.
5
+ * @param repoLocalDir
6
+ * @returns
7
+ */
8
+ export declare function checkIfTestProtonScriptExists(repoLocalDir: string): boolean;
9
+ export declare function getRepoRunMethod(dir: string): "" | "maven" | "sap" | "pyTest" | "playwright";
10
+ export declare function initializeFolders(): void;
@@ -0,0 +1,107 @@
1
+ import { simpleGit } from 'simple-git';
2
+ import fs, { readdirSync, statSync } from "fs";
3
+ import os from 'os';
4
+ import { join } from 'path';
5
+ export function dirExists(dir) {
6
+ const homedir = os.homedir();
7
+ return fs.existsSync(homedir + '/.proton-runner-repo/' + dir);
8
+ }
9
+ export async function cloneRepo(authorization, repo, branch, dir) {
10
+ const homedir = os.homedir();
11
+ const git = simpleGit();
12
+ const url = `https://${authorization}@github.com/${repo}.git`;
13
+ await git.clone(url, homedir + '/.proton-runner-repo/' + dir, ['-b', branch, '-c', 'core.longpaths=true']);
14
+ }
15
+ /**
16
+ * Verifica se o arquivo TestProtonScript.java existe no diretório do repositório local.
17
+ * @param repoLocalDir
18
+ * @returns
19
+ */
20
+ export function checkIfTestProtonScriptExists(repoLocalDir) {
21
+ const searchFile = 'TestProtonScript.java';
22
+ function findFile(dir) {
23
+ const files = readdirSync(dir);
24
+ for (const file of files) {
25
+ const fullPath = join(dir, file);
26
+ if (statSync(fullPath).isDirectory()) {
27
+ if (findFile(fullPath)) {
28
+ return true;
29
+ }
30
+ }
31
+ else if (file === searchFile) {
32
+ return true;
33
+ }
34
+ }
35
+ return false;
36
+ }
37
+ return findFile(repoLocalDir);
38
+ }
39
+ export function getRepoRunMethod(dir) {
40
+ const homedir = os.homedir();
41
+ const repoDir = homedir + '/.proton-runner-repo/' + dir;
42
+ const maven = fs.existsSync(repoDir + '/pom.xml');
43
+ if (maven) {
44
+ return 'maven';
45
+ }
46
+ const sap = fs.existsSync(repoDir + '/SAP_Runner.vbs');
47
+ if (sap) {
48
+ return 'sap';
49
+ }
50
+ const pyTest = fs.existsSync(repoDir + '/pytest.ini');
51
+ if (pyTest) {
52
+ return 'pyTest';
53
+ }
54
+ const pwTest = fs.existsSync(repoDir + '/playwright.config.ts');
55
+ if (pwTest) {
56
+ return 'playwright';
57
+ }
58
+ return '';
59
+ }
60
+ export function initializeFolders() {
61
+ const homedir = os.homedir();
62
+ const baseDirPath = homedir + '/.proton-runner';
63
+ const baseDir = fs.existsSync(baseDirPath);
64
+ if (!baseDir) {
65
+ fs.mkdirSync(baseDirPath);
66
+ }
67
+ const appDir = fs.existsSync(baseDirPath + '/app');
68
+ if (!appDir) {
69
+ fs.mkdirSync(baseDirPath + '/app');
70
+ }
71
+ const attachmentsDir = fs.existsSync(baseDirPath + '/attachments');
72
+ if (!attachmentsDir) {
73
+ fs.mkdirSync(baseDirPath + '/attachments');
74
+ }
75
+ const driversDir = fs.existsSync(baseDirPath + '/drivers');
76
+ if (!driversDir) {
77
+ fs.mkdirSync(baseDirPath + '/drivers');
78
+ }
79
+ const libraryDir = fs.existsSync(baseDirPath + '/library');
80
+ if (!libraryDir) {
81
+ fs.mkdirSync(baseDirPath + '/library');
82
+ }
83
+ const logDir = fs.existsSync(baseDirPath + '/log');
84
+ if (!logDir) {
85
+ fs.mkdirSync(baseDirPath + '/log');
86
+ }
87
+ const repositoryDir = fs.existsSync(baseDirPath + '/repository');
88
+ if (!repositoryDir) {
89
+ fs.mkdirSync(baseDirPath + '/repository');
90
+ }
91
+ const screenshotsDir = fs.existsSync(baseDirPath + '/screenshots');
92
+ if (!screenshotsDir) {
93
+ fs.mkdirSync(baseDirPath + '/screenshots');
94
+ }
95
+ const traceDir = fs.existsSync(baseDirPath + '/trace');
96
+ if (!traceDir) {
97
+ fs.mkdirSync(baseDirPath + '/trace');
98
+ }
99
+ const toolsDir = fs.existsSync(baseDirPath + '/tools');
100
+ if (!toolsDir) {
101
+ fs.mkdirSync(baseDirPath + '/tools');
102
+ }
103
+ const videoDir = fs.existsSync(baseDirPath + '/video');
104
+ if (!videoDir) {
105
+ fs.mkdirSync(baseDirPath + '/video');
106
+ }
107
+ }
@@ -0,0 +1,31 @@
1
+ import { ChildProcessWithoutNullStreams } from "child_process";
2
+ import type { IDatasetRun, ISystem, InitiateProcessOptions } from "#types";
3
+ export declare class Manager {
4
+ addToWaitList(run: IDatasetRun[]): Promise<void>;
5
+ addToRunList(run: IDatasetRun): IDatasetRun;
6
+ updateRun(idDatasetRun: number | string, updatedRun: Partial<IDatasetRun>): void;
7
+ removeRun(id: number): void;
8
+ stopRun(idDatasetRun: number): Promise<void>;
9
+ getRunList(): IDatasetRun[];
10
+ clearRunList(): void;
11
+ getWaitList(): IDatasetRun[];
12
+ clearWaitList(): void;
13
+ addProcess(idDatasetRun: number, processId: number): void;
14
+ removeProcess(idDatasetRun: number): void;
15
+ finishRun(idDatasetRun: number): Promise<void>;
16
+ addNextToRun(): Promise<void>;
17
+ addToRun(run: IDatasetRun): Promise<void>;
18
+ updateRepos(systemList: ISystem[]): Promise<{
19
+ success: boolean;
20
+ message: string;
21
+ updatedSystems?: undefined;
22
+ } | {
23
+ success: boolean;
24
+ message: string;
25
+ updatedSystems: ISystem[];
26
+ }>;
27
+ runAutomation(run: IDatasetRun): Promise<void>;
28
+ private processKiller;
29
+ initiateProcess(command: string, options: InitiateProcessOptions): ChildProcessWithoutNullStreams;
30
+ }
31
+ export declare const manager: Manager;
@@ -0,0 +1,287 @@
1
+ import { runner } from "../runner/index.js";
2
+ import { cloneRepo, dirExists, getRepoRunMethod } from "../fileSystem/index.js";
3
+ import { getCurrentComponentSystem, getRemoteHeaderHash, setLog, updateDatasetRunStatus } from "../proton/api.js";
4
+ import Maven from "../proton/maven.js";
5
+ import { runNpmInstall } from "../proton/npm.js";
6
+ import Playwright from "../proton/playwright.js";
7
+ import PyTest from "../proton/pyTest.js";
8
+ import VBScript from "../proton/vbs.js";
9
+ import { getStoreValue, setStoreValue } from "../store/index.js";
10
+ import { spawn } from "child_process";
11
+ import i18n from 'i18next';
12
+ export class Manager {
13
+ async addToWaitList(run) {
14
+ const waitList = this.getWaitList();
15
+ waitList.push(...run);
16
+ setStoreValue("waitList", waitList);
17
+ await runner.setStatus("Busy");
18
+ await this.addNextToRun();
19
+ }
20
+ addToRunList(run) {
21
+ const runList = this.getRunList();
22
+ runList.push(run);
23
+ setStoreValue("runList", runList);
24
+ return run;
25
+ }
26
+ updateRun(idDatasetRun, updatedRun) {
27
+ let currentRunList = getStoreValue("runList") || [];
28
+ currentRunList = currentRunList.map((run) => {
29
+ if (run.id === Number(idDatasetRun)) {
30
+ let updRun = {
31
+ ...run,
32
+ ...updatedRun
33
+ };
34
+ if (updatedRun.status) {
35
+ if (['Loading', 'Running'].includes(updatedRun.status)) {
36
+ updRun = {
37
+ ...updRun,
38
+ isRunning: true
39
+ };
40
+ }
41
+ else {
42
+ updRun = {
43
+ ...updRun,
44
+ isRunning: false,
45
+ isUploadingResults: true
46
+ };
47
+ }
48
+ }
49
+ return updRun;
50
+ }
51
+ return run;
52
+ });
53
+ setStoreValue("runList", currentRunList);
54
+ }
55
+ removeRun(id) {
56
+ let currentRunList = getStoreValue("runList") || [];
57
+ currentRunList = currentRunList.filter((run) => run.id !== id);
58
+ setStoreValue("runList", currentRunList);
59
+ let waitList = getStoreValue("waitList") || [];
60
+ if (currentRunList.length === 0 && waitList.length === 0) {
61
+ runner.setStatus("Idle");
62
+ }
63
+ }
64
+ async stopRun(idDatasetRun) {
65
+ await updateDatasetRunStatus(idDatasetRun, 'Stopped');
66
+ const processList = getStoreValue("process") || [];
67
+ const processItem = processList.find((item) => item.idDatasetRun === idDatasetRun);
68
+ if (processItem) {
69
+ try {
70
+ this.processKiller(processItem.processId);
71
+ }
72
+ catch (err) {
73
+ console.log(`Erro ao finalizar processo ${processItem.processId}: `, err);
74
+ }
75
+ }
76
+ runner.setMsgPanel(`⏹️ **${i18n.t('msgPanel.automationRun')} #${idDatasetRun} ${i18n.t('msgPanel.wasStopped')}.**`);
77
+ }
78
+ getRunList() {
79
+ return getStoreValue("runList") || [];
80
+ }
81
+ clearRunList() {
82
+ setStoreValue("runList", []);
83
+ }
84
+ getWaitList() {
85
+ return getStoreValue("waitList") || [];
86
+ }
87
+ clearWaitList() {
88
+ setStoreValue("waitList", []);
89
+ }
90
+ addProcess(idDatasetRun, processId) {
91
+ const list = getStoreValue("process");
92
+ const newItem = { idDatasetRun, processId };
93
+ setStoreValue("process", [...list, newItem]);
94
+ }
95
+ removeProcess(idDatasetRun) {
96
+ let list = getStoreValue("process");
97
+ list = list.filter((item) => item.idDatasetRun !== idDatasetRun);
98
+ setStoreValue("process", list);
99
+ }
100
+ async finishRun(idDatasetRun) {
101
+ this.updateRun(idDatasetRun, { isUploadingResults: false });
102
+ runner.setMsgPanel(`🏁 **${i18n.t('msgPanel.automationRun')} #${idDatasetRun} ${i18n.t('msgPanel.finished')}**`);
103
+ this.removeRun(idDatasetRun);
104
+ await this.addNextToRun();
105
+ }
106
+ async addNextToRun() {
107
+ const parallelRuns = Number(getStoreValue("settings")?.parallelRuns || 1);
108
+ while (this.getRunList().length < parallelRuns) {
109
+ const waitList = this.getWaitList().sort((a, b) => b.idPriority - a.idPriority);
110
+ if (waitList.length === 0) {
111
+ return;
112
+ }
113
+ const nextRun = waitList.shift();
114
+ setStoreValue("waitList", waitList);
115
+ let addedRun = this.addToRunList(nextRun);
116
+ await updateDatasetRunStatus(addedRun.id, 'Loading');
117
+ this.addToRun(addedRun);
118
+ }
119
+ }
120
+ async addToRun(run) {
121
+ const updateRepoSuccess = await this.updateRepos(run.system);
122
+ if (updateRepoSuccess.success && updateRepoSuccess.updatedSystems) {
123
+ run = {
124
+ ...run,
125
+ system: updateRepoSuccess.updatedSystems
126
+ };
127
+ await this.runAutomation(run);
128
+ }
129
+ else {
130
+ updateDatasetRunStatus(run.id, 'Failed');
131
+ await setLog(run.id, updateRepoSuccess.message);
132
+ this.removeRun(run.id);
133
+ }
134
+ }
135
+ async updateRepos(systemList) {
136
+ const updatedSystems = [];
137
+ for (const system of systemList) {
138
+ const remoteHeaderHash = await getRemoteHeaderHash(system.gitRepository);
139
+ if (remoteHeaderHash) {
140
+ updatedSystems.push({
141
+ ...system,
142
+ gitRepository: {
143
+ ...system.gitRepository,
144
+ headerHash: remoteHeaderHash
145
+ }
146
+ });
147
+ const ownerRepo = `${system.gitRepository.owner}/${system.gitRepository.repository}`;
148
+ const dirRepo = ownerRepo + '/' + system.gitRepository.defaultBranch + '/' + remoteHeaderHash + '/' + system.gitRepository.repository;
149
+ const repoDirExists = dirExists(dirRepo);
150
+ if (repoDirExists) {
151
+ runner.setMsgPanel(`ℹ️ ${i18n.t('msgPanel.theProject')} ${system.gitRepository.repository} [${system.gitRepository.defaultBranch}] ${i18n.t('msgPanel.isUpToDate')}`);
152
+ }
153
+ else {
154
+ runner.setMsgPanel(`ℹ️ ${i18n.t('msgPanel.downloadingProject')} ${system.gitRepository.repository} [${system.gitRepository.defaultBranch}] ${i18n.t('msgPanel.from')} ${system.gitRepository.platform}...`);
155
+ await cloneRepo(system.gitRepository.remoteAuthorization, ownerRepo, system.gitRepository.defaultBranch, dirRepo);
156
+ const runMethod = getRepoRunMethod(dirRepo);
157
+ if (runMethod === 'playwright') {
158
+ await runNpmInstall(dirRepo);
159
+ }
160
+ runner.setMsgPanel(`ℹ️ ${i18n.t('msgPanel.downloadCompleted')} ${system.gitRepository.repository} [${system.gitRepository.defaultBranch}] ${i18n.t('msgPanel.projectUpdated')}`);
161
+ }
162
+ runner.setMsgPanel(`ℹ️ ${i18n.t('msgPanel.currentCommitHashFor')} ${system.gitRepository.platform} - ${system.gitRepository.repository} [${system.gitRepository.defaultBranch}]: ${remoteHeaderHash}`);
163
+ }
164
+ else {
165
+ const errorLog = `⛔ **${i18n.t('msgPanel.errorDownloadingProject')} ${system.gitRepository.repository} [${system.gitRepository.defaultBranch}]**`;
166
+ runner.setMsgPanel(errorLog);
167
+ return { success: false, message: errorLog };
168
+ // updateDatasetRunStatus(idDatasetRun, 'Failed');
169
+ // await setLog(idDatasetRun, errorLog);
170
+ }
171
+ }
172
+ return { success: true, message: '', updatedSystems };
173
+ }
174
+ async runAutomation(run) {
175
+ let exitCode = 1;
176
+ let componentSystem = await getCurrentComponentSystem(run.id);
177
+ while (String(componentSystem).length > 0) {
178
+ const remote = run.system.find((sys) => { return sys.name === componentSystem; });
179
+ if (remote) {
180
+ const ownerRepo = `${remote.gitRepository.owner}/${remote.gitRepository.repository}`;
181
+ try {
182
+ const dir = ownerRepo + '/' + remote.gitRepository.defaultBranch + '/' + remote.gitRepository.headerHash + '/' + remote.gitRepository.repository;
183
+ const runMethod = getRepoRunMethod(dir);
184
+ const runConfig = { dir: dir, idDatasetRun: run.id, reference: run.externalId };
185
+ runner.setMsgPanel(`▶️ **${i18n.t('msgPanel.automationRun')} #${run.id} ${i18n.t('msgPanel.initiated')}**`);
186
+ switch (runMethod) {
187
+ case 'maven':
188
+ exitCode = await Maven.runScript(runConfig);
189
+ break;
190
+ case 'sap':
191
+ exitCode = await VBScript.runScript(runConfig);
192
+ break;
193
+ case 'pyTest':
194
+ exitCode = await PyTest.runScript(runConfig);
195
+ break;
196
+ case 'playwright':
197
+ exitCode = await Playwright.runScript(runConfig);
198
+ break;
199
+ }
200
+ }
201
+ catch (err) {
202
+ await setLog(run.id, String(err));
203
+ }
204
+ this.removeProcess(run.id);
205
+ }
206
+ if (exitCode > 0) {
207
+ if (this.getRunList().find((r) => r.id === run.id)?.status !== 'Stopped') {
208
+ await updateDatasetRunStatus(run.id, 'Failed');
209
+ runner.setMsgPanel(`❌ **${i18n.t('msgPanel.errorRunningAutomation')} #${run.id}**`);
210
+ }
211
+ break;
212
+ }
213
+ componentSystem = await getCurrentComponentSystem(run.id);
214
+ }
215
+ await this.finishRun(run.id);
216
+ await this.addNextToRun();
217
+ }
218
+ async processKiller(pid) {
219
+ return new Promise((resolve) => {
220
+ if (!pid || pid <= 0) {
221
+ resolve();
222
+ return;
223
+ }
224
+ const platform = process.platform;
225
+ // =========================
226
+ // WINDOWS
227
+ // =========================
228
+ if (platform === 'win32') {
229
+ // taskkill mata o processo pai + todos os filhos
230
+ const killer = spawn('taskkill', ['/PID', pid.toString(), '/T', '/F'], {
231
+ windowsHide: true,
232
+ stdio: 'ignore'
233
+ });
234
+ killer.on('close', () => resolve());
235
+ killer.on('error', () => resolve());
236
+ return;
237
+ }
238
+ // =========================
239
+ // LINUX / MACOS
240
+ // =========================
241
+ try {
242
+ /**
243
+ * Em sistemas Unix:
244
+ * - usamos PID negativo para matar o PROCESS GROUP
245
+ * - isso mata o processo pai e todos os filhos
246
+ *
247
+ * IMPORTANTE:
248
+ * o processo original deve ter sido criado com:
249
+ * detached: true
250
+ */
251
+ process.kill(-pid, 'SIGKILL');
252
+ }
253
+ catch (err) {
254
+ // Ignora erros (processo pode já ter morrido)
255
+ }
256
+ resolve();
257
+ });
258
+ }
259
+ initiateProcess(command, options) {
260
+ const { cwd, args } = options;
261
+ // =========================
262
+ // WINDOWS
263
+ // =========================
264
+ if (process.platform === 'win32') {
265
+ return spawn('cmd.exe', [
266
+ '/d',
267
+ '/s',
268
+ '/c',
269
+ `${command}`,
270
+ ...args
271
+ ], {
272
+ cwd,
273
+ stdio: 'pipe',
274
+ windowsHide: true
275
+ });
276
+ }
277
+ // =========================
278
+ // LINUX / MACOS
279
+ // =========================
280
+ return spawn(command, args, {
281
+ cwd,
282
+ stdio: 'pipe',
283
+ detached: true
284
+ });
285
+ }
286
+ }
287
+ export const manager = new Manager();
@@ -0,0 +1,7 @@
1
+ import type { IRepoData } from "#types";
2
+ export declare function getRemoteHeaderHash(remote: IRepoData): Promise<string | null>;
3
+ export declare function getCurrentComponentSystem(datasetRunId: number): Promise<string | null>;
4
+ export declare function updateDatasetRunStatus(datasetRunId: number, status: string): Promise<boolean>;
5
+ export declare function setLog(datasetRunId: number, msg: string): Promise<void>;
6
+ export declare function updateRunnerStatus(status: string): Promise<void>;
7
+ export declare function uploadLogFile(idDatasetRun: number, log: string): Promise<void>;
@@ -0,0 +1,122 @@
1
+ import api from "../services/api.js";
2
+ import { getStoreValue } from "../store/index.js";
3
+ function getRequestBaseData() {
4
+ const activeConnection = getStoreValue("activeConnection");
5
+ if (!activeConnection || !activeConnection.token) {
6
+ return null;
7
+ }
8
+ return {
9
+ headers: {
10
+ Authorization: `Bearer ${activeConnection.token}`,
11
+ database: activeConnection.server.includes("localhost") ? "dev5" : activeConnection.server.match(/\/\/([^.]+)\./)[1]
12
+ },
13
+ baseUrl: activeConnection.server.includes("localhost") ? "http://localhost:3333" : activeConnection.server
14
+ };
15
+ }
16
+ export async function getRemoteHeaderHash(remote) {
17
+ const params = {
18
+ remoteAuthorization: remote.remoteAuthorization,
19
+ repository: remote.repository,
20
+ owner: remote.owner,
21
+ branch: remote.defaultBranch,
22
+ repoId: remote.repoId
23
+ };
24
+ try {
25
+ const requestBaseData = getRequestBaseData();
26
+ if (!requestBaseData) {
27
+ console.log('No active connection');
28
+ return null;
29
+ }
30
+ const response = await api.get(requestBaseData.baseUrl + '/git-repository/remote-header-hash', { params: params, headers: requestBaseData.headers });
31
+ if (response.status === 200) {
32
+ switch (remote.platform) {
33
+ case 'github':
34
+ return response.data['sha'];
35
+ case 'gitlab':
36
+ return response.data;
37
+ default:
38
+ return null;
39
+ }
40
+ }
41
+ else {
42
+ console.log('erro ao obter remote repository');
43
+ return null;
44
+ }
45
+ }
46
+ catch (err) {
47
+ console.log(err);
48
+ return null;
49
+ }
50
+ }
51
+ export async function getCurrentComponentSystem(datasetRunId) {
52
+ const requestBaseData = getRequestBaseData();
53
+ if (!requestBaseData) {
54
+ console.log('No active connection');
55
+ return null;
56
+ }
57
+ const response = await api.get(requestBaseData.baseUrl + '/dataset-run/get-current-component-system/' + datasetRunId, { headers: requestBaseData.headers });
58
+ if (response.status === 200) {
59
+ return response.data['system'];
60
+ }
61
+ else {
62
+ console.log('Erro ao obter o sistema do componente atual');
63
+ return null;
64
+ }
65
+ }
66
+ export async function updateDatasetRunStatus(datasetRunId, status) {
67
+ const requestBaseData = getRequestBaseData();
68
+ if (requestBaseData === null) {
69
+ console.log('No active connection');
70
+ return false;
71
+ }
72
+ const body = {
73
+ status: status
74
+ };
75
+ try {
76
+ const response = await api.put(requestBaseData.baseUrl + '/dataset-run/update-run-status/' + datasetRunId, body, { headers: requestBaseData.headers });
77
+ if (response.status === 200) {
78
+ return true;
79
+ // console.log(`Run #${datasetRunId} updated to ${status}`);
80
+ }
81
+ else {
82
+ return false;
83
+ // console.log('update dataset failed');
84
+ }
85
+ }
86
+ catch (err) {
87
+ console.log(err);
88
+ console.log('update dataset failed');
89
+ return false;
90
+ }
91
+ }
92
+ export async function setLog(datasetRunId, msg) {
93
+ const requestBaseData = getRequestBaseData();
94
+ if (requestBaseData) {
95
+ const body = {
96
+ idDatasetRun: datasetRunId,
97
+ log: msg
98
+ };
99
+ await api.put(requestBaseData.baseUrl + '/dataset-run-log/update-log/' + datasetRunId, body, { headers: requestBaseData.headers });
100
+ }
101
+ }
102
+ export async function updateRunnerStatus(status) {
103
+ const requestBaseData = getRequestBaseData();
104
+ if (requestBaseData) {
105
+ const body = {
106
+ status: status
107
+ };
108
+ await api.put(requestBaseData.baseUrl + '/runner/update-runner-status', body, { headers: requestBaseData.headers });
109
+ }
110
+ }
111
+ export async function uploadLogFile(idDatasetRun, log) {
112
+ const requestBaseData = getRequestBaseData();
113
+ if (!requestBaseData) {
114
+ console.log('No active connection');
115
+ return;
116
+ }
117
+ const params = { entity: 'dataset_run_resource', idEntity: String(idDatasetRun), description: '' };
118
+ const blobData = new Blob([log], { type: 'plain/text' });
119
+ let formData = new FormData();
120
+ formData.append('file', blobData, `${idDatasetRun}_RunLog.txt`);
121
+ await fetch(requestBaseData.baseUrl + '/file-system/upload-log-file?' + new URLSearchParams(params), { method: 'POST', body: formData, headers: requestBaseData.headers });
122
+ }
@@ -0,0 +1,5 @@
1
+ import type { IRunConfig } from '#types';
2
+ export default class Maven {
3
+ static runScript(runConfig: IRunConfig): Promise<number>;
4
+ private static executeProcess;
5
+ }
@@ -0,0 +1,74 @@
1
+ import os from 'os';
2
+ import { checkIfTestProtonScriptExists } from '../fileSystem/index.js';
3
+ import { runner } from '../runner/index.js';
4
+ import { manager } from '../manager/index.js';
5
+ import path from 'path';
6
+ import fs from 'fs';
7
+ import { uploadLogFile } from './api.js';
8
+ export default class Maven {
9
+ static async runScript(runConfig) {
10
+ const repoLocalDir = path.join(os.homedir(), '.proton-runner-repo', runConfig.dir);
11
+ const exitCode = await this.executeProcess(repoLocalDir, runConfig.idDatasetRun, runConfig.reference || '');
12
+ return exitCode;
13
+ }
14
+ static executeProcess(repoLocalDir, idDatasetRun, reference) {
15
+ if (!fs.existsSync(repoLocalDir)) {
16
+ throw new Error(`Diretório inválido: ${repoLocalDir}`);
17
+ }
18
+ const activeConnection = runner.getActiveConnection();
19
+ if (!activeConnection) {
20
+ return Promise.resolve(1);
21
+ }
22
+ return new Promise((resolve) => {
23
+ try {
24
+ let mvnCmd = ['test', `-DidDatasetRun=${idDatasetRun}`];
25
+ if (reference.length > 0) {
26
+ let cucumberOption = '-Dcucumber.filter.tags="';
27
+ const tags = reference.split(' ');
28
+ for (let i = 0; i < tags.length; i++) {
29
+ cucumberOption = cucumberOption + `${tags[i]} `;
30
+ }
31
+ cucumberOption = cucumberOption + '"';
32
+ mvnCmd.push(cucumberOption);
33
+ }
34
+ if (checkIfTestProtonScriptExists(repoLocalDir)) {
35
+ mvnCmd.push('-Dtest=TestProtonScript');
36
+ }
37
+ const proc = manager.initiateProcess('mvn', {
38
+ cwd: repoLocalDir,
39
+ args: ['-B', ...mvnCmd]
40
+ });
41
+ if (!proc.pid) {
42
+ resolve(1);
43
+ return;
44
+ }
45
+ manager.addProcess(idDatasetRun, proc.pid);
46
+ let log = '';
47
+ proc.stdout.setEncoding('latin1');
48
+ proc.stdout.on('data', (data) => {
49
+ log += data;
50
+ });
51
+ proc.stderr.setEncoding('latin1');
52
+ proc.stderr.on('data', (data) => {
53
+ console.log('Maven STDERR:', data);
54
+ });
55
+ proc.on('close', async (code) => {
56
+ try {
57
+ await uploadLogFile(idDatasetRun, log);
58
+ }
59
+ catch (err) {
60
+ console.log(err);
61
+ console.log('Erro ao gerar arquivo de log');
62
+ }
63
+ resolve(code);
64
+ });
65
+ proc.on('error', err => {
66
+ console.error('Erro ao iniciar Maven:', err);
67
+ });
68
+ }
69
+ catch (err) {
70
+ resolve(1);
71
+ }
72
+ });
73
+ }
74
+ }