cob-cli 2.52.0-beta-1 → 2.52.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/bin/cob-cli.js +0 -31
- package/lib/commands/deploy.js +26 -33
- package/lib/commands/test.js +9 -29
- package/lib/commands/updateFromServer.js +13 -149
- package/lib/task_lists/common_enviromentHandler.js +8 -14
- package/lib/task_lists/common_helpers.js +17 -96
- package/lib/task_lists/common_releaseManager.js +8 -10
- package/lib/task_lists/common_syncFiles.js +7 -10
- package/lib/task_lists/test_customUIsContinuosReload.js +7 -36
- package/lib/task_lists/test_otherFilesContiousReload.js +22 -44
- package/lib/task_lists/test_syncFile.js +4 -5
- package/lib/task_lists/test_validate.js +2 -3
- package/lib/task_lists/updateFromServer_validate.js +3 -3
- package/lib/webpack/webpack.config.js +1 -1
- package/package.json +1 -5
- package/lib/commands/cleanup.js +0 -116
- package/lib/commands/package.js +0 -20
- package/lib/commands/tagDefs.js +0 -67
- package/lib/task_lists/common_definitions.js +0 -26
- package/lib/task_lists/common_operationState.js +0 -28
- package/lib/task_lists/package_execute.js +0 -45
- package/lib/task_lists/ssh.js +0 -30
- package/lib/task_lists/tagDefs_execute.js +0 -121
- package/lib/task_lists/updateFromServer_definitions.js +0 -135
- package/lib/task_lists/updateFromServer_domains.js +0 -50
- package/lib/task_lists/updateFromServer_groups.js +0 -111
- package/lib/task_lists/updateFromServer_instances.js +0 -76
- package/lib/task_lists/updateFromServer_kibana.js +0 -88
|
@@ -2,10 +2,9 @@ const execa = require('execa');
|
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const fs = require('fs-extra');
|
|
4
4
|
const { getKeypress } = require("../task_lists/common_helpers");
|
|
5
|
-
const { getRsyncSsh, getServerAddress } = require("./common_helpers");
|
|
6
5
|
|
|
7
6
|
/* ************************************ */
|
|
8
|
-
const COB_PRODUCTS = ["recordm", "integrationm", "recordm-importer", "reportm", "userm", "confm", "others", "authm"];
|
|
7
|
+
const COB_PRODUCTS = ["recordm", "integrationm", "recordm-importer", "reportm", "userm", "confm", "others", "authm", "public"];
|
|
9
8
|
|
|
10
9
|
_syncFiles.TEST = "Test equality";
|
|
11
10
|
_syncFiles.DIFF = "Get differences";
|
|
@@ -33,7 +32,6 @@ async function _syncFiles(executionType, cmdEnv, from, to, extraOptions = [], ar
|
|
|
33
32
|
return new Promise(async (resolve, reject) => {
|
|
34
33
|
let fromPath = resolveCobPath(cmdEnv.server, from, product);
|
|
35
34
|
let toPath = resolveCobPath(cmdEnv.server, to, product);
|
|
36
|
-
if (toPath.startsWith('.') && !fs.existsSync(toPath)) fs.mkdirSync(toPath)
|
|
37
35
|
let productExtraOptions = extraOptions.map( option => option.replace(/=.*\|/,"="))
|
|
38
36
|
productExtraOptions = productExtraOptions.filter( option => option.indexOf("|") < 0 )
|
|
39
37
|
|
|
@@ -66,7 +64,7 @@ async function _syncFiles(executionType, cmdEnv, from, to, extraOptions = [], ar
|
|
|
66
64
|
}
|
|
67
65
|
await execa('rsync', rsyncArgs, {
|
|
68
66
|
shell: true,
|
|
69
|
-
env: { "RSYNC_RSH":
|
|
67
|
+
env: { "RSYNC_RSH": "ssh -o ConnectTimeout=30 -o ServerAliveInterval=30 -o ServerAliveCountMax=30" }
|
|
70
68
|
})
|
|
71
69
|
.then((value) => {
|
|
72
70
|
if (args.verbose > 3)
|
|
@@ -171,19 +169,18 @@ function resolveCobPath(server, type, product) {
|
|
|
171
169
|
return "./" + product + "/";
|
|
172
170
|
|
|
173
171
|
case "serverInitial":
|
|
174
|
-
return
|
|
172
|
+
return server + ":/opt/" + product + "/etc.default/";
|
|
175
173
|
|
|
176
174
|
case "serverLive":
|
|
177
175
|
switch (product) {
|
|
176
|
+
case "public":
|
|
177
|
+
return server + ":/usr/share/cob/"
|
|
178
178
|
case "recordm-importer":
|
|
179
179
|
case "others":
|
|
180
|
-
return
|
|
180
|
+
return server + ':' + "/opt/" + product + "/";
|
|
181
181
|
default:
|
|
182
|
-
return
|
|
182
|
+
return server + ':' + "/etc/" + product + "/";
|
|
183
183
|
}
|
|
184
|
-
|
|
185
|
-
case "staging":
|
|
186
|
-
return ".staging/" + product + "/";
|
|
187
184
|
}
|
|
188
185
|
}
|
|
189
186
|
exports.resolveCobPath = resolveCobPath;
|
|
@@ -1,28 +1,11 @@
|
|
|
1
1
|
const execa = require('execa');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
const net = require('net');
|
|
4
3
|
const concurrently = require('concurrently');
|
|
5
4
|
const fs= require('fs');
|
|
6
5
|
const util = require('util');
|
|
7
6
|
const child_process = require('child_process');
|
|
8
7
|
const exec = util.promisify(child_process.exec);
|
|
9
8
|
|
|
10
|
-
function findPort(preferred = 8040) {
|
|
11
|
-
return new Promise((resolve) => {
|
|
12
|
-
const server = net.createServer();
|
|
13
|
-
server.listen(preferred, '0.0.0.0', () => {
|
|
14
|
-
server.close(() => resolve(preferred));
|
|
15
|
-
});
|
|
16
|
-
server.on('error', () => {
|
|
17
|
-
const fallback = net.createServer();
|
|
18
|
-
fallback.listen(0, '0.0.0.0', () => {
|
|
19
|
-
const port = fallback.address().port;
|
|
20
|
-
fallback.close(() => resolve(port));
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
|
|
26
9
|
|
|
27
10
|
async function customUIsContinuosReload(cmdEnv, dashboard) {
|
|
28
11
|
process.env.dash_dir = dashboard
|
|
@@ -39,9 +22,6 @@ async function customUIsContinuosReload(cmdEnv, dashboard) {
|
|
|
39
22
|
throw new Error("Aborted: ".red + " dashboard " + dashboard.bold + " does not exist.\n ")
|
|
40
23
|
}
|
|
41
24
|
|
|
42
|
-
const dashPort = await findPort(8041);
|
|
43
|
-
process.env.dash_port = dashPort;
|
|
44
|
-
|
|
45
25
|
if(dashboardPathIsDirectory) {
|
|
46
26
|
// If we have a dashboard to serve run it from local dashboard directory on 8081 with vue-cli-service
|
|
47
27
|
// it will use its vue.config.js
|
|
@@ -51,15 +31,13 @@ async function customUIsContinuosReload(cmdEnv, dashboard) {
|
|
|
51
31
|
commands.push( {
|
|
52
32
|
command: [
|
|
53
33
|
"cd " + dashboardPath + ";",
|
|
54
|
-
"node_modules/.bin/vue-cli-service serve --port
|
|
55
|
-
].join(" "),
|
|
34
|
+
"node_modules/.bin/vue-cli-service serve --port 8041 2>/dev/null"
|
|
35
|
+
].join(" "),
|
|
56
36
|
name: 'dashboard server',
|
|
57
|
-
prefixColor: "red"
|
|
37
|
+
prefixColor: "red"
|
|
58
38
|
})
|
|
59
39
|
}
|
|
60
40
|
|
|
61
|
-
const port = await findPort(8040);
|
|
62
|
-
|
|
63
41
|
console.log( "\n" + (" NOTE: Press " + "O".bold.red + " to open default browser, " + "CTRL+C".bold.red + " or " + "Q".bold.red + " to stop the tests... ").yellow.bold + "\n\n" )
|
|
64
42
|
|
|
65
43
|
const insideCobCliPath = path.resolve(__dirname, '../../node_modules/.bin/webpack-dev-server');
|
|
@@ -72,9 +50,8 @@ async function customUIsContinuosReload(cmdEnv, dashboard) {
|
|
|
72
50
|
webpackDevServerPath,
|
|
73
51
|
"--config",
|
|
74
52
|
path.resolve(__dirname, "../webpack/webpack.config.js"),
|
|
75
|
-
"--mode=development"
|
|
76
|
-
|
|
77
|
-
].join(" "),
|
|
53
|
+
"--mode=development"
|
|
54
|
+
].join(" "),
|
|
78
55
|
name: 'customUIs server',
|
|
79
56
|
prefixColor: "blue"
|
|
80
57
|
})
|
|
@@ -105,20 +82,14 @@ async function customUIsContinuosReload(cmdEnv, dashboard) {
|
|
|
105
82
|
}
|
|
106
83
|
}
|
|
107
84
|
|
|
108
|
-
|
|
109
|
-
const failurePromise = new Promise((_, reject) => { notifyFailure = reject; });
|
|
110
|
-
|
|
111
|
-
conc.result.catch( _err => {
|
|
85
|
+
conc.result.catch( _err => {
|
|
112
86
|
if(isStopping) return;
|
|
113
87
|
|
|
114
88
|
stopEverything();
|
|
115
|
-
notifyFailure(new Error('processes-failed'));
|
|
116
89
|
});
|
|
117
90
|
|
|
118
91
|
return {
|
|
119
|
-
stop: stopEverything
|
|
120
|
-
failed: failurePromise,
|
|
121
|
-
port
|
|
92
|
+
stop: stopEverything
|
|
122
93
|
};
|
|
123
94
|
}
|
|
124
95
|
exports.customUIsContinuosReload = customUIsContinuosReload;
|
|
@@ -7,7 +7,6 @@ const { SERVER_COB_CLI_DIRECTORY } = require("./common_helpers");
|
|
|
7
7
|
const { confirmExecutionOfChanges, resolveCobPath } = require("./common_syncFiles");
|
|
8
8
|
const { syncFile } = require("./test_syncFile");
|
|
9
9
|
const { getLastDeployedSha } = require("./common_releaseManager");
|
|
10
|
-
const { getSshArgs } = require("./common_helpers");
|
|
11
10
|
|
|
12
11
|
const IN_PROGRESS_TEST_FILE = "test.in.execution"
|
|
13
12
|
const SERVER_IN_PROGRESS_TEST_FILE = SERVER_COB_CLI_DIRECTORY + IN_PROGRESS_TEST_FILE
|
|
@@ -19,7 +18,7 @@ async function otherFilesContiousReload(cmdEnv) {
|
|
|
19
18
|
let changedFiles = new Set()
|
|
20
19
|
|
|
21
20
|
let currentTestsFilesList = []
|
|
22
|
-
await execa('ssh', [
|
|
21
|
+
await execa('ssh', [cmdEnv.server, "cat " + SERVER_IN_PROGRESS_TEST_FILE])
|
|
23
22
|
.then( value => currentTestsFilesList = value.stdout.split("\n").map(l => l.substring(0,l.indexOf(" "))) )
|
|
24
23
|
.catch( () => { } ) /* grep returns error if no match and execa throws an excepcions when return is error */
|
|
25
24
|
|
|
@@ -30,7 +29,22 @@ async function otherFilesContiousReload(cmdEnv) {
|
|
|
30
29
|
let restoreChanges = async () => {
|
|
31
30
|
if(watcher.process) watcher.process.close();
|
|
32
31
|
if(changedFiles.size > 0) {
|
|
33
|
-
|
|
32
|
+
console.log("\nRestoring changed files...".yellow);
|
|
33
|
+
let stash = true;
|
|
34
|
+
await git().env('LC_ALL', 'C').stash(["--include-untracked"]).then( value => value.indexOf("Saved") == 0 || (stash = false))
|
|
35
|
+
let lastSha = await getLastDeployedSha(cmdEnv.server)
|
|
36
|
+
await git().checkout(lastSha)
|
|
37
|
+
|
|
38
|
+
await cmdEnv.applyLastEnvironmentDeployedToServerChanges()
|
|
39
|
+
for(let changedFile of changedFiles) {
|
|
40
|
+
await removeFileFromCurrentTest(cmdEnv.server, changedFile);
|
|
41
|
+
}
|
|
42
|
+
await cmdEnv.unApplyLastEnvironmentDeployedToServerChanges()
|
|
43
|
+
|
|
44
|
+
await execa('ssh', [cmdEnv.server,"find " + SERVER_IN_PROGRESS_TEST_FILE + " -size 0 -delete "]) //Remove file if empty
|
|
45
|
+
|
|
46
|
+
await git().checkout("-")
|
|
47
|
+
if (stash) await git().stash(["pop"])
|
|
34
48
|
}
|
|
35
49
|
fs.unlinkSync("."+IN_PROGRESS_TEST_FILE)
|
|
36
50
|
}
|
|
@@ -57,7 +71,7 @@ async function otherFilesContiousReload(cmdEnv) {
|
|
|
57
71
|
let productDir = resolveCobPath(cmdEnv.server, "serverLive", product).split(":")[1];
|
|
58
72
|
let productScopeFilePath = changedFile.substring(changedFile.indexOf("/") + 1); // remove o directorio inicial do producto
|
|
59
73
|
|
|
60
|
-
let isRemoteFile = () => execa('ssh', [
|
|
74
|
+
let isRemoteFile = () => execa('ssh', [cmdEnv.server, "[[ -f " + productDir + productScopeFilePath + " ]] && echo 'file' || echo '' " ])
|
|
61
75
|
.then( r => {
|
|
62
76
|
return r.stdout == "file"
|
|
63
77
|
}).catch( () => {
|
|
@@ -100,45 +114,10 @@ async function otherFilesContiousReload(cmdEnv) {
|
|
|
100
114
|
}
|
|
101
115
|
exports.otherFilesContiousReload = otherFilesContiousReload
|
|
102
116
|
|
|
103
|
-
/* ************************************ */
|
|
104
|
-
async function restoreServerFilesToLastDeployed(cmdEnv, changedFiles) {
|
|
105
|
-
console.log("\nRestoring changed files...".yellow);
|
|
106
|
-
|
|
107
|
-
// Clean up any env-swap markers left by applyCurrentCommandEnvironmentChanges before
|
|
108
|
-
// stashing. These files are gitignored, so git stash --include-untracked ignores them.
|
|
109
|
-
// If they survive into _undoSpecific(lastEnv) they create ghost env files that are
|
|
110
|
-
// untracked at lastSha, causing "git checkout -" to abort.
|
|
111
|
-
await cmdEnv.unApplyCurrentCommandEnvironmentChanges();
|
|
112
|
-
|
|
113
|
-
let stashed = false;
|
|
114
|
-
await git().env('LC_ALL', 'C').stash(["--include-untracked"])
|
|
115
|
-
.then(value => { stashed = value.indexOf("Saved") === 0; })
|
|
116
|
-
.catch(() => {});
|
|
117
|
-
|
|
118
|
-
const lastSha = await getLastDeployedSha(cmdEnv.server);
|
|
119
|
-
if (!lastSha) throw new Error("Cannot restore server files: no previous deploy found on server.");
|
|
120
|
-
await git().checkout(lastSha);
|
|
121
|
-
|
|
122
|
-
await cmdEnv.applyLastEnvironmentDeployedToServerChanges();
|
|
123
|
-
|
|
124
|
-
for (const changedFile of changedFiles) {
|
|
125
|
-
await removeFileFromCurrentTest(cmdEnv.server, changedFile);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
await cmdEnv.unApplyLastEnvironmentDeployedToServerChanges();
|
|
129
|
-
|
|
130
|
-
await execa('ssh', [...getSshArgs(cmdEnv.server), "find " + SERVER_IN_PROGRESS_TEST_FILE + " -size 0 -delete"])
|
|
131
|
-
.catch(() => {});
|
|
132
|
-
|
|
133
|
-
await git().checkout("-");
|
|
134
|
-
if (stashed) await git().stash(["pop"]);
|
|
135
|
-
}
|
|
136
|
-
exports.restoreServerFilesToLastDeployed = restoreServerFilesToLastDeployed
|
|
137
|
-
|
|
138
117
|
/* ************************************ */
|
|
139
118
|
async function addFileToCurrentTest(server, changedFile, changedFiles, changeType, restoreChanges) {
|
|
140
119
|
let inUse = "";
|
|
141
|
-
await execa('ssh', [
|
|
120
|
+
await execa('ssh', [server, "grep -F '" + changedFile + " ' " + SERVER_IN_PROGRESS_TEST_FILE ])
|
|
142
121
|
.then( value => inUse = value.stdout )
|
|
143
122
|
.catch( () => { } ) /* grep returns error if no match and execa throws an excepcions when return is error */
|
|
144
123
|
.finally( async () => {
|
|
@@ -154,7 +133,7 @@ async function addFileToCurrentTest(server, changedFile, changedFiles, changeTyp
|
|
|
154
133
|
|
|
155
134
|
if(!changedFiles.has(changedFile)) {
|
|
156
135
|
const user = require("os").userInfo().username;
|
|
157
|
-
execa('ssh', [
|
|
136
|
+
execa('ssh', [server, "echo '" + changedFile + " by " + user + "' >> " + SERVER_IN_PROGRESS_TEST_FILE]);
|
|
158
137
|
changedFiles.add(changedFile);
|
|
159
138
|
}
|
|
160
139
|
console.log(" " + changeType.replace(/(e)([^e]*)$/, "ed$2 ") + changedFile);
|
|
@@ -164,14 +143,13 @@ async function addFileToCurrentTest(server, changedFile, changedFiles, changeTyp
|
|
|
164
143
|
/* ************************************ */
|
|
165
144
|
async function removeFileFromCurrentTest(server, changedFile) {
|
|
166
145
|
await syncFile(server, changedFile);
|
|
167
|
-
await execa('ssh', [
|
|
146
|
+
await execa('ssh', [server, "sed -i '/" + changedFile.split("/").join("\\/") + "/d' " + SERVER_IN_PROGRESS_TEST_FILE]).catch( () => {/* ignore files removed by user */} );
|
|
168
147
|
console.log(" reset ".brightGreen + changedFile);
|
|
169
148
|
}
|
|
170
|
-
exports.removeFileFromCurrentTest = removeFileFromCurrentTest
|
|
171
149
|
|
|
172
150
|
/* ************************************ */
|
|
173
151
|
function checkNoTestsRunningOnServer(server) {
|
|
174
|
-
return execa('ssh', [
|
|
152
|
+
return execa('ssh', [server, "cat " + SERVER_IN_PROGRESS_TEST_FILE])
|
|
175
153
|
.then(value => {
|
|
176
154
|
throw new Error(
|
|
177
155
|
"Aborted:".red + " there are tests running with files changed on the server:\n "
|
|
@@ -2,7 +2,6 @@ const execa = require('execa');
|
|
|
2
2
|
const fs = require('fs-extra');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const { resolveCobPath } = require("./common_syncFiles");
|
|
5
|
-
const { getSshArgs, getRsyncSsh } = require("./common_helpers");
|
|
6
5
|
|
|
7
6
|
const DEBUG = false;
|
|
8
7
|
const RSYNC_RETRIES = 10;
|
|
@@ -19,7 +18,7 @@ async function syncFile(server, localFile) {
|
|
|
19
18
|
|
|
20
19
|
let count = 0;
|
|
21
20
|
while (count < RSYNC_RETRIES) {
|
|
22
|
-
await execa('ssh', [
|
|
21
|
+
await execa('ssh', [server, "mkdir -p " + remoteFileDir]).catch({});
|
|
23
22
|
await execa('rsync', [localFile, remoteProductPath + productScopeFilePath,
|
|
24
23
|
"-acz",
|
|
25
24
|
"--prune-empty-dirs",
|
|
@@ -29,17 +28,17 @@ async function syncFile(server, localFile) {
|
|
|
29
28
|
"--no-t",
|
|
30
29
|
"--filter='merge " + path.resolve(__dirname,"rsyncFilter-pre.txt") + "'",
|
|
31
30
|
"--filter='merge " + path.resolve(__dirname,"rsyncFilter-post.txt") + "'"],
|
|
32
|
-
{ shell: true, env: { "RSYNC_RSH":
|
|
31
|
+
{ shell: true, env: { "RSYNC_RSH": "ssh -o ConnectTimeout=30 -o ServerAliveInterval=30 -o ServerAliveCountMax=30" } })
|
|
33
32
|
.then(count = RSYNC_RETRIES)
|
|
34
33
|
.catch(async (err) => {
|
|
35
34
|
// exitCode 23 indicam que o ficheiro não existe na origem. Temod de apagar no destino.
|
|
36
35
|
if (err.exitCode == 23) {
|
|
37
|
-
await execa('ssh', [
|
|
36
|
+
await execa('ssh', [server, "rm -fd " + remoteProductPath.split(":")[1] + productScopeFilePath]).catch({});
|
|
38
37
|
|
|
39
38
|
let localFileDir = localFile.substring(0, localFile.lastIndexOf("/"));
|
|
40
39
|
if (!fs.existsSync(localFileDir)) {
|
|
41
40
|
if (DEBUG) console.log(remoteFileDir + " needs to be removed");
|
|
42
|
-
await execa('ssh', [
|
|
41
|
+
await execa('ssh', [server, "rm -rf " + remoteFileDir]).catch({});
|
|
43
42
|
}
|
|
44
43
|
count = RSYNC_RETRIES;
|
|
45
44
|
} else if ((count + 1)> RSYNC_RETRIES) {
|
|
@@ -9,7 +9,6 @@ const { checkConnectivity } = require("./common_helpers");
|
|
|
9
9
|
const { getCurrentBranch, getLastDeployedSha } = require("./common_releaseManager");
|
|
10
10
|
const { testEquality } = require("./common_syncFiles");
|
|
11
11
|
const { SERVER_IN_PROGRESS_TEST_FILE } = require("../task_lists/test_otherFilesContiousReload");
|
|
12
|
-
const { getSshArgs } = require("./common_helpers");
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
async function validateTestingConditions(cmdEnv, args) {
|
|
@@ -80,7 +79,7 @@ async function _handleTestEquality(ctx, changes, server) {
|
|
|
80
79
|
let offendingFiles = changes.map(f => f.substring(17)) //17 é a posição onde começa o nome dos ficheiros em cada linha
|
|
81
80
|
let problemFiles = [];
|
|
82
81
|
for(let changedFile of offendingFiles) {
|
|
83
|
-
await execa('ssh', [
|
|
82
|
+
await execa('ssh', [server, "grep -F " + changedFile + " " + SERVER_IN_PROGRESS_TEST_FILE ])
|
|
84
83
|
.catch( () => {
|
|
85
84
|
try {
|
|
86
85
|
if (fs.lstatSync(changedFile.trim()).isFile()) {
|
|
@@ -95,7 +94,7 @@ async function _handleTestEquality(ctx, changes, server) {
|
|
|
95
94
|
if(problemFiles.length > 0) throw new Error("Aborted:".red + " server was changed since last deploy:\n " + problemFiles.join("\n ") + "\n" );
|
|
96
95
|
|
|
97
96
|
let inTest = "";
|
|
98
|
-
await execa('ssh', [
|
|
97
|
+
await execa('ssh', [server, "cat " + SERVER_IN_PROGRESS_TEST_FILE])
|
|
99
98
|
.then( value => inTest = value.stdout )
|
|
100
99
|
.catch( () => { } ) /* grep returns error if no match and execa throws an excepcions when return is error */
|
|
101
100
|
.finally( async () => {
|
|
@@ -8,7 +8,7 @@ function validateUpdateFromServerConditions(cmdEnv) {
|
|
|
8
8
|
return new Listr([
|
|
9
9
|
{ title: "Check connectivity and permissions".bold, task: () => checkConnectivity(cmdEnv.server) },
|
|
10
10
|
{ title: "Check there's no cob-cli test' running".bold, task: () => checkNoTestsRunningOnServer(cmdEnv.server) },
|
|
11
|
-
{ title: "Check git status".bold, task: () => checkWorkingCopyCleanliness() },
|
|
12
|
-
|
|
11
|
+
{ title: "Check git status".bold, task: () => checkWorkingCopyCleanliness() },
|
|
12
|
+
])
|
|
13
13
|
}
|
|
14
|
-
exports.validateUpdateFromServerConditions = validateUpdateFromServerConditions
|
|
14
|
+
exports.validateUpdateFromServerConditions = validateUpdateFromServerConditions
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cob-cli",
|
|
3
|
-
"version": "2.52.0
|
|
3
|
+
"version": "2.52.0",
|
|
4
4
|
"description": "A command line utility to help Cult of Bits partners develop with higher speed and reusing common code and best practices.",
|
|
5
5
|
"preferGlobal": true,
|
|
6
6
|
"repository": {
|
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@webpack-cli/serve": "^2.0.1",
|
|
20
20
|
"axios": "^0.21.1",
|
|
21
|
-
"axios-cookiejar-support": "^5.0.5",
|
|
22
21
|
"chokidar": "^3.5.3",
|
|
23
22
|
"cmd-line-importer": "^1.0.0",
|
|
24
23
|
"colors": "^1.4.0",
|
|
@@ -29,14 +28,11 @@
|
|
|
29
28
|
"file-cookie-store": "^0.2.1",
|
|
30
29
|
"fs-extra": "^9.0.1",
|
|
31
30
|
"inquirer": "^7.3.3",
|
|
32
|
-
"js-yaml": "^4.1.0",
|
|
33
31
|
"listr": "^0.14.3",
|
|
34
32
|
"ncp": "^2.0.0",
|
|
35
33
|
"omelette": "^0.4.15-1",
|
|
36
34
|
"open": "^8.4.0",
|
|
37
35
|
"simple-git": "^3.15.1",
|
|
38
|
-
"tar": "^7.4.3",
|
|
39
|
-
"tough-cookie": "^5.1.2",
|
|
40
36
|
"webpack": "^5.75.0",
|
|
41
37
|
"webpack-cli": "^5.0.1",
|
|
42
38
|
"webpack-dev-server": "^4.11.1",
|
package/lib/commands/cleanup.js
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
require('colors');
|
|
2
|
-
const git = require('simple-git');
|
|
3
|
-
const fs = require('fs-extra');
|
|
4
|
-
const fg = require('fast-glob');
|
|
5
|
-
const execa = require('execa');
|
|
6
|
-
const Listr = require('listr');
|
|
7
|
-
const UpdaterRenderer = require('listr-update-renderer');
|
|
8
|
-
const verboseRenderer = require('listr-verbose-renderer');
|
|
9
|
-
const { getCurrentCommandEnviroment } = require("../task_lists/common_enviromentHandler");
|
|
10
|
-
const { SERVER_COB_CLI_DIRECTORY } = require("../task_lists/common_helpers");
|
|
11
|
-
const { restoreServerFilesToLastDeployed } = require("../task_lists/test_otherFilesContiousReload");
|
|
12
|
-
const { loadOperationState, clearOperationState } = require("../task_lists/common_operationState");
|
|
13
|
-
const { checkRepoVersion } = require("../commands/upgradeRepo");
|
|
14
|
-
const { getSshArgs } = require("../task_lists/common_helpers");
|
|
15
|
-
|
|
16
|
-
const LOCAL_TEST_LOCK_FILE = ".test.in.execution";
|
|
17
|
-
const SERVER_TEST_LOCK_FILE = SERVER_COB_CLI_DIRECTORY + "test.in.execution";
|
|
18
|
-
|
|
19
|
-
async function cleanup(args) {
|
|
20
|
-
try {
|
|
21
|
-
checkRepoVersion()
|
|
22
|
-
|
|
23
|
-
const savedState = loadOperationState();
|
|
24
|
-
if (!savedState && !args.environment) {
|
|
25
|
-
console.log("No saved state and no explicit environment, aborting".bold);
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
if (savedState) {
|
|
29
|
-
if (!args.environment) args.environment = savedState.environment;
|
|
30
|
-
if (!args.servername) args.servername = savedState.servername;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
console.log("Cleaning up interrupted test/deploy state...".bold)
|
|
34
|
-
|
|
35
|
-
const cmdEnv = await getCurrentCommandEnviroment(args)
|
|
36
|
-
console.log(` environment: ${cmdEnv.name.bold} server: ${cmdEnv.serverStr}`)
|
|
37
|
-
|
|
38
|
-
await new Listr([
|
|
39
|
-
{
|
|
40
|
-
title: "Undo environment-specific file changes".bold,
|
|
41
|
-
skip: async () => {
|
|
42
|
-
const backupFiles = await fg(
|
|
43
|
-
['**/*.ENV__ORIGINAL_BACKUP__.*', '**/*.ENV__DELETE__.*'],
|
|
44
|
-
{ onlyFiles: false, dot: true }
|
|
45
|
-
);
|
|
46
|
-
return backupFiles.length === 0 ? "No environment-specific changes found" : false;
|
|
47
|
-
},
|
|
48
|
-
task: () => cmdEnv.unApplyCurrentCommandEnvironmentChanges()
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
// Runs after the local env undo so the working tree is clean before
|
|
52
|
-
// stashing and checking out the last-deployed SHA.
|
|
53
|
-
title: "Restore server files to last deployed version".bold,
|
|
54
|
-
skip: () => args.localOnly ? "Skipping server restore (--localOnly)" : false,
|
|
55
|
-
task: async () => {
|
|
56
|
-
let changedFiles = [];
|
|
57
|
-
try {
|
|
58
|
-
const result = await execa('ssh', [...getSshArgs(cmdEnv.server), "cat " + SERVER_TEST_LOCK_FILE]);
|
|
59
|
-
changedFiles = result.stdout.split("\n")
|
|
60
|
-
.map(l => l.split(" ")[0].trim())
|
|
61
|
-
.filter(f => f);
|
|
62
|
-
} catch (error) {
|
|
63
|
-
if (error.exitCode === 255) {
|
|
64
|
-
throw new Error(`SSH connection to '${cmdEnv.server}' failed: ${error.shortMessage}`);
|
|
65
|
-
}
|
|
66
|
-
/* no test.in.execution on server = nothing to restore */
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (changedFiles.length === 0) return;
|
|
70
|
-
|
|
71
|
-
await restoreServerFilesToLastDeployed(cmdEnv, changedFiles);
|
|
72
|
-
}
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
title: "Restore git branch from detached HEAD".bold,
|
|
76
|
-
skip: async () => {
|
|
77
|
-
const branch = await git().revparse(["--abbrev-ref", "HEAD"]);
|
|
78
|
-
return branch.trim() !== "HEAD" ? "Not in detached HEAD state" : false;
|
|
79
|
-
},
|
|
80
|
-
task: () => git().checkout("-")
|
|
81
|
-
},
|
|
82
|
-
{
|
|
83
|
-
title: "Remove local test lock file".bold,
|
|
84
|
-
skip: () => !fs.existsSync(LOCAL_TEST_LOCK_FILE) ? "No local test lock file found" : false,
|
|
85
|
-
task: () => fs.unlinkSync(LOCAL_TEST_LOCK_FILE)
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
title: "Remove server test lock file".bold,
|
|
89
|
-
skip: () => args.localOnly ? "Skipping server cleanup (--localOnly)" : false,
|
|
90
|
-
task: () => execa('ssh', [...getSshArgs(cmdEnv.server), "rm -f " + SERVER_TEST_LOCK_FILE])
|
|
91
|
-
.catch(() => {}) // non-critical if server unreachable
|
|
92
|
-
},
|
|
93
|
-
], {
|
|
94
|
-
renderer: args.verbose ? verboseRenderer : UpdaterRenderer,
|
|
95
|
-
collapse: false
|
|
96
|
-
}).run()
|
|
97
|
-
|
|
98
|
-
clearOperationState()
|
|
99
|
-
|
|
100
|
-
// Inform about stashes — don't auto-pop since user may have unrelated stashes
|
|
101
|
-
const stashList = await git().stash(["list"]);
|
|
102
|
-
if (stashList) {
|
|
103
|
-
console.log("\n" + "Note:".yellow.bold
|
|
104
|
-
+ " Stashed changes detected (may be from the interrupted operation):")
|
|
105
|
-
console.log(stashList.split("\n").slice(0, 3).map(l => " " + l).join("\n"))
|
|
106
|
-
console.log("Run " + "git stash pop".yellow + " if you want to restore your uncommitted changes.\n")
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
console.log("\nDone!".green, "\nYou can now run 'cob-cli test' or 'cob-cli deploy' again.\n")
|
|
110
|
-
|
|
111
|
-
} catch(err) {
|
|
112
|
-
console.error("\n", err.message)
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
module.exports = cleanup;
|
package/lib/commands/package.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
require('colors');
|
|
2
|
-
const { checkRepoVersion } = require("../commands/upgradeRepo");
|
|
3
|
-
const { getCurrentCommandEnviroment } = require("../task_lists/common_enviromentHandler");
|
|
4
|
-
const { executeTasks } = require("../task_lists/package_execute");
|
|
5
|
-
|
|
6
|
-
async function package(args) {
|
|
7
|
-
try {
|
|
8
|
-
checkRepoVersion()
|
|
9
|
-
const cmdEnv = await getCurrentCommandEnviroment(args)
|
|
10
|
-
if(args.resync) args.force = true;
|
|
11
|
-
|
|
12
|
-
await executeTasks(cmdEnv, args).run();
|
|
13
|
-
|
|
14
|
-
console.log("\nDone!".green, "\nEnjoy!")
|
|
15
|
-
|
|
16
|
-
} catch(err) {
|
|
17
|
-
console.error("\n",err.message);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
module.exports = package;
|
package/lib/commands/tagDefs.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
require('colors');
|
|
2
|
-
const { getCurrentCommandEnviroment } = require("../task_lists/common_enviromentHandler");
|
|
3
|
-
const { promptCredentials, readYamlFile } = require("../task_lists/common_helpers.js");
|
|
4
|
-
const { tagDefinitions } = require("../task_lists/tagDefs_execute.js");
|
|
5
|
-
const { checkRepoVersion } = require("../commands/upgradeRepo");
|
|
6
|
-
const axios = require('axios');
|
|
7
|
-
const tough = require('tough-cookie');
|
|
8
|
-
const axiosCookieJarSupport = require('axios-cookiejar-support')
|
|
9
|
-
const path = require('path')
|
|
10
|
-
const FileCookieStore = require('file-cookie-store');
|
|
11
|
-
|
|
12
|
-
async function tagDefs(args) {
|
|
13
|
-
try {
|
|
14
|
-
checkRepoVersion()
|
|
15
|
-
const cmdEnv = await getCurrentCommandEnviroment(args)
|
|
16
|
-
|
|
17
|
-
axiosCookieJarSupport.wrapper(axios)
|
|
18
|
-
axios.defaults.ignoreCookieErrors = true
|
|
19
|
-
axios.defaults.withCredentials = true
|
|
20
|
-
const cookieJar = new tough.CookieJar()
|
|
21
|
-
axios.defaults.jar = cookieJar
|
|
22
|
-
|
|
23
|
-
if( args.cookie ) {
|
|
24
|
-
const p = path.resolve(args.cookie);
|
|
25
|
-
const cookieFile = new FileCookieStore(p, {auto_sync: false, force_parse: true});
|
|
26
|
-
try{
|
|
27
|
-
let c = await new Promise((resolve, reject) => {
|
|
28
|
-
cookieFile.findCookie(`${cmdEnv.servername}.cultofbits.com`, '/', 'cobtoken', (err, result) => {
|
|
29
|
-
if(err != null) reject(err);
|
|
30
|
-
else resolve(result)
|
|
31
|
-
})
|
|
32
|
-
});
|
|
33
|
-
if(!c){
|
|
34
|
-
throw Error( `couldn't find a cookie for ${cmdEnv.servername} in ${p}`)
|
|
35
|
-
}
|
|
36
|
-
cookieJar.setCookie(c.toString(), `https://${cmdEnv.servername}.cultofbits.com`)
|
|
37
|
-
} catch(e){
|
|
38
|
-
console.error(e)
|
|
39
|
-
return
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
} else {
|
|
43
|
-
|
|
44
|
-
const credentials = await promptCredentials()
|
|
45
|
-
|
|
46
|
-
await axios.post(`https://${cmdEnv.servername}.cultofbits.com/recordm/security/auth`, credentials, {
|
|
47
|
-
headers: {
|
|
48
|
-
"Content-Type": "application/json",
|
|
49
|
-
},
|
|
50
|
-
})
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const solutions = await readYamlFile("solutions.yml")
|
|
54
|
-
|
|
55
|
-
for (const solution of solutions) {
|
|
56
|
-
console.log("\nStarting to tag Defs of solution " + solution.name, solution.definitions)
|
|
57
|
-
if (solution.definitions) {
|
|
58
|
-
await tagDefinitions(cmdEnv.servername, solution.name, solution.definitions, args)
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
} catch (err) {
|
|
63
|
-
console.error("\n", err.message);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
module.exports = tagDefs;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
const axios = require("axios");
|
|
2
|
-
|
|
3
|
-
async function getFilteredDefinitions(servername, defConfigs) {
|
|
4
|
-
const uri = `https://${servername}.cultofbits.com/recordm/recordm/definitions`
|
|
5
|
-
const response = await axios.get( uri );
|
|
6
|
-
|
|
7
|
-
if(response.status != 200){
|
|
8
|
-
throw new Error(`HTTP Error Response: ${response.status} ${response.statusText}`);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
let result = defConfigs.flatMap(c => {
|
|
12
|
-
return response.data.filter(def => match(c.filter, def))
|
|
13
|
-
.map(m => ({...m, ...c}))
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
return result
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function match(query, definition) {
|
|
20
|
-
// simple matching for now
|
|
21
|
-
return definition.name.includes(query) || definition.description?.includes(query)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
module.exports = {
|
|
25
|
-
getFilteredDefinitions: getFilteredDefinitions
|
|
26
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
const fs = require('fs-extra');
|
|
2
|
-
const fg = require('fast-glob');
|
|
3
|
-
const STATE_FILE = ".git/cob-cli-state";
|
|
4
|
-
|
|
5
|
-
function saveOperationState(environment, servername) {
|
|
6
|
-
try { fs.writeJsonSync(STATE_FILE, { environment, servername }); } catch {}
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
function loadOperationState() {
|
|
10
|
-
try { return fs.readJsonSync(STATE_FILE); } catch { return null; }
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function clearOperationState() {
|
|
14
|
-
try { fs.unlinkSync(STATE_FILE); } catch {}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async function checkNoInterruptedRun() {
|
|
18
|
-
const stateExists = !!loadOperationState();
|
|
19
|
-
const envBackupFiles = await fg(['**/*.ENV__ORIGINAL_BACKUP__.*', '**/*.ENV__DELETE__.*'], { onlyFiles: false, dot: true });
|
|
20
|
-
if (stateExists || envBackupFiles.length > 0) {
|
|
21
|
-
throw new Error(
|
|
22
|
-
"\nAborted:".red + " found traces of a previous interrupted test/deploy.\n"
|
|
23
|
-
+ "Run " + "cob-cli cleanup".yellow + " to restore the repo to a clean state first.\n"
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
module.exports = { saveOperationState, loadOperationState, clearOperationState, checkNoInterruptedRun };
|