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.
@@ -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
+ };
@@ -10,10 +10,10 @@ function dev() {
10
10
  case 'yarn':
11
11
  return execCommand('yarn dev');
12
12
  case 'bun':
13
- logError('⚠️', 'Bun not implemented');
13
+ logError('⚠️', 'Bun пока не поддерживается');
14
14
  return false;
15
15
  default:
16
- logError('⚠️', 'No package manager found');
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 not implemented');
30
+ logError('⚠️', 'Bun пока не поддерживается');
31
31
  return false;
32
32
  default:
33
- logError('⚠️', 'No package manager found');
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 not implemented');
47
+ logError('⚠️', 'Bun пока не поддерживается');
48
48
  return false;
49
49
  default:
50
- logError('⚠️', 'No package manager found');
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('⚠️', 'No package manager found');
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 not implemented');
80
+ logError('⚠️', 'Bun пока не поддерживается');
81
81
  return false;
82
82
  default:
83
- logError('⚠️', 'No package manager found');
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 not implemented');
97
+ logError('⚠️', 'Bun пока не поддерживается');
98
98
  return false;
99
99
  default:
100
- logError('⚠️', 'No package manager found');
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, logError, execSilent, execCommand, getCurrentBranch, getMainBranch, getDevelopBranch, getVersion } = require('./utils');
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}`, null, null)) {
7
- logSuccess('🌿', `Swap to branch ${mainBranch}.`);
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}`, null, null)) {
16
- logSuccess('🌿', `Swap to branch ${getCurrentBranch()}.`);
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}`, null, null);
25
- const fetchSuccess = execCommand(`git fetch --all --prune --jobs=10`, null, null);
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('🔄', `Pull and fetch from branch ${currentBranch}.`);
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}`, null, null)) {
42
- return execCommand(`git merge origin/${devBranch}`, null, null);
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, null, null)) {
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', null, null);
65
- execCommand('git restore .gitattributes', null, null);
66
- logSuccess('📦', 'Reinstall git-lfs and clear files.');
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
- goToMainBranch();
74
- updateCurrentBranch();
75
-
76
- const currentVersion = getVersion();
77
- if (!currentVersion) {
78
- logError('❌', 'Cannot get version from package.json');
79
- return false;
80
- }
81
-
82
- const existingTag = execSilent(`git tag -l "v${currentVersion}"`);
83
-
84
- if (existingTag) {
85
- logError('❌', `Tag v${currentVersion} already created.`);
86
- return false;
87
- }
88
-
89
- if (execCommand(`git tag v${currentVersion}`, null, null)) {
90
- logSuccess('🔖', `Create tag v${currentVersion}.`);
91
-
92
- if (execCommand(`git push origin v${currentVersion}`, null, null)) {
93
- logSuccess('🚀', `Push tag v${currentVersion}.`);
94
- return true;
95
- }
96
- }
97
-
98
- return false;
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