nitor 1.2.2 → 1.3.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/CHANGELOG.md +8 -0
- package/README.md +29 -0
- package/package.json +1 -1
- package/services/cleanup.js +14 -5
- package/services/create-branch.js +6 -1
- package/services/enums/actions.enum.js +2 -0
- package/services/merge.js +12 -8
- package/services/mongodb-backup.js +75 -37
- package/services/process-commands.js +89 -13
- package/services/task-stats.js +197 -0
- package/services/time-entry/get-gitlab-activities.js +74 -44
- package/services/utils.js +9 -8
- package/services/time-entry/enums/actions.enum.js +0 -16
package/CHANGELOG.md
CHANGED
|
@@ -30,3 +30,11 @@ For a complete list of changes and discussion, see [Issue #1](https://github.com
|
|
|
30
30
|
- Added time entry commands.
|
|
31
31
|
|
|
32
32
|
- [Issue #5](https://github.com/codebynithin/nitor/issues/5)
|
|
33
|
+
|
|
34
|
+
## [1.3.0] - 2025-11-29
|
|
35
|
+
|
|
36
|
+
### New Features
|
|
37
|
+
|
|
38
|
+
- Added support for task stats and get task commands.
|
|
39
|
+
|
|
40
|
+
- [Issue #7](https://github.com/codebynithin/nitor/issues/7)
|
package/README.md
CHANGED
|
@@ -26,6 +26,9 @@ A CLI utility toolkit for automating and managing build, deploy, and status oper
|
|
|
26
26
|
- Cleanup local git branches
|
|
27
27
|
- Time entry management with Zoho integration
|
|
28
28
|
- GitLab activity tracking
|
|
29
|
+
- Task statistics with merge request details
|
|
30
|
+
- Extract Zoho task IDs from GitLab issue descriptions
|
|
31
|
+
- Merge request status tracking for active tasks
|
|
29
32
|
|
|
30
33
|
## Requirements
|
|
31
34
|
|
|
@@ -36,6 +39,7 @@ A CLI utility toolkit for automating and managing build, deploy, and status oper
|
|
|
36
39
|
- `COOKIE` - Cookie for Gitlab (Copy from browser)
|
|
37
40
|
- `GITLAB_URI` - GitLab API URL, eg: `https://gitlab.com/`
|
|
38
41
|
- `GITLAB_TOKEN` - Gitlab token
|
|
42
|
+
- `GITLAB_DEFAULT_PROJECT_ID` - Default GitLab project ID for issue lookups
|
|
39
43
|
- `MR_PROMPT` - Merge request prompt
|
|
40
44
|
- `MR_LANG` - Merge request language
|
|
41
45
|
- `AI_API_KEY` - AI API key
|
|
@@ -155,6 +159,26 @@ Once enabled, you can use Tab to autocomplete:
|
|
|
155
159
|
```bash
|
|
156
160
|
nitor time-zoho
|
|
157
161
|
```
|
|
162
|
+
- **Time Entry - GitLab Activities:**
|
|
163
|
+
```bash
|
|
164
|
+
nitor time-gitlab -from <YYYY-MM-DD> -to <YYYY-MM-DD>
|
|
165
|
+
```
|
|
166
|
+
- **Time Entry - Merge Request Status:**
|
|
167
|
+
```bash
|
|
168
|
+
nitor time-merge
|
|
169
|
+
```
|
|
170
|
+
- **Time Entry - Switch Project:**
|
|
171
|
+
```bash
|
|
172
|
+
nitor time-switch
|
|
173
|
+
```
|
|
174
|
+
- **Task Stats:**
|
|
175
|
+
```bash
|
|
176
|
+
nitor task-stats -task <task numbers with space>
|
|
177
|
+
```
|
|
178
|
+
- **Get Task (Extract Zoho Task IDs):**
|
|
179
|
+
```bash
|
|
180
|
+
nitor get-task -task <task numbers with space>
|
|
181
|
+
```
|
|
158
182
|
|
|
159
183
|
### Command Reference
|
|
160
184
|
|
|
@@ -178,6 +202,11 @@ Once enabled, you can use Tab to autocomplete:
|
|
|
178
202
|
- `time-entries` : View time entries by date range
|
|
179
203
|
- `time-stats` : View daily statistics of time entries
|
|
180
204
|
- `time-zoho` : Sync time entries to Zoho
|
|
205
|
+
- `time-gitlab` : Get GitLab activities for a date range
|
|
206
|
+
- `time-merge` : View merge request status for active tasks
|
|
207
|
+
- `time-switch` : Switch between default projects
|
|
208
|
+
- `task-stats` : View task statistics with GitLab merge request details
|
|
209
|
+
- `get-task` : Extract Zoho task IDs from GitLab issue descriptions
|
|
181
210
|
|
|
182
211
|
### Options
|
|
183
212
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nitor",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "A comprehensive CLI toolkit for automating GitLab operations, AI-powered code review, build/deploy automation, MongoDB backup/restore, and developer productivity tools",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "Nithin V <mails2nithin@gmail.com>",
|
package/services/cleanup.js
CHANGED
|
@@ -1,26 +1,35 @@
|
|
|
1
1
|
const { execSync } = require('child_process');
|
|
2
|
+
const os = require('os');
|
|
3
|
+
const isWindows = os.platform() === 'win32';
|
|
2
4
|
|
|
3
5
|
const cleanup = async () => {
|
|
4
6
|
try {
|
|
5
7
|
console.log('Starting cleanup process...\n');
|
|
6
8
|
|
|
9
|
+
const execOptions = { encoding: 'utf-8', shell: isWindows ? 'cmd.exe' : '/bin/sh' };
|
|
10
|
+
const execOptionsInherit = {
|
|
11
|
+
encoding: 'utf-8',
|
|
12
|
+
stdio: 'inherit',
|
|
13
|
+
shell: isWindows ? 'cmd.exe' : '/bin/sh',
|
|
14
|
+
};
|
|
15
|
+
|
|
7
16
|
// Get current branch
|
|
8
|
-
const currentBranch = execSync('git branch --show-current',
|
|
17
|
+
const currentBranch = execSync('git branch --show-current', execOptions).trim();
|
|
9
18
|
console.log(`Current branch: ${currentBranch}`);
|
|
10
19
|
|
|
11
20
|
// Checkout to master
|
|
12
21
|
console.log('\nChecking out to master branch...');
|
|
13
22
|
try {
|
|
14
|
-
execSync('git checkout master',
|
|
23
|
+
execSync('git checkout master', execOptionsInherit);
|
|
15
24
|
} catch (error) {
|
|
16
25
|
// Try main if master doesn't exist
|
|
17
26
|
console.log('Master branch not found, trying main...');
|
|
18
|
-
execSync('git checkout main',
|
|
27
|
+
execSync('git checkout main', execOptionsInherit);
|
|
19
28
|
}
|
|
20
29
|
|
|
21
30
|
// Get all local branches except master/main
|
|
22
31
|
console.log('\nFetching list of local branches...');
|
|
23
|
-
const branches = execSync('git branch',
|
|
32
|
+
const branches = execSync('git branch', execOptions)
|
|
24
33
|
.split('\n')
|
|
25
34
|
.map((branch) => branch.trim().replace('* ', ''))
|
|
26
35
|
.filter((branch) => branch && branch !== 'master' && branch !== 'main');
|
|
@@ -39,7 +48,7 @@ const cleanup = async () => {
|
|
|
39
48
|
|
|
40
49
|
for (const branch of branches) {
|
|
41
50
|
try {
|
|
42
|
-
execSync(`git branch -D ${branch}`,
|
|
51
|
+
execSync(`git branch -D ${branch}`, execOptions);
|
|
43
52
|
console.log(` ✓ Deleted: ${branch}`);
|
|
44
53
|
deletedCount++;
|
|
45
54
|
} catch (error) {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
const { execSync } = require('child_process');
|
|
2
|
+
const os = require('os');
|
|
3
|
+
const isWindows = os.platform() === 'win32';
|
|
2
4
|
|
|
3
5
|
const createBranch = async (values) => {
|
|
4
6
|
if (!values.task || !values.type || !values.description) {
|
|
@@ -20,7 +22,10 @@ const createBranch = async (values) => {
|
|
|
20
22
|
const branchName = `${values.project}-${values.task}-${values.type}-${values.description.toLowerCase().replace(/\s/g, '-')}`;
|
|
21
23
|
|
|
22
24
|
try {
|
|
23
|
-
execSync(`git checkout -b ${branchName}`, {
|
|
25
|
+
execSync(`git checkout -b ${branchName}`, {
|
|
26
|
+
stdio: 'inherit',
|
|
27
|
+
shell: isWindows ? 'cmd.exe' : '/bin/sh',
|
|
28
|
+
});
|
|
24
29
|
} catch (error) {
|
|
25
30
|
console.error('Error creating branch:', error.message);
|
|
26
31
|
}
|
package/services/merge.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
const { execSync } = require('child_process');
|
|
2
|
+
const os = require('os');
|
|
3
|
+
const isWindows = os.platform() === 'win32';
|
|
2
4
|
|
|
3
5
|
const merge = async (values) => {
|
|
4
6
|
const { source, target } = values;
|
|
@@ -12,16 +14,18 @@ const merge = async (values) => {
|
|
|
12
14
|
try {
|
|
13
15
|
console.log('Starting merge process...\n');
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
execSync(
|
|
18
|
-
execSync('git pull',
|
|
17
|
+
const execOptions = { stdio: 'inherit', shell: isWindows ? 'cmd.exe' : '/bin/sh' };
|
|
18
|
+
|
|
19
|
+
execSync('git checkout master', execOptions);
|
|
20
|
+
execSync('git pull', execOptions);
|
|
21
|
+
execSync(`git checkout ${source}`, execOptions);
|
|
22
|
+
execSync('git pull', execOptions);
|
|
19
23
|
|
|
20
24
|
for (const branch of target.split(' ')) {
|
|
21
|
-
execSync(`git checkout ${branch}`,
|
|
22
|
-
execSync('git pull',
|
|
23
|
-
execSync(`git merge ${source} --no-edit`,
|
|
24
|
-
execSync('git push',
|
|
25
|
+
execSync(`git checkout ${branch}`, execOptions);
|
|
26
|
+
execSync('git pull', execOptions);
|
|
27
|
+
execSync(`git merge ${source} --no-edit`, execOptions);
|
|
28
|
+
execSync('git push', execOptions);
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
console.log('\n✓ Merge completed successfully!');
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
const { execSync } = require('child_process');
|
|
2
2
|
const os = require('os');
|
|
3
|
+
const path = require('path');
|
|
3
4
|
const { backupConfig, restoreConfig } = require('./utils');
|
|
4
|
-
|
|
5
|
+
const isWindows = os.platform() === 'win32';
|
|
5
6
|
// ANSI color codes
|
|
6
7
|
const colors = {
|
|
7
8
|
red: '\x1b[31m',
|
|
@@ -12,6 +13,7 @@ const colors = {
|
|
|
12
13
|
/**
|
|
13
14
|
* Execute MongoDB restore from local backup to Docker container
|
|
14
15
|
* @param {Object} config - Restore configuration
|
|
16
|
+
* @param {boolean} config.mongoInDocker - If mongodb running outside of docker
|
|
15
17
|
* @param {string} config.containerName - Name of the Docker container (default: 'mongodb')
|
|
16
18
|
* @param {string} config.localBackupPath - Local path where backup is stored (default: '~/backups/mongo')
|
|
17
19
|
* @param {string} config.containerBackupPath - Path inside container for backup (default: '/data/backup')
|
|
@@ -19,37 +21,60 @@ const colors = {
|
|
|
19
21
|
const executeMongoRestore = async (config) => {
|
|
20
22
|
const {
|
|
21
23
|
containerName = 'mongodb',
|
|
22
|
-
localBackupPath = os.homedir()
|
|
24
|
+
localBackupPath = path.join(os.homedir(), 'backups', 'mongo'),
|
|
23
25
|
containerBackupPath = '/data/backup',
|
|
24
26
|
} = config;
|
|
25
27
|
|
|
26
28
|
try {
|
|
27
|
-
const expandedLocalPath = localBackupPath.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
29
|
+
const expandedLocalPath = localBackupPath.startsWith('~')
|
|
30
|
+
? localBackupPath.replace('~', os.homedir())
|
|
31
|
+
: localBackupPath;
|
|
32
|
+
const normalizedLocalPath = path.normalize(expandedLocalPath);
|
|
33
|
+
|
|
34
|
+
if (config.mongoInDocker) {
|
|
35
|
+
console.log(`\nStarting MongoDB restore to container: ${containerName}`);
|
|
36
|
+
|
|
37
|
+
// Step 1: Copy backup from local to Docker container
|
|
38
|
+
// Use normalized path for Windows compatibility
|
|
39
|
+
const copyCommand = `docker cp "${normalizedLocalPath}" ${containerName}:${containerBackupPath}`;
|
|
40
|
+
|
|
41
|
+
console.log(`Copying backup to container...`);
|
|
42
|
+
execSync(copyCommand, { stdio: 'inherit', shell: isWindows ? 'cmd.exe' : '/bin/sh' });
|
|
43
|
+
console.log(`${colors.green}✓ Backup copied to container${colors.reset}`);
|
|
44
|
+
|
|
45
|
+
// Step 2: Execute mongorestore inside the container
|
|
46
|
+
// Remove -it flag for Windows compatibility (causes issues in non-interactive shells)
|
|
47
|
+
const restoreCommand = isWindows
|
|
48
|
+
? `docker exec ${containerName} mongorestore ${containerBackupPath}`
|
|
49
|
+
: `docker exec -it ${containerName} mongorestore ${containerBackupPath}`;
|
|
50
|
+
|
|
51
|
+
console.log('Executing mongorestore...');
|
|
52
|
+
execSync(restoreCommand, { stdio: 'inherit', shell: isWindows ? 'cmd.exe' : '/bin/sh' });
|
|
53
|
+
console.log(`${colors.green}✓ Mongorestore completed successfully${colors.reset}`);
|
|
54
|
+
|
|
55
|
+
// Step 3: Remove backup data from container
|
|
56
|
+
const cleanupCommand = isWindows
|
|
57
|
+
? `docker exec ${containerName} rm -rf ${containerBackupPath}`
|
|
58
|
+
: `docker exec -it ${containerName} rm -rf ${containerBackupPath}`;
|
|
59
|
+
|
|
60
|
+
console.log('Cleaning up backup data from container...');
|
|
61
|
+
execSync(cleanupCommand, { stdio: 'inherit', shell: isWindows ? 'cmd.exe' : '/bin/sh' });
|
|
62
|
+
console.log(`${colors.green}✓ Backup data removed from container${colors.reset}`);
|
|
63
|
+
|
|
64
|
+
console.log(`${colors.green}Restore completed successfully!${colors.reset}\n`);
|
|
65
|
+
} else {
|
|
66
|
+
console.log(`\nStarting MongoDB restore to local machine`);
|
|
67
|
+
|
|
68
|
+
console.log('Executing mongorestore...');
|
|
69
|
+
const localRestoreCommand = `mongorestore --uri="mongodb://localhost:27017/" "${normalizedLocalPath}"`;
|
|
70
|
+
execSync(localRestoreCommand, {
|
|
71
|
+
stdio: 'inherit',
|
|
72
|
+
shell: isWindows ? 'cmd.exe' : '/bin/sh',
|
|
73
|
+
});
|
|
74
|
+
console.log(`${colors.green}✓ Mongorestore completed successfully${colors.reset}`);
|
|
75
|
+
|
|
76
|
+
console.log(`${colors.green}Restore completed successfully!${colors.reset}\n`);
|
|
77
|
+
}
|
|
53
78
|
|
|
54
79
|
return { success: true };
|
|
55
80
|
} catch (error) {
|
|
@@ -75,29 +100,40 @@ const executeMongoBackup = async (config) => {
|
|
|
75
100
|
password,
|
|
76
101
|
database,
|
|
77
102
|
backupPath = '/data/backup',
|
|
78
|
-
localBackupPath = '
|
|
103
|
+
localBackupPath = path.join(os.homedir(), 'backups', 'mongo'),
|
|
79
104
|
} = config;
|
|
80
105
|
|
|
81
106
|
try {
|
|
82
107
|
console.log(`\nStarting MongoDB backup for pod: ${pod}, database: ${database}`);
|
|
83
108
|
|
|
84
|
-
|
|
109
|
+
// Remove -it flag for Windows compatibility
|
|
110
|
+
const mongodumpCommand = isWindows
|
|
111
|
+
? `kubectl exec ${pod} -- mongodump --username ${username} --password ${password} --authenticationDatabase ${database} --db ${database} --out ${backupPath}`
|
|
112
|
+
: `kubectl exec -it ${pod} -- mongodump --username ${username} --password ${password} --authenticationDatabase ${database} --db ${database} --out ${backupPath}`;
|
|
85
113
|
|
|
86
114
|
console.log('Executing mongodump...');
|
|
87
|
-
execSync(mongodumpCommand, { stdio: 'inherit' });
|
|
115
|
+
execSync(mongodumpCommand, { stdio: 'inherit', shell: isWindows ? 'cmd.exe' : '/bin/sh' });
|
|
88
116
|
console.log(`${colors.green}✓ Mongodump completed successfully${colors.reset}`);
|
|
89
117
|
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
118
|
+
// Expand and normalize paths for cross-platform compatibility
|
|
119
|
+
const expandedLocalPath = localBackupPath.startsWith('~')
|
|
120
|
+
? localBackupPath.replace('~', os.homedir())
|
|
121
|
+
: localBackupPath;
|
|
122
|
+
const normalizedBasePath = path.normalize(expandedLocalPath);
|
|
123
|
+
const destinationPath = path.join(normalizedBasePath, database);
|
|
124
|
+
|
|
125
|
+
// Use quotes for paths with spaces on Windows
|
|
126
|
+
const copyCommand = `kubectl cp ${pod}:${backupPath}/${database} "${destinationPath}"`;
|
|
127
|
+
const cleanupCommand = isWindows
|
|
128
|
+
? `kubectl exec ${pod} -- rm -rf ${backupPath}`
|
|
129
|
+
: `kubectl exec -it ${pod} -- rm -rf ${backupPath}`;
|
|
94
130
|
|
|
95
131
|
console.log(`Copying backup to ${destinationPath}...`);
|
|
96
|
-
execSync(copyCommand, { stdio: 'inherit' });
|
|
132
|
+
execSync(copyCommand, { stdio: 'inherit', shell: isWindows ? 'cmd.exe' : '/bin/sh' });
|
|
97
133
|
console.log(`${colors.green}✓ Backup copied successfully${colors.reset}`);
|
|
98
134
|
|
|
99
135
|
console.log('Cleaning up backup data from pod...');
|
|
100
|
-
execSync(cleanupCommand, { stdio: 'inherit' });
|
|
136
|
+
execSync(cleanupCommand, { stdio: 'inherit', shell: isWindows ? 'cmd.exe' : '/bin/sh' });
|
|
101
137
|
console.log(`${colors.green}✓ Backup data removed from pod${colors.reset}`);
|
|
102
138
|
|
|
103
139
|
console.log(
|
|
@@ -159,6 +195,8 @@ const backup = async (values) => {
|
|
|
159
195
|
console.log(`Starting restore process for projects: ${projects.join(', ')}`);
|
|
160
196
|
console.log(`========================================`);
|
|
161
197
|
|
|
198
|
+
restoreConfig.mongoInDocker = !!values?.docker;
|
|
199
|
+
|
|
162
200
|
await executeMongoRestore(restoreConfig);
|
|
163
201
|
|
|
164
202
|
console.log('\n========================================');
|
|
@@ -18,25 +18,19 @@ const { addNewTask } = require('./time-entry/add-task');
|
|
|
18
18
|
const { updateTask, deleteTask } = require('./time-entry/update-delete-task');
|
|
19
19
|
const { getGitlabActivities } = require('./time-entry/get-gitlab-activities');
|
|
20
20
|
const { getZohoTasks } = require('./time-entry/get-zoho-tasks');
|
|
21
|
+
const {
|
|
22
|
+
getTaskStats,
|
|
23
|
+
getGitIdStats,
|
|
24
|
+
getGitlabIssueMergeRequests,
|
|
25
|
+
getGitMergeRequestDetails,
|
|
26
|
+
} = require('./task-stats');
|
|
21
27
|
|
|
22
28
|
const processArgs = async (type, value) => {
|
|
23
29
|
try {
|
|
24
30
|
let values;
|
|
25
31
|
|
|
26
32
|
// Skip convertParamsToMap for time commands and other special commands
|
|
27
|
-
const skipConversion = [
|
|
28
|
-
ACTIONS.HELP,
|
|
29
|
-
ACTIONS.VERSION,
|
|
30
|
-
ACTIONS.CLEANUP,
|
|
31
|
-
ACTIONS.TIME_ADD,
|
|
32
|
-
ACTIONS.TIME_UPDATE,
|
|
33
|
-
ACTIONS.TIME_DELETE,
|
|
34
|
-
ACTIONS.TIME_STATUS,
|
|
35
|
-
ACTIONS.TIME_ENTRIES,
|
|
36
|
-
ACTIONS.TIME_ZOHO,
|
|
37
|
-
ACTIONS.TIME_GITLAB,
|
|
38
|
-
ACTIONS.TIME_MERGE,
|
|
39
|
-
];
|
|
33
|
+
const skipConversion = [ACTIONS.HELP, ACTIONS.VERSION, ACTIONS.CLEANUP];
|
|
40
34
|
|
|
41
35
|
if (!skipConversion.includes(type) && !value?.includes('--h') && !value?.includes('-help')) {
|
|
42
36
|
values = await convertParamsToMap(value, type);
|
|
@@ -292,6 +286,88 @@ ${cyan}${bold}╔═════════════════════
|
|
|
292
286
|
break;
|
|
293
287
|
}
|
|
294
288
|
|
|
289
|
+
case ACTIONS.TASK_STATS: {
|
|
290
|
+
if (value === '-help' || value === '--h') {
|
|
291
|
+
console.log(`usage: \tnu task-stats [-task <task number>]
|
|
292
|
+
\tnu task-stats [-t <task number>]
|
|
293
|
+
|
|
294
|
+
View task stats
|
|
295
|
+
|
|
296
|
+
Options:
|
|
297
|
+
-t, --task <number> task number`);
|
|
298
|
+
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (!values.task) {
|
|
303
|
+
console.log('Task number is required');
|
|
304
|
+
|
|
305
|
+
process.exit(1);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const list = [];
|
|
309
|
+
|
|
310
|
+
for (const task of values.task.split(' ')) {
|
|
311
|
+
const taskDetail = await getTaskStats(task);
|
|
312
|
+
const gitIdDetails = await getGitIdStats(taskDetail.itemIds);
|
|
313
|
+
const mrDetails = await getGitlabIssueMergeRequests(gitIdDetails);
|
|
314
|
+
|
|
315
|
+
for (const mrDetail of mrDetails) {
|
|
316
|
+
list.push({
|
|
317
|
+
Task: task,
|
|
318
|
+
Owner: taskDetail.owner,
|
|
319
|
+
...mrDetail,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
console.table(list);
|
|
325
|
+
|
|
326
|
+
break;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
case ACTIONS.GET_TASK: {
|
|
330
|
+
if (value === '-help' || value === '--h') {
|
|
331
|
+
console.log(`usage: \tnu get-task [-task <task numbers with space>]
|
|
332
|
+
\tnu get-task [-t <task numbers with space>]
|
|
333
|
+
|
|
334
|
+
Get task details
|
|
335
|
+
|
|
336
|
+
Options:
|
|
337
|
+
-t, --task <numbers with space> task numbers with space`);
|
|
338
|
+
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (!values.task) {
|
|
343
|
+
console.log('Task number is required');
|
|
344
|
+
|
|
345
|
+
process.exit(1);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const tasks = {};
|
|
349
|
+
|
|
350
|
+
for (const task of values.task.split(' ')) {
|
|
351
|
+
const taskDetails = await getGitMergeRequestDetails(task);
|
|
352
|
+
|
|
353
|
+
if (taskDetails.error) {
|
|
354
|
+
console.log(`No merge requests found for task ${task}`);
|
|
355
|
+
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
for (const taskDetail of taskDetails) {
|
|
360
|
+
const zohoTaskMatch = taskDetail.description?.match(/itemdetails\/(I\d+)\)/);
|
|
361
|
+
|
|
362
|
+
tasks[task] = zohoTaskMatch ? zohoTaskMatch[1] : 'Not found';
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
console.log(tasks);
|
|
367
|
+
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
|
|
295
371
|
// Time entry commands
|
|
296
372
|
case ACTIONS.TIME_ADD: {
|
|
297
373
|
const timeValues = value ? removeEmpty(value?.split(' -')) : value;
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
const { zohoConfig, gitlabConfig } = require('./utils');
|
|
3
|
+
|
|
4
|
+
const getZohoUrl = (type, taskNumber) => {
|
|
5
|
+
switch (type) {
|
|
6
|
+
case 'task':
|
|
7
|
+
return `${zohoConfig.url}/zsapi/team/${zohoConfig.team}/projects/${zohoConfig.defaultProjectId}/item/no-${taskNumber}/?action=details`;
|
|
8
|
+
|
|
9
|
+
case 'gitId':
|
|
10
|
+
return `${zohoConfig.url}/zsapi/team/${zohoConfig.team}/projects/${zohoConfig.defaultProjectId}/item/${taskNumber}/scm/3/issuedetails/?action=scmissuedetails`;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const getZohoConfig = (type, taskNumber) => {
|
|
15
|
+
return {
|
|
16
|
+
method: 'get',
|
|
17
|
+
maxBodyLength: Infinity,
|
|
18
|
+
url: getZohoUrl(type, taskNumber),
|
|
19
|
+
headers: {
|
|
20
|
+
'User-Agent':
|
|
21
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:145.0) Gecko/20100101 Firefox/145.0',
|
|
22
|
+
Accept: '*/*',
|
|
23
|
+
'Accept-Language': 'en-GB,en;q=0.5',
|
|
24
|
+
'Accept-Encoding': 'gzip, deflate, br, zstd',
|
|
25
|
+
Referer: `${zohoConfig.url}/workspace/4medica/client/wmoku`,
|
|
26
|
+
'X-ZA-REQSIZE': 'large',
|
|
27
|
+
'X-Requested-With': 'XMLHttpRequest',
|
|
28
|
+
'X-ZA-SOURCE': zohoConfig.source,
|
|
29
|
+
'X-ZA-UI-VERSION': 'v2',
|
|
30
|
+
'X-ZCSRF-TOKEN': zohoConfig.token,
|
|
31
|
+
'X-ZA-CLIENTPORTALID': zohoConfig.portalId,
|
|
32
|
+
'X-ZA-SESSIONID': zohoConfig.sessionId,
|
|
33
|
+
Connection: 'keep-alive',
|
|
34
|
+
Cookie: zohoConfig.cookie,
|
|
35
|
+
'Sec-Fetch-Dest': 'empty',
|
|
36
|
+
'Sec-Fetch-Mode': 'cors',
|
|
37
|
+
'Sec-Fetch-Site': 'same-origin',
|
|
38
|
+
Priority: 'u=0',
|
|
39
|
+
Pragma: 'no-cache',
|
|
40
|
+
'Cache-Control': 'no-cache',
|
|
41
|
+
TE: 'trailers',
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const getGitlabConfig = (url) => {
|
|
47
|
+
return {
|
|
48
|
+
method: 'get',
|
|
49
|
+
maxBodyLength: Infinity,
|
|
50
|
+
url,
|
|
51
|
+
headers: {
|
|
52
|
+
'User-Agent':
|
|
53
|
+
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:145.0) Gecko/20100101 Firefox/145.0',
|
|
54
|
+
Accept: 'application/json',
|
|
55
|
+
'Accept-Language': 'en-GB,en;q=0.5',
|
|
56
|
+
'Accept-Encoding': 'gzip, deflate, br, zstd',
|
|
57
|
+
'PRIVATE-TOKEN': gitlabConfig.token,
|
|
58
|
+
Connection: 'keep-alive',
|
|
59
|
+
Cookie: gitlabConfig.cookie,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const getTaskStats = async (task) => {
|
|
65
|
+
try {
|
|
66
|
+
const config = getZohoConfig('task', task);
|
|
67
|
+
const response = await axios.request(config);
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
itemIds: response.data.itemIds,
|
|
71
|
+
owner: Object.values(response.data.userDisplayName).join(', '),
|
|
72
|
+
};
|
|
73
|
+
} catch (error) {
|
|
74
|
+
console.log(error);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const getGitIdStats = async (gitIds) => {
|
|
79
|
+
const gitIdStats = [];
|
|
80
|
+
|
|
81
|
+
for (const gitId of gitIds) {
|
|
82
|
+
try {
|
|
83
|
+
const config = getZohoConfig('gitId', gitId);
|
|
84
|
+
const response = await axios.request(config);
|
|
85
|
+
|
|
86
|
+
gitIdStats.push(response.data);
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.log(error);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return gitIdStats;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const getGitlabIssueDetails = async (projectId, issueIid) => {
|
|
96
|
+
try {
|
|
97
|
+
const config = getGitlabConfig(`${projectId}/issues/${issueIid}`);
|
|
98
|
+
const response = await axios.request(config);
|
|
99
|
+
|
|
100
|
+
return response.data;
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.error('Error fetching GitLab issue details:', error.message);
|
|
103
|
+
if (error.response) {
|
|
104
|
+
console.error('Response status:', error.response.status);
|
|
105
|
+
console.error('Response data:', error.response.data);
|
|
106
|
+
}
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const getGitMergeRequestDetails = async (issueIid, projectId) => {
|
|
112
|
+
try {
|
|
113
|
+
if (!projectId) {
|
|
114
|
+
projectId = `${gitlabConfig.url}/api/v4/projects/${gitlabConfig.defaultProjectId}`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const config = getGitlabConfig(`${projectId}/issues/${issueIid}/related_merge_requests`);
|
|
118
|
+
const response = await axios.request(config);
|
|
119
|
+
|
|
120
|
+
return response.data;
|
|
121
|
+
} catch (error) {
|
|
122
|
+
return { error };
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const getGitlabIssueMergeRequests = async (gitDetails) => {
|
|
127
|
+
for (const gitDetail of gitDetails) {
|
|
128
|
+
try {
|
|
129
|
+
const mergeRequests = await getGitMergeRequestDetails(
|
|
130
|
+
gitDetail.iid,
|
|
131
|
+
gitDetail._links.project,
|
|
132
|
+
);
|
|
133
|
+
const detailedMRs = await Promise.all(
|
|
134
|
+
mergeRequests.map(async (mr) => {
|
|
135
|
+
try {
|
|
136
|
+
const detailConfig = getGitlabConfig(
|
|
137
|
+
`${gitlabConfig.url}/api/v4/projects/${mr.project_id}/merge_requests/${mr.iid}`,
|
|
138
|
+
);
|
|
139
|
+
const detailResponse = await axios.request(detailConfig);
|
|
140
|
+
const mrData = detailResponse.data;
|
|
141
|
+
|
|
142
|
+
// Fetch approval details separately
|
|
143
|
+
try {
|
|
144
|
+
const approvalConfig = getGitlabConfig(
|
|
145
|
+
`${gitlabConfig.url}/api/v4/projects/${mr.project_id}/merge_requests/${mr.iid}/approvals`,
|
|
146
|
+
);
|
|
147
|
+
const approvalResponse = await axios.request(approvalConfig);
|
|
148
|
+
const approvalData = approvalResponse.data;
|
|
149
|
+
|
|
150
|
+
// Merge approval data with MR data
|
|
151
|
+
return {
|
|
152
|
+
IssueID: gitDetail.iid,
|
|
153
|
+
MRID: mrData.iid,
|
|
154
|
+
MRAssignedTo: mrData.assignee?.name,
|
|
155
|
+
Repo: mr.reference?.split('!')?.[0],
|
|
156
|
+
ApprovedBy:
|
|
157
|
+
(approvalData.approved_by || [])
|
|
158
|
+
.map((approvedBy) => approvedBy?.user?.name || '')
|
|
159
|
+
?.join(', ') || 'Not Approved',
|
|
160
|
+
ApprovedCount: approvalData.approved_by?.length || 0,
|
|
161
|
+
MergedBy: mrData.merged_by?.name || 'Not Merged',
|
|
162
|
+
MergedOn: mrData.merged_at?.split('T')?.[0] || 'Not Merged',
|
|
163
|
+
};
|
|
164
|
+
} catch (approvalError) {
|
|
165
|
+
console.error(`Error fetching approvals for MR ${mr.iid}:`, approvalError.message);
|
|
166
|
+
// Return MR data without approval details if approval fetch fails
|
|
167
|
+
return mrData;
|
|
168
|
+
}
|
|
169
|
+
} catch (error) {
|
|
170
|
+
console.error(`Error fetching details for MR ${mr.iid}:`, error.message);
|
|
171
|
+
// Return the basic MR data if detailed fetch fails
|
|
172
|
+
return mr;
|
|
173
|
+
}
|
|
174
|
+
}),
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
return detailedMRs;
|
|
178
|
+
} catch (error) {
|
|
179
|
+
console.error('Error fetching GitLab issue merge requests:', error.message);
|
|
180
|
+
|
|
181
|
+
if (error.response) {
|
|
182
|
+
console.error('Response status:', error.response.status);
|
|
183
|
+
console.error('Response data:', error.response.data);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
throw error;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
module.exports = {
|
|
192
|
+
getTaskStats,
|
|
193
|
+
getGitIdStats,
|
|
194
|
+
getGitlabIssueDetails,
|
|
195
|
+
getGitlabIssueMergeRequests,
|
|
196
|
+
getGitMergeRequestDetails,
|
|
197
|
+
};
|
|
@@ -2,25 +2,61 @@ const axios = require('axios');
|
|
|
2
2
|
const cheerio = require('cheerio');
|
|
3
3
|
const { gitlabConfig } = require('../utils');
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Fetches GitLab activities for a date range
|
|
7
|
+
* Defaults to last one week if no values are provided
|
|
8
|
+
* @param {Array} values - Optional array of filter values (e.g., ['-from 2024-11-21', '-to 2024-11-28'])
|
|
9
|
+
* @returns {Object} Object with dates as keys and activities grouped by action
|
|
10
|
+
*/
|
|
5
11
|
const getGitlabActivities = async (values) => {
|
|
6
12
|
const resp = {};
|
|
13
|
+
const res = [];
|
|
7
14
|
const filters = getFilters(values);
|
|
8
15
|
const startDate = new Date(filters.from);
|
|
9
16
|
|
|
17
|
+
// Iterate through each date in the range
|
|
10
18
|
while (startDate <= new Date(filters.to)) {
|
|
11
19
|
const date = startDate.toISOString().split('T')[0];
|
|
12
20
|
const activities = await getGitlabActivitiesByDate(date);
|
|
13
21
|
|
|
14
|
-
if (activities?.length) {
|
|
22
|
+
/* if (activities?.length) {
|
|
15
23
|
resp[date] = arrayToObjectByKey(activities, 'action');
|
|
16
|
-
}
|
|
24
|
+
} */
|
|
25
|
+
res.push(...activities);
|
|
17
26
|
|
|
18
27
|
startDate.setDate(startDate.getDate() + 1);
|
|
19
28
|
}
|
|
20
29
|
|
|
21
|
-
|
|
30
|
+
// Format and display each entry in a single line with ellipses
|
|
31
|
+
const truncate = (str, maxLen = 50) => {
|
|
32
|
+
if (!str) return '';
|
|
33
|
+
return str.length > maxLen ? str.substring(0, maxLen - 3) + '...' : str;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
console.log('\n📊 GitLab Activities (Last Week)\n');
|
|
37
|
+
console.log(
|
|
38
|
+
`\n${'index'.toString().padStart(8)} | ${'date'.toString().padStart(10)} ${'time'.toString().padEnd(8) || ''.padEnd(8)} | ${'action'.toString().padEnd(18)} | ${'text'.toString().padEnd(100)} | ${'project'.toString().padEnd(25)}`,
|
|
39
|
+
);
|
|
40
|
+
res.forEach((activity, index) => {
|
|
41
|
+
const { date, time, action, text, project } = activity;
|
|
42
|
+
const formattedText = truncate(text, 100);
|
|
43
|
+
const formattedAction = action?.padEnd(18) || ''.padEnd(18);
|
|
44
|
+
const formattedProject = truncate(project, 25);
|
|
45
|
+
|
|
46
|
+
console.log(
|
|
47
|
+
`${(index + 1).toString().padStart(8)} | ${date} ${time?.padEnd(8) || ''.padEnd(8)} | ${formattedAction} | ${formattedText.padEnd(100)} | ${formattedProject}`,
|
|
48
|
+
);
|
|
49
|
+
});
|
|
50
|
+
console.log(`\n✅ Total: ${res.length} activities\n`);
|
|
51
|
+
|
|
22
52
|
return resp;
|
|
23
53
|
};
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Parses filter values or sets default to last one week
|
|
57
|
+
* @param {Array} values - Array of filter strings
|
|
58
|
+
* @returns {Object} Object with 'from' and 'to' date strings
|
|
59
|
+
*/
|
|
24
60
|
const getFilters = (values) => {
|
|
25
61
|
const filters = {};
|
|
26
62
|
const keyMap = {
|
|
@@ -31,10 +67,12 @@ const getFilters = (values) => {
|
|
|
31
67
|
};
|
|
32
68
|
|
|
33
69
|
if (values?.length) {
|
|
70
|
+
// Parse provided filter values
|
|
34
71
|
for (const item of values) {
|
|
35
72
|
let [key, ...itemValues] = item.split(' ');
|
|
36
73
|
const itemValue = itemValues.join(' ');
|
|
37
74
|
|
|
75
|
+
// Remove leading dash if present
|
|
38
76
|
if (key.charAt(0) === '-') {
|
|
39
77
|
key = key.substring(1);
|
|
40
78
|
}
|
|
@@ -46,6 +84,7 @@ const getFilters = (values) => {
|
|
|
46
84
|
}
|
|
47
85
|
}
|
|
48
86
|
} else {
|
|
87
|
+
// Default: last one week
|
|
49
88
|
filters.from = new Date(new Date().setDate(new Date().getDate() - 7))
|
|
50
89
|
.toISOString()
|
|
51
90
|
.split('T')[0];
|
|
@@ -54,8 +93,13 @@ const getFilters = (values) => {
|
|
|
54
93
|
|
|
55
94
|
return filters;
|
|
56
95
|
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Fetches GitLab activities for a specific date
|
|
99
|
+
* @param {string} date - Date in YYYY-MM-DD format
|
|
100
|
+
* @returns {Array} Array of activity objects
|
|
101
|
+
*/
|
|
57
102
|
const getGitlabActivitiesByDate = async (date) => {
|
|
58
|
-
const { removeEmpty } = require('./utils');
|
|
59
103
|
const gitlabUrl = `${gitlabConfig.url}/users/${gitlabConfig.userId}/calendar_activities?date=${date}`;
|
|
60
104
|
const headers = {
|
|
61
105
|
accept: 'application/json, text/plain, */*',
|
|
@@ -71,7 +115,6 @@ const getGitlabActivitiesByDate = async (date) => {
|
|
|
71
115
|
'x-csrf-token': gitlabConfig.xCsrfToken,
|
|
72
116
|
'x-requested-with': 'XMLHttpRequest',
|
|
73
117
|
};
|
|
74
|
-
// let config = { method: 'get', maxBodyLength: Infinity, url: `${gitlabUrl}2024-5-10`, headers };
|
|
75
118
|
|
|
76
119
|
try {
|
|
77
120
|
const response = await axios.get(gitlabUrl, { headers });
|
|
@@ -79,45 +122,39 @@ const getGitlabActivitiesByDate = async (date) => {
|
|
|
79
122
|
const $ = cheerio.load(response.data);
|
|
80
123
|
|
|
81
124
|
// Initialize an empty array to store the JSON objects
|
|
82
|
-
|
|
125
|
+
const contributions = [];
|
|
83
126
|
|
|
84
127
|
// Iterate over each list item
|
|
85
|
-
$('
|
|
128
|
+
$('.event-item').each((i, element) => {
|
|
86
129
|
const $element = $(element);
|
|
87
|
-
const time = $element.find('
|
|
88
|
-
const action = $element
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
.
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if (item.title === 'medica-portal-client') {
|
|
109
|
-
acc.repo = item.title;
|
|
110
|
-
} else {
|
|
111
|
-
acc = removeEmpty(item);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return acc;
|
|
115
|
-
}, {});
|
|
130
|
+
const time = $element.find('.event-item-timestamp').text()?.trim();
|
|
131
|
+
const action = $element.find('.event-title-block .event-type').text()?.trim();
|
|
132
|
+
const project = $element.find('.event-title-block .project-name').text()?.trim();
|
|
133
|
+
const $refLink = $element.find('.event-title-block a.ref-name');
|
|
134
|
+
const $targetLink = $element.find('.event-title-block a.event-target-link');
|
|
135
|
+
|
|
136
|
+
let href, text;
|
|
137
|
+
|
|
138
|
+
if ($refLink.length > 0) {
|
|
139
|
+
href = $refLink.attr('href');
|
|
140
|
+
text = $refLink.text()?.trim();
|
|
141
|
+
} else if ($targetLink.length > 0) {
|
|
142
|
+
href = $targetLink.attr('href');
|
|
143
|
+
text = $targetLink.text()?.trim();
|
|
144
|
+
} else {
|
|
145
|
+
const $eventTypeSpan = $element.find('.event-title-block .event-type');
|
|
146
|
+
const nextSpan = $eventTypeSpan.next('span');
|
|
147
|
+
|
|
148
|
+
text = nextSpan.text()?.trim();
|
|
149
|
+
href = undefined;
|
|
150
|
+
}
|
|
116
151
|
|
|
117
152
|
contributions.push({
|
|
118
153
|
time,
|
|
119
154
|
action,
|
|
120
|
-
|
|
155
|
+
text,
|
|
156
|
+
project,
|
|
157
|
+
date,
|
|
121
158
|
});
|
|
122
159
|
});
|
|
123
160
|
|
|
@@ -126,12 +163,5 @@ const getGitlabActivitiesByDate = async (date) => {
|
|
|
126
163
|
console.log(error.message);
|
|
127
164
|
}
|
|
128
165
|
};
|
|
129
|
-
const arrayToObjectByKey = (arr, key) => {
|
|
130
|
-
return arr.reduce((acc, obj) => {
|
|
131
|
-
acc[obj[key]] = obj;
|
|
132
|
-
|
|
133
|
-
return acc;
|
|
134
|
-
}, {});
|
|
135
|
-
};
|
|
136
166
|
|
|
137
167
|
module.exports = { getGitlabActivities };
|
package/services/utils.js
CHANGED
|
@@ -17,6 +17,7 @@ const gitlabConfig = {
|
|
|
17
17
|
xCsrfToken: process.env.GITLAB_XCSRF_TOKEN,
|
|
18
18
|
userId: process.env.GITLAB_USERID,
|
|
19
19
|
token: process.env.GITLAB_TOKEN,
|
|
20
|
+
defaultProjectId: process.env.GITLAB_DEFAULT_PROJECT_ID,
|
|
20
21
|
};
|
|
21
22
|
const zohoConfig = {
|
|
22
23
|
cookie: process.env.ZOHO_COOKIE,
|
|
@@ -56,6 +57,8 @@ const keyMap = {
|
|
|
56
57
|
so: 'source',
|
|
57
58
|
target: 'target',
|
|
58
59
|
ta: 'target',
|
|
60
|
+
docker: 'docker',
|
|
61
|
+
do: 'docker',
|
|
59
62
|
};
|
|
60
63
|
const projectMap = {
|
|
61
64
|
portal: 'medica-portal',
|
|
@@ -297,18 +300,16 @@ const generateDeployConfigs = (values = {}) => {
|
|
|
297
300
|
return { configs: removeEmpty(configs, true) };
|
|
298
301
|
};
|
|
299
302
|
const convertParamsToMap = async (item, type) => {
|
|
300
|
-
const
|
|
301
|
-
ACTIONS.
|
|
302
|
-
ACTIONS.
|
|
303
|
-
ACTIONS.
|
|
304
|
-
ACTIONS.REFACTOR,
|
|
305
|
-
ACTIONS.BACKUP,
|
|
303
|
+
const itemsToCheckLiveness = [
|
|
304
|
+
ACTIONS.BUILD_DEPLOY,
|
|
305
|
+
ACTIONS.BUILD,
|
|
306
|
+
ACTIONS.DEPLOY,
|
|
306
307
|
ACTIONS.MERGE,
|
|
308
|
+
ACTIONS.REVIEW,
|
|
307
309
|
];
|
|
308
|
-
const skipCheck = itemsToSkipCheck.includes(type);
|
|
309
310
|
let live = false;
|
|
310
311
|
|
|
311
|
-
if (
|
|
312
|
+
if (itemsToCheckLiveness.includes(type)) {
|
|
312
313
|
if (!gitlabConfig.token) {
|
|
313
314
|
console.log('Configurations are missing...!');
|
|
314
315
|
return null;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
ACTIONS: {
|
|
3
|
-
INIT: 'init',
|
|
4
|
-
SWITCH: 'switch',
|
|
5
|
-
ADD: 'add',
|
|
6
|
-
UPDATE: 'update',
|
|
7
|
-
DELETE: 'delete',
|
|
8
|
-
STATUS: 'status',
|
|
9
|
-
ENTRIES: 'entries',
|
|
10
|
-
ZOHO: 'zoho',
|
|
11
|
-
GITLAB: 'gitlab',
|
|
12
|
-
MERGE: 'merge',
|
|
13
|
-
VERSION: 'version',
|
|
14
|
-
HELP: 'help',
|
|
15
|
-
},
|
|
16
|
-
};
|