nitor 1.3.1 → 1.3.3
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 +146 -8
- package/package.json +1 -1
- package/services/cleanup.js +12 -8
- package/services/mongodb-backup.js +25 -10
- package/services/process-commands.js +16 -12
- package/services/task-stats.js +7 -1
- package/services/time-entry/get-report.js +4 -2
- package/services/time-entry/utils.js +0 -24
- package/services/utils.js +1 -1
package/README.md
CHANGED
|
@@ -115,14 +115,19 @@ Once enabled, you can use Tab to autocomplete:
|
|
|
115
115
|
```bash
|
|
116
116
|
nitor refactor <text>
|
|
117
117
|
```
|
|
118
|
-
- **Backup:**
|
|
119
|
-
|
|
120
|
-
nitor backup <text>
|
|
121
|
-
```
|
|
122
|
-
- **Restore:**
|
|
118
|
+
- **MongoDB Backup & Restore:**
|
|
119
|
+
|
|
123
120
|
```bash
|
|
124
|
-
|
|
121
|
+
# Backup from Kubernetes pods and restore to local MongoDB
|
|
122
|
+
nitor backup
|
|
123
|
+
|
|
124
|
+
# Backup specific projects only
|
|
125
|
+
nitor backup -project <project1> <project2>
|
|
126
|
+
|
|
127
|
+
# Restore to Docker container (default: local MongoDB)
|
|
128
|
+
nitor backup -docker <boolean>
|
|
125
129
|
```
|
|
130
|
+
|
|
126
131
|
- **Merge:**
|
|
127
132
|
```bash
|
|
128
133
|
nitor merge -source <source branch> -target <target branch>
|
|
@@ -191,8 +196,7 @@ Once enabled, you can use Tab to autocomplete:
|
|
|
191
196
|
- `create-branch` : Create git branch
|
|
192
197
|
- `review` : AI review specified merge request
|
|
193
198
|
- `refactor` : AI refactor specified text
|
|
194
|
-
- `backup` : Backup
|
|
195
|
-
- `restore` : Restore specified projects
|
|
199
|
+
- `backup` : Backup MongoDB databases from Kubernetes pods and restore to local/Docker
|
|
196
200
|
- `merge` : Merge source branch into target branch
|
|
197
201
|
- `cleanup` : Cleanup local git branches (checkout to master and delete all other branches)
|
|
198
202
|
- `time-init` : Initialize time entry configuration
|
|
@@ -208,6 +212,140 @@ Once enabled, you can use Tab to autocomplete:
|
|
|
208
212
|
- `task-stats` : View task statistics with GitLab merge request details
|
|
209
213
|
- `get-task` : Extract Zoho task IDs from GitLab issue descriptions
|
|
210
214
|
|
|
215
|
+
## MongoDB Backup & Restore
|
|
216
|
+
|
|
217
|
+
### Overview
|
|
218
|
+
|
|
219
|
+
The MongoDB backup service provides automated backup and restore functionality for MongoDB databases running in Kubernetes pods. It supports:
|
|
220
|
+
|
|
221
|
+
- ✅ Backup from Kubernetes pods using `kubectl`
|
|
222
|
+
- ✅ Restore to Docker containers or local MongoDB instances
|
|
223
|
+
- ✅ Cross-platform support (Windows, macOS, Linux)
|
|
224
|
+
- ✅ Multi-project configuration
|
|
225
|
+
- ✅ Automatic cleanup of temporary files
|
|
226
|
+
- ✅ Error handling with detailed logging
|
|
227
|
+
|
|
228
|
+
### Configuration
|
|
229
|
+
|
|
230
|
+
Configure your backup settings in the `.env.nu` file using JSON format:
|
|
231
|
+
|
|
232
|
+
#### BACKUP_CONFIG
|
|
233
|
+
|
|
234
|
+
Defines the source databases to backup from Kubernetes pods:
|
|
235
|
+
|
|
236
|
+
```json
|
|
237
|
+
BACKUP_CONFIG={
|
|
238
|
+
"project1": [
|
|
239
|
+
{
|
|
240
|
+
"pod": "mongodb-pod-name",
|
|
241
|
+
"username": "admin",
|
|
242
|
+
"password": "password123",
|
|
243
|
+
"database": "mydb",
|
|
244
|
+
"backupPath": "/data/backup",
|
|
245
|
+
"localBackupPath": "~/backups/mongo"
|
|
246
|
+
}
|
|
247
|
+
],
|
|
248
|
+
"project2": [
|
|
249
|
+
{
|
|
250
|
+
"pod": "another-pod",
|
|
251
|
+
"username": "dbuser",
|
|
252
|
+
"password": "dbpass",
|
|
253
|
+
"database": "anotherdb"
|
|
254
|
+
}
|
|
255
|
+
]
|
|
256
|
+
}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
**Configuration Options:**
|
|
260
|
+
|
|
261
|
+
- `pod` (required): Name of the Kubernetes pod
|
|
262
|
+
- `username` (required): MongoDB username
|
|
263
|
+
- `password` (required): MongoDB password
|
|
264
|
+
- `database` (required): Database name
|
|
265
|
+
- `backupPath` (optional): Path inside pod for temporary backup (default: `/data/backup`)
|
|
266
|
+
- `localBackupPath` (optional): Local path to store backups (default: `~/backups/mongo`)
|
|
267
|
+
|
|
268
|
+
#### RESTORE_CONFIG
|
|
269
|
+
|
|
270
|
+
Defines where to restore the backup:
|
|
271
|
+
|
|
272
|
+
```json
|
|
273
|
+
RESTORE_CONFIG={
|
|
274
|
+
"mongoInDocker": false,
|
|
275
|
+
"containerName": "mongodb",
|
|
276
|
+
"localBackupPath": "~/backups/mongo",
|
|
277
|
+
"containerBackupPath": "/data/backup"
|
|
278
|
+
}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
**Configuration Options:**
|
|
282
|
+
|
|
283
|
+
- `mongoInDocker` (optional): Set to `true` to restore to Docker container, `false` for local MongoDB (can be overridden with `-docker` flag)
|
|
284
|
+
- `containerName` (optional): Docker container name (default: `mongodb`)
|
|
285
|
+
- `localBackupPath` (optional): Path where backup is stored (default: `~/backups/mongo`)
|
|
286
|
+
- `containerBackupPath` (optional): Path inside container for temporary files (default: `/data/backup`)
|
|
287
|
+
|
|
288
|
+
### How It Works
|
|
289
|
+
|
|
290
|
+
1. **Backup Phase:**
|
|
291
|
+
|
|
292
|
+
- Executes `mongodump` inside the Kubernetes pod
|
|
293
|
+
- Copies backup files to your local machine using `kubectl cp`
|
|
294
|
+
- Cleans up temporary files from the pod
|
|
295
|
+
- Saves to `~/backups/mongo/<database-name>` by default
|
|
296
|
+
|
|
297
|
+
2. **Restore Phase:**
|
|
298
|
+
- **Docker Mode** (`-docker` flag):
|
|
299
|
+
- Copies backup from local machine to Docker container
|
|
300
|
+
- Executes `mongorestore --drop` inside the container
|
|
301
|
+
- Cleans up temporary files from container
|
|
302
|
+
- **Local Mode** (default):
|
|
303
|
+
- Executes `mongorestore --drop` directly on local machine
|
|
304
|
+
- Connects to `mongodb://localhost:27017/`
|
|
305
|
+
|
|
306
|
+
### Usage Examples
|
|
307
|
+
|
|
308
|
+
**Backup all configured projects:**
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
nitor backup
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
**Backup specific projects:**
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
nitor backup -project project1 project2
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
**Backup and restore to Docker container:**
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
nitor backup -docker
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Prerequisites
|
|
327
|
+
|
|
328
|
+
- **For Backup:** `kubectl` configured with access to your Kubernetes cluster
|
|
329
|
+
- **For Restore (Docker):** Docker running with MongoDB container
|
|
330
|
+
- **For Restore (Local):** MongoDB installed and running locally on port 27017
|
|
331
|
+
- MongoDB tools (`mongodump`, `mongorestore`) must be available in the pod/container
|
|
332
|
+
|
|
333
|
+
### Cross-Platform Support
|
|
334
|
+
|
|
335
|
+
The backup service is designed to work on Windows, macOS, and Linux:
|
|
336
|
+
|
|
337
|
+
- Automatically detects the operating system
|
|
338
|
+
- Uses appropriate shell (`cmd.exe` on Windows, `/bin/sh` on Unix)
|
|
339
|
+
- Handles path normalization across platforms
|
|
340
|
+
- Adjusts command flags for Windows compatibility (e.g., removes `-it` flags)
|
|
341
|
+
|
|
342
|
+
### Error Handling
|
|
343
|
+
|
|
344
|
+
- Non-zero exit codes from `mongorestore` are treated as warnings (common with duplicate keys)
|
|
345
|
+
- Detailed error messages with color-coded output
|
|
346
|
+
- Continues processing remaining projects even if one fails
|
|
347
|
+
- Cleanup operations run even if restore encounters errors
|
|
348
|
+
|
|
211
349
|
### Options
|
|
212
350
|
|
|
213
351
|
- `-project` or `-p` : Project name (`portal`, `gateway`, `phr`)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nitor",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3",
|
|
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
|
@@ -15,15 +15,15 @@ const cleanup = async () => {
|
|
|
15
15
|
|
|
16
16
|
// Get current branch
|
|
17
17
|
const currentBranch = execSync('git branch --show-current', execOptions).trim();
|
|
18
|
-
console.log(`Current branch: ${currentBranch}`);
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
console.log(`Current branch: ${currentBranch}`);
|
|
21
20
|
console.log('\nChecking out to master branch...');
|
|
22
21
|
try {
|
|
23
22
|
execSync('git checkout master', execOptionsInherit);
|
|
24
23
|
} catch (error) {
|
|
25
24
|
// Try main if master doesn't exist
|
|
26
25
|
console.log('Master branch not found, trying main...');
|
|
26
|
+
|
|
27
27
|
execSync('git checkout main', execOptionsInherit);
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -40,28 +40,32 @@ const cleanup = async () => {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
console.log(`\nFound ${branches.length} branch(es) to delete:`);
|
|
43
|
-
|
|
44
|
-
// Delete each branch
|
|
45
43
|
console.log('\nDeleting branches...');
|
|
44
|
+
|
|
46
45
|
let deletedCount = 0;
|
|
47
46
|
let failedCount = 0;
|
|
48
47
|
|
|
49
48
|
for (const branch of branches) {
|
|
50
49
|
try {
|
|
51
50
|
execSync(`git branch -D ${branch}`, execOptions);
|
|
52
|
-
|
|
51
|
+
execSync(`rm -rf ~/.git/logs/refs/heads/${branch}`, execOptions);
|
|
52
|
+
execSync(`rm -rf ~/.git/refs/heads/${branch}`, execOptions);
|
|
53
|
+
|
|
54
|
+
console.log(`Deleted: ${branch}`);
|
|
55
|
+
|
|
53
56
|
deletedCount++;
|
|
54
57
|
} catch (error) {
|
|
55
|
-
console.log(`
|
|
58
|
+
console.log(`Failed to delete: ${branch}`);
|
|
59
|
+
|
|
56
60
|
failedCount++;
|
|
57
61
|
}
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
console.log(`\nCleanup complete!`);
|
|
61
|
-
console.log(`
|
|
65
|
+
console.log(`Deleted: ${deletedCount} branch(es)`);
|
|
62
66
|
|
|
63
67
|
if (failedCount > 0) {
|
|
64
|
-
console.log(`
|
|
68
|
+
console.log(`Failed: ${failedCount} branch(es)`);
|
|
65
69
|
}
|
|
66
70
|
} catch (error) {
|
|
67
71
|
console.error('Error during cleanup:', error.message);
|
|
@@ -45,12 +45,18 @@ const executeMongoRestore = async (config) => {
|
|
|
45
45
|
// Step 2: Execute mongorestore inside the container
|
|
46
46
|
// Remove -it flag for Windows compatibility (causes issues in non-interactive shells)
|
|
47
47
|
const restoreCommand = isWindows
|
|
48
|
-
? `docker exec ${containerName} mongorestore ${containerBackupPath}`
|
|
49
|
-
: `docker exec -it ${containerName} mongorestore ${containerBackupPath}`;
|
|
48
|
+
? `docker exec ${containerName} mongorestore --drop --stopOnError=false ${containerBackupPath}`
|
|
49
|
+
: `docker exec -it ${containerName} mongorestore --drop --stopOnError=false ${containerBackupPath}`;
|
|
50
50
|
|
|
51
51
|
console.log('Executing mongorestore...');
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
try {
|
|
53
|
+
execSync(restoreCommand, { stdio: 'inherit', shell: isWindows ? 'cmd.exe' : '/bin/sh' });
|
|
54
|
+
console.log(`${colors.green}✓ Mongorestore completed successfully${colors.reset}`);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.log(
|
|
57
|
+
`${colors.red}⚠ Mongorestore completed with some errors (check output above for details)${colors.reset}`,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
54
60
|
|
|
55
61
|
// Step 3: Remove backup data from container
|
|
56
62
|
const cleanupCommand = isWindows
|
|
@@ -66,12 +72,21 @@ const executeMongoRestore = async (config) => {
|
|
|
66
72
|
console.log(`\nStarting MongoDB restore to local machine`);
|
|
67
73
|
|
|
68
74
|
console.log('Executing mongorestore...');
|
|
69
|
-
const localRestoreCommand = `mongorestore --uri="mongodb://localhost:27017/" "${normalizedLocalPath}"`;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
+
const localRestoreCommand = `mongorestore --drop --stopOnError=false --uri="mongodb://localhost:27017/" "${normalizedLocalPath}"`;
|
|
76
|
+
try {
|
|
77
|
+
execSync(localRestoreCommand, {
|
|
78
|
+
stdio: 'inherit',
|
|
79
|
+
shell: isWindows ? 'cmd.exe' : '/bin/sh',
|
|
80
|
+
});
|
|
81
|
+
console.log(`${colors.green}✓ Mongorestore completed successfully${colors.reset}`);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
// mongorestore returns non-zero even for partial success (e.g., duplicate keys)
|
|
84
|
+
// Log the warning but don't throw unless it's a critical failure
|
|
85
|
+
console.log(
|
|
86
|
+
`${colors.red}⚠ Mongorestore completed with some errors (this may be expected if data already exists)${colors.reset}`,
|
|
87
|
+
);
|
|
88
|
+
console.log(`Check the output above for details`);
|
|
89
|
+
}
|
|
75
90
|
|
|
76
91
|
console.log(`${colors.green}Restore completed successfully!${colors.reset}\n`);
|
|
77
92
|
}
|
|
@@ -11,7 +11,7 @@ const { merge } = require('./merge');
|
|
|
11
11
|
const { cleanup } = require('./cleanup');
|
|
12
12
|
|
|
13
13
|
// Time entry imports
|
|
14
|
-
const {
|
|
14
|
+
const { getSprints } = require('./time-entry/utils');
|
|
15
15
|
const { getStatus, getTasksByDate } = require('./time-entry/get-report');
|
|
16
16
|
const { logTaskHoursAndSync } = require('./time-entry/log-task-hours-and-sync');
|
|
17
17
|
const { addNewTask } = require('./time-entry/add-task');
|
|
@@ -199,7 +199,7 @@ Enhance the provided text for improved clarity, conciseness, and professional qu
|
|
|
199
199
|
Backup mongodb for specified project and components.
|
|
200
200
|
|
|
201
201
|
project list:
|
|
202
|
-
-
|
|
202
|
+
- configService
|
|
203
203
|
- medicaCentralAuth
|
|
204
204
|
- medicaPortal
|
|
205
205
|
- phr`);
|
|
@@ -387,7 +387,7 @@ Options:
|
|
|
387
387
|
|
|
388
388
|
// Time entry commands
|
|
389
389
|
case ACTIONS.TIME_ADD: {
|
|
390
|
-
const timeValues = value ?
|
|
390
|
+
const timeValues = value ? value.split(' -') : value;
|
|
391
391
|
|
|
392
392
|
await addNewTask(timeValues);
|
|
393
393
|
|
|
@@ -395,7 +395,7 @@ Options:
|
|
|
395
395
|
}
|
|
396
396
|
|
|
397
397
|
case ACTIONS.TIME_UPDATE: {
|
|
398
|
-
const timeValues = value ?
|
|
398
|
+
const timeValues = value ? value.split(' -') : value;
|
|
399
399
|
|
|
400
400
|
await updateTask(timeValues);
|
|
401
401
|
|
|
@@ -403,7 +403,7 @@ Options:
|
|
|
403
403
|
}
|
|
404
404
|
|
|
405
405
|
case ACTIONS.TIME_DELETE: {
|
|
406
|
-
const timeValues = value ?
|
|
406
|
+
const timeValues = value ? value.split(' -') : value;
|
|
407
407
|
|
|
408
408
|
console.log(await deleteTask(timeValues));
|
|
409
409
|
|
|
@@ -411,7 +411,7 @@ Options:
|
|
|
411
411
|
}
|
|
412
412
|
|
|
413
413
|
case ACTIONS.TIME_STATUS: {
|
|
414
|
-
const timeValues = value ?
|
|
414
|
+
const timeValues = value ? value.split(' -') : value;
|
|
415
415
|
|
|
416
416
|
await getStatus(timeValues);
|
|
417
417
|
|
|
@@ -419,7 +419,7 @@ Options:
|
|
|
419
419
|
}
|
|
420
420
|
|
|
421
421
|
case ACTIONS.TIME_ENTRIES: {
|
|
422
|
-
const timeValues = value ?
|
|
422
|
+
const timeValues = value ? value.split(' -') : value;
|
|
423
423
|
|
|
424
424
|
console.table(await getTasksByDate(timeValues));
|
|
425
425
|
|
|
@@ -433,7 +433,7 @@ Options:
|
|
|
433
433
|
}
|
|
434
434
|
|
|
435
435
|
case ACTIONS.TIME_GITLAB: {
|
|
436
|
-
const timeValues = value ?
|
|
436
|
+
const timeValues = value ? value.split(' -') : value;
|
|
437
437
|
|
|
438
438
|
await getGitlabActivities(timeValues);
|
|
439
439
|
|
|
@@ -505,6 +505,7 @@ Options:
|
|
|
505
505
|
\t[${ACTIONS.BUILD}] [${ACTIONS.DEPLOY}] [${ACTIONS.BUILD_DEPLOY}]
|
|
506
506
|
\t[${ACTIONS.CREATE_BRANCH}] [${ACTIONS.REVIEW}] [${ACTIONS.MERGE}]
|
|
507
507
|
\t[${ACTIONS.CLEANUP}] [${ACTIONS.BACKUP}] [${ACTIONS.REFACTOR}]
|
|
508
|
+
\t[${ACTIONS.TASK_STATS}] [${ACTIONS.GET_TASK}]
|
|
508
509
|
\t[${ACTIONS.TIME_INIT}] [${ACTIONS.TIME_ADD}] [${ACTIONS.TIME_STATUS}]\n
|
|
509
510
|
Available commands:\n
|
|
510
511
|
backup : Backup MongoDB databases
|
|
@@ -514,11 +515,11 @@ Available commands:\n
|
|
|
514
515
|
completion : Setup shell autocomplete
|
|
515
516
|
create-branch : Create git branch
|
|
516
517
|
deploy : Deploy specified components
|
|
517
|
-
get-task : Get task details
|
|
518
|
+
get-task : Get task details from GitLab merge requests
|
|
518
519
|
merge : Merge source branch into target branch
|
|
519
520
|
refactor : Refactor the provided text for improved clarity, conciseness, and professional quality
|
|
520
521
|
review : AI Review specified merge request
|
|
521
|
-
task-stats : View task statistics
|
|
522
|
+
task-stats : View task statistics and merge request details
|
|
522
523
|
version : Show version info
|
|
523
524
|
help : Show help
|
|
524
525
|
|
|
@@ -542,9 +543,11 @@ Example usage:\n
|
|
|
542
543
|
nitor cleanup
|
|
543
544
|
nitor create-branch -task <task number> -type <feat|fix> -description <description> -project <project short name>
|
|
544
545
|
nitor deploy -project <project> -components <components> -instance <instance>
|
|
546
|
+
nitor get-task -task <task numbers with space>
|
|
545
547
|
nitor merge -source <source branch> -target <target branch>
|
|
546
548
|
nitor refactor <text>
|
|
547
549
|
nitor review -project <project short name> -mergeId <merge id> -repository <repository name>
|
|
550
|
+
nitor task-stats -task <task number>
|
|
548
551
|
nitor time-init
|
|
549
552
|
nitor time-add
|
|
550
553
|
nitor time-stats
|
|
@@ -559,11 +562,12 @@ Running 'nitor help' will list available subcommands and provide some conceptual
|
|
|
559
562
|
return;
|
|
560
563
|
}
|
|
561
564
|
}
|
|
565
|
+
|
|
566
|
+
process.exit(1);
|
|
562
567
|
} catch (error) {
|
|
563
568
|
console.log(error);
|
|
569
|
+
process.exit(1);
|
|
564
570
|
}
|
|
565
|
-
|
|
566
|
-
process.exit(1);
|
|
567
571
|
};
|
|
568
572
|
|
|
569
573
|
module.exports = { processArgs };
|
package/services/task-stats.js
CHANGED
|
@@ -122,6 +122,8 @@ const getGitMergeRequestDetails = async (issueIid, projectId) => {
|
|
|
122
122
|
};
|
|
123
123
|
|
|
124
124
|
const getGitlabIssueMergeRequests = async (gitDetails) => {
|
|
125
|
+
const skippedMrBranches = ['dev-qa-testing', 'qa-testing'];
|
|
126
|
+
|
|
125
127
|
for (const gitDetail of gitDetails) {
|
|
126
128
|
try {
|
|
127
129
|
const mergeRequests = await getGitMergeRequestDetails(
|
|
@@ -137,6 +139,10 @@ const getGitlabIssueMergeRequests = async (gitDetails) => {
|
|
|
137
139
|
const detailResponse = await axios.request(detailConfig);
|
|
138
140
|
const mrData = detailResponse.data;
|
|
139
141
|
|
|
142
|
+
if (skippedMrBranches.some((branch) => mrData.target_branch.includes(branch))) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
140
146
|
// Fetch approval details separately
|
|
141
147
|
try {
|
|
142
148
|
const approvalConfig = getGitlabConfig(
|
|
@@ -150,7 +156,7 @@ const getGitlabIssueMergeRequests = async (gitDetails) => {
|
|
|
150
156
|
IssueID: gitDetail.iid,
|
|
151
157
|
MRID: mrData.iid,
|
|
152
158
|
MRAssignedTo: mrData.assignee?.name,
|
|
153
|
-
|
|
159
|
+
MRTarget: mrData.target_branch,
|
|
154
160
|
Repo: mr.reference?.split('!')?.[0],
|
|
155
161
|
ApprovedBy:
|
|
156
162
|
(approvalData.approved_by || [])
|
|
@@ -4,7 +4,6 @@ const {
|
|
|
4
4
|
path,
|
|
5
5
|
readFileSync,
|
|
6
6
|
userHomeDir,
|
|
7
|
-
removeEmpty,
|
|
8
7
|
} = require('./utils');
|
|
9
8
|
const getTasksByDate = async (filters) => {
|
|
10
9
|
try {
|
|
@@ -29,7 +28,10 @@ const getTasksByDate = async (filters) => {
|
|
|
29
28
|
const item = readFileSync(path.join(userHomeDir, `.${stringDate}`));
|
|
30
29
|
|
|
31
30
|
if (item) {
|
|
32
|
-
const timeEntries =
|
|
31
|
+
const timeEntries = item
|
|
32
|
+
.split(contentTableSeparator)[1]
|
|
33
|
+
.split('\n')
|
|
34
|
+
.filter((entry) => entry.trim() !== '');
|
|
33
35
|
|
|
34
36
|
data = data.concat(
|
|
35
37
|
timeEntries.map((entry) =>
|
|
@@ -228,29 +228,6 @@ const readFileSync = (path) => {
|
|
|
228
228
|
// console.log(error);
|
|
229
229
|
}
|
|
230
230
|
};
|
|
231
|
-
const removeEmpty = (obj) => {
|
|
232
|
-
for (let [key, val] of Object.entries(obj)) {
|
|
233
|
-
if (val && typeof val === 'object') {
|
|
234
|
-
this.removeEmpty(val);
|
|
235
|
-
|
|
236
|
-
if (!(Object.keys(val).length || val instanceof Date)) {
|
|
237
|
-
delete obj[key];
|
|
238
|
-
}
|
|
239
|
-
} else {
|
|
240
|
-
if (typeof val === 'string') {
|
|
241
|
-
val = val.trim();
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
if (val === null || val === undefined || val === '') {
|
|
245
|
-
delete obj[key];
|
|
246
|
-
} else {
|
|
247
|
-
obj[key] = val;
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
return obj;
|
|
253
|
-
};
|
|
254
231
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
255
232
|
const userConfig = async (jsonData) => {
|
|
256
233
|
return new Promise((resolve, reject) => {
|
|
@@ -293,7 +270,6 @@ module.exports = {
|
|
|
293
270
|
mkdirSync,
|
|
294
271
|
path,
|
|
295
272
|
readFileSync,
|
|
296
|
-
removeEmpty,
|
|
297
273
|
rl,
|
|
298
274
|
userConfig,
|
|
299
275
|
userHomeDir,
|
package/services/utils.js
CHANGED
|
@@ -22,7 +22,7 @@ const gitlabConfig = {
|
|
|
22
22
|
const zohoConfig = {
|
|
23
23
|
cookie: process.env.ZOHO_COOKIE,
|
|
24
24
|
customViewId: process.env.ZOHO_CUSTOMVIEW_ID,
|
|
25
|
-
defaultProjectId: process.env.
|
|
25
|
+
defaultProjectId: process.env.ZOHO_DEFAULT_PROJECT_ID,
|
|
26
26
|
portalId: process.env.ZOHO_PORTAL_ID,
|
|
27
27
|
projects: process.env.ZOHO_PROJECTS,
|
|
28
28
|
sessionId: process.env.ZOHO_SESSION_ID,
|