spectrum-cli 1.1.1 → 1.2.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 +21 -0
- package/README.md +63 -11
- package/index.js +63 -37
- package/package.json +5 -3
- package/src/changelog.js +96 -57
- package/src/chart.js +821 -0
- package/src/command-executor.js +70 -0
- package/src/development.js +11 -11
- package/src/git.js +59 -40
- package/src/preflight.js +556 -0
- package/src/release.js +102 -55
- package/src/utils.js +47 -9
- package/src/version.js +23 -17
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const { logError, logSuccess } = require('./utils');
|
|
3
|
+
|
|
4
|
+
function normalizeCheckResult(result, fallbackReason) {
|
|
5
|
+
if (typeof result === 'boolean') {
|
|
6
|
+
return { ok: result, reason: result ? null : fallbackReason };
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
if (typeof result === 'string') {
|
|
10
|
+
return { ok: false, reason: result };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (result && typeof result === 'object') {
|
|
14
|
+
return {
|
|
15
|
+
ok: Boolean(result.ok),
|
|
16
|
+
reason: result.reason || fallbackReason,
|
|
17
|
+
data: result.data
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return { ok: false, reason: fallbackReason };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async function runCommand(spec) {
|
|
25
|
+
const {
|
|
26
|
+
name,
|
|
27
|
+
checks = [],
|
|
28
|
+
steps = [],
|
|
29
|
+
context = {}
|
|
30
|
+
} = spec || {};
|
|
31
|
+
|
|
32
|
+
if (!name) {
|
|
33
|
+
logError('❌', 'Требуется имя команды.');
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
for (const check of checks) {
|
|
38
|
+
const checkName = check.name || 'unknown-check';
|
|
39
|
+
const checkResult = normalizeCheckResult(
|
|
40
|
+
await check.run(context),
|
|
41
|
+
`Проверка не пройдена: ${checkName}`
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
if (!checkResult.ok) {
|
|
45
|
+
/* istanbul ignore next */
|
|
46
|
+
logError('❌', '[%s] Предпроверка не пройдена (%s): %s', name, checkName, checkResult.reason || 'неизвестная причина');
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (checkResult.data && typeof checkResult.data === 'object') {
|
|
51
|
+
Object.assign(context, checkResult.data);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
for (const step of steps) {
|
|
56
|
+
const stepName = step.name || 'unknown-step';
|
|
57
|
+
const ok = await step.run(context);
|
|
58
|
+
if (!ok) {
|
|
59
|
+
logError('❌', '[%s] Шаг не выполнен: %s', name, stepName);
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
logSuccess('✅', '[%s] Выполнено.', name);
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
module.exports = {
|
|
69
|
+
runCommand
|
|
70
|
+
};
|
package/src/development.js
CHANGED
|
@@ -10,10 +10,10 @@ function dev() {
|
|
|
10
10
|
case 'yarn':
|
|
11
11
|
return execCommand('yarn dev');
|
|
12
12
|
case 'bun':
|
|
13
|
-
logError('⚠️', 'Bun
|
|
13
|
+
logError('⚠️', 'Bun пока не поддерживается');
|
|
14
14
|
return false;
|
|
15
15
|
default:
|
|
16
|
-
logError('⚠️', '
|
|
16
|
+
logError('⚠️', 'Менеджер пакетов не найден');
|
|
17
17
|
return false;
|
|
18
18
|
}
|
|
19
19
|
}
|
|
@@ -27,10 +27,10 @@ function test() {
|
|
|
27
27
|
case 'yarn':
|
|
28
28
|
return execCommand('NODE_ENV=test yarn dev');
|
|
29
29
|
case 'bun':
|
|
30
|
-
logError('⚠️', 'Bun
|
|
30
|
+
logError('⚠️', 'Bun пока не поддерживается');
|
|
31
31
|
return false;
|
|
32
32
|
default:
|
|
33
|
-
logError('⚠️', '
|
|
33
|
+
logError('⚠️', 'Менеджер пакетов не найден');
|
|
34
34
|
return false;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -44,10 +44,10 @@ function deps() {
|
|
|
44
44
|
case 'yarn':
|
|
45
45
|
return execCommand('yarn install');
|
|
46
46
|
case 'bun':
|
|
47
|
-
logError('⚠️', 'Bun
|
|
47
|
+
logError('⚠️', 'Bun пока не поддерживается');
|
|
48
48
|
return false;
|
|
49
49
|
default:
|
|
50
|
-
logError('⚠️', '
|
|
50
|
+
logError('⚠️', 'Менеджер пакетов не найден');
|
|
51
51
|
return false;
|
|
52
52
|
}
|
|
53
53
|
}
|
|
@@ -63,7 +63,7 @@ function build() {
|
|
|
63
63
|
case 'bun':
|
|
64
64
|
return execCommand('bun run build');
|
|
65
65
|
default:
|
|
66
|
-
logError('⚠️', '
|
|
66
|
+
logError('⚠️', 'Менеджер пакетов не найден');
|
|
67
67
|
return false;
|
|
68
68
|
}
|
|
69
69
|
}
|
|
@@ -77,10 +77,10 @@ function e2e() {
|
|
|
77
77
|
case 'yarn':
|
|
78
78
|
return execCommand('yarn test:e2e');
|
|
79
79
|
case 'bun':
|
|
80
|
-
logError('⚠️', 'Bun
|
|
80
|
+
logError('⚠️', 'Bun пока не поддерживается');
|
|
81
81
|
return false;
|
|
82
82
|
default:
|
|
83
|
-
logError('⚠️', '
|
|
83
|
+
logError('⚠️', 'Менеджер пакетов не найден');
|
|
84
84
|
return false;
|
|
85
85
|
}
|
|
86
86
|
}
|
|
@@ -94,10 +94,10 @@ function e2eui() {
|
|
|
94
94
|
case 'yarn':
|
|
95
95
|
return execCommand('yarn test:e2e --ui');
|
|
96
96
|
case 'bun':
|
|
97
|
-
logError('⚠️', 'Bun
|
|
97
|
+
logError('⚠️', 'Bun пока не поддерживается');
|
|
98
98
|
return false;
|
|
99
99
|
default:
|
|
100
|
-
logError('⚠️', '
|
|
100
|
+
logError('⚠️', 'Менеджер пакетов не найден');
|
|
101
101
|
return false;
|
|
102
102
|
}
|
|
103
103
|
}
|
package/src/git.js
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const { logSuccess,
|
|
2
|
+
const { logSuccess, execCommand, getCurrentBranch, getMainBranch, getDevelopBranch } = require('./utils');
|
|
3
|
+
const { runCommand } = require('./command-executor');
|
|
4
|
+
const {
|
|
5
|
+
requireGitRepo,
|
|
6
|
+
requireCleanWorkingTree,
|
|
7
|
+
requireOnMainBranch,
|
|
8
|
+
requireCurrentBranchUpToDateWithRemote,
|
|
9
|
+
requirePackageVersion,
|
|
10
|
+
requireTagMissing
|
|
11
|
+
} = require('./preflight');
|
|
3
12
|
|
|
4
13
|
function goToMainBranch() {
|
|
5
14
|
const mainBranch = getMainBranch();
|
|
6
|
-
if (execCommand(`git switch ${mainBranch}
|
|
7
|
-
logSuccess('🌿',
|
|
15
|
+
if (execCommand(`git switch ${mainBranch}`)) {
|
|
16
|
+
logSuccess('🌿', 'Переключение на ветку %s выполнено.', mainBranch);
|
|
8
17
|
return true;
|
|
9
18
|
}
|
|
10
19
|
return false;
|
|
@@ -12,8 +21,8 @@ function goToMainBranch() {
|
|
|
12
21
|
|
|
13
22
|
function goToDevBranch() {
|
|
14
23
|
const devBranch = getDevelopBranch();
|
|
15
|
-
if (execCommand(`git switch ${devBranch}
|
|
16
|
-
logSuccess('🌿',
|
|
24
|
+
if (execCommand(`git switch ${devBranch}`)) {
|
|
25
|
+
logSuccess('🌿', 'Переключение на ветку %s выполнено.', getCurrentBranch());
|
|
17
26
|
return true;
|
|
18
27
|
}
|
|
19
28
|
return false;
|
|
@@ -21,11 +30,11 @@ function goToDevBranch() {
|
|
|
21
30
|
|
|
22
31
|
function updateCurrentBranch() {
|
|
23
32
|
const currentBranch = getCurrentBranch();
|
|
24
|
-
const pullSuccess = execCommand(`git pull origin ${currentBranch}
|
|
25
|
-
const fetchSuccess = execCommand(`git fetch --all --prune --jobs=10
|
|
33
|
+
const pullSuccess = execCommand(`git pull origin ${currentBranch}`);
|
|
34
|
+
const fetchSuccess = execCommand(`git fetch --all --prune --jobs=10`);
|
|
26
35
|
|
|
27
36
|
if (pullSuccess && fetchSuccess) {
|
|
28
|
-
logSuccess('🔄',
|
|
37
|
+
logSuccess('🔄', 'Для ветки %s выполнены pull и fetch.', currentBranch);
|
|
29
38
|
return true;
|
|
30
39
|
}
|
|
31
40
|
return false;
|
|
@@ -38,8 +47,8 @@ function gitMergeOriginDev() {
|
|
|
38
47
|
goToDevBranch();
|
|
39
48
|
updateCurrentBranch();
|
|
40
49
|
|
|
41
|
-
if (execCommand(`git switch ${currentBranch}
|
|
42
|
-
return execCommand(`git merge origin/${devBranch}
|
|
50
|
+
if (execCommand(`git switch ${currentBranch}`)) {
|
|
51
|
+
return execCommand(`git merge origin/${devBranch}`);
|
|
43
52
|
}
|
|
44
53
|
return false;
|
|
45
54
|
}
|
|
@@ -54,48 +63,58 @@ function gitLfsReset() {
|
|
|
54
63
|
|
|
55
64
|
let success = true;
|
|
56
65
|
for (const command of commands) {
|
|
57
|
-
if (!execCommand(command
|
|
66
|
+
if (!execCommand(command)) {
|
|
58
67
|
success = false;
|
|
59
68
|
break;
|
|
60
69
|
}
|
|
61
70
|
}
|
|
62
71
|
|
|
63
72
|
if (success) {
|
|
64
|
-
execCommand('rm .gitattributes'
|
|
65
|
-
execCommand('git restore .gitattributes'
|
|
66
|
-
logSuccess('📦', '
|
|
73
|
+
execCommand('rm .gitattributes');
|
|
74
|
+
execCommand('git restore .gitattributes');
|
|
75
|
+
logSuccess('📦', 'git-lfs переустановлен, файлы очищены.');
|
|
67
76
|
}
|
|
68
77
|
|
|
69
78
|
return success;
|
|
70
79
|
}
|
|
71
80
|
|
|
72
81
|
function gitCreateTagAndPush() {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
82
|
+
return runCommand({
|
|
83
|
+
name: 'release deploy',
|
|
84
|
+
checks: [
|
|
85
|
+
{ name: 'git-repo', run: requireGitRepo },
|
|
86
|
+
{ name: 'clean-working-tree', run: requireCleanWorkingTree },
|
|
87
|
+
{ name: 'on-main-branch', run: requireOnMainBranch },
|
|
88
|
+
{ name: 'branch-up-to-date', run: requireCurrentBranchUpToDateWithRemote },
|
|
89
|
+
{ name: 'package-version', run: requirePackageVersion },
|
|
90
|
+
{
|
|
91
|
+
name: 'tag-missing',
|
|
92
|
+
run: (ctx) => requireTagMissing(`v${ctx.version}`)
|
|
93
|
+
}
|
|
94
|
+
],
|
|
95
|
+
steps: [
|
|
96
|
+
{
|
|
97
|
+
name: 'update-main-branch',
|
|
98
|
+
run: () => updateCurrentBranch()
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
name: 'create-tag',
|
|
102
|
+
run: (ctx) => {
|
|
103
|
+
if (!execCommand(`git tag v${ctx.version}`)) return false;
|
|
104
|
+
logSuccess('🔖', 'Создан тег v%s.', ctx.version);
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
name: 'push-tag',
|
|
110
|
+
run: (ctx) => {
|
|
111
|
+
if (!execCommand(`git push origin v${ctx.version}`)) return false;
|
|
112
|
+
logSuccess('🚀', 'Тег v%s отправлен.', ctx.version);
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
});
|
|
99
118
|
}
|
|
100
119
|
|
|
101
120
|
|