spectrum-cli 1.0.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/CHANGELOG.md ADDED
@@ -0,0 +1,85 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### 🆕 Added
11
+
12
+ _Список новой функциональности._
13
+
14
+ ### 🛠 Changed
15
+
16
+ _Список изменившейся функциональности._
17
+
18
+ ### 📜 Deprecated
19
+
20
+ _Список устаревшей функциональности._
21
+
22
+ ### 🗑 Removed
23
+
24
+ _Список удаленной функциональности._
25
+
26
+ ### 🪲 Fixed
27
+
28
+ _Список исправлений багов._
29
+
30
+ ### 🔐 Security
31
+
32
+ _Список правок для обеспечения безопасности._
33
+
34
+ ### 📦 Support
35
+
36
+ _Список правок для обеспечения технической поддержки._
37
+
38
+ ## 🚀 [1.0.1] - 2024-09-19
39
+
40
+ ### 🆕 Added
41
+
42
+ - Создана структура проекта с каталогом `src/`
43
+ - Добавлен автоматический установщик `install.sh`
44
+ - Создан файл `INSTALL.md` с подробными инструкциями по установке
45
+ - Добавлен файл `DISTRIBUTION.md` с вариантами дистрибьюции
46
+ - Настроен `.gitignore` для Node.js проекта
47
+
48
+ ### 🛠 Changed
49
+
50
+ - Перенесены все модули в каталог `src/` для лучшей организации
51
+ - Обновлены пути импортов в `index.js`
52
+ - Улучшена документация в `README.md`
53
+
54
+ ### 📦 Support
55
+
56
+ - Добавлена поддержка различных способов установки
57
+ - Создан универсальный установщик для Unix-систем
58
+
59
+ ## 🚀 [1.0.0] - 2024-09-19
60
+
61
+ ### 🆕 Added
62
+
63
+ - Переписаны все shell-скрипты на JavaScript
64
+ - Создан CLI интерфейс `spectrum` с командой `commander`
65
+ - Добавлены основные команды:
66
+ - `spectrum release start` - полный цикл релиза
67
+ - `spectrum release close` - закрытие релиза
68
+ - `spectrum release deploy` - деплой релиза
69
+ - `spectrum up version major/minor/patch` - управление версиями
70
+ - Цветной вывод с эмодзи для лучшего UX
71
+ - Автоматическое определение пакетного менеджера (npm/yarn/bun)
72
+ - Обработка ошибок и fallback'ы
73
+ - Детальная обратная связь по операциям
74
+
75
+ ### 🗑 Removed
76
+
77
+ - Удалены все старые shell-скрипты
78
+ - Убраны ненужные npm scripts
79
+ - Удалены внутренние CLI команды модулей
80
+
81
+ ### 📦 Support
82
+
83
+ - Поддержка Node.js >= 14
84
+ - Интеграция с Git workflow
85
+ - Работа с `package.json` и `CHANGELOG.md`
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Spectrum CLI Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,171 @@
1
+ # 🚀 Spectrum CLI
2
+
3
+ Современный CLI для workflow разработки - переписанный с shell-скриптов на Node.js
4
+
5
+ ## 📦 Установка
6
+
7
+ ### 🌟 NPM (рекомендуется)
8
+
9
+ ```bash
10
+ # Установить глобально
11
+ npm install -g spectrum-cli
12
+
13
+ # Использовать
14
+ spectrum --help
15
+ ```
16
+
17
+ ### 🍺 Homebrew (macOS/Linux)
18
+
19
+ ```bash
20
+ # Добавить tap и установить
21
+ brew tap dnwsilver/spectrum-cli
22
+ brew install spectrum-cli
23
+
24
+ # Использовать
25
+ spectrum --help
26
+ ```
27
+
28
+ ### 🔧 Из исходников
29
+
30
+ ```bash
31
+ # Клонировать и установить
32
+ git clone https://github.com/dnwsilver/spectrum-cli.git
33
+ cd spectrum-cli
34
+ npm install
35
+ ./index.js --help
36
+ ```
37
+
38
+ 📋 **Подробные инструкции**: [INSTALL.md](./INSTALL.md)
39
+
40
+ ## 🚀 Использование
41
+
42
+ ### Основные команды:
43
+
44
+ ```bash
45
+ # Показать справку
46
+ spectrum --help
47
+
48
+ # 📦 Управление версиями
49
+ spectrum up version major # Поднять major версию (1.0.0 → 2.0.0)
50
+ spectrum up version minor # Поднять minor версию (1.0.0 → 1.1.0)
51
+ spectrum up version patch # Поднять patch версию (1.0.0 → 1.0.1)
52
+
53
+ # 🚀 Управление релизами
54
+ spectrum release start # Полный цикл релиза
55
+ spectrum release close # Закрыть релиз и смержить в dev
56
+ spectrum release deploy # Деплой релиза (создать тег)
57
+ ```
58
+
59
+ ### Справка по командам:
60
+
61
+ ```bash
62
+ # Справка по релизам
63
+ spectrum release --help
64
+
65
+ # Справка по версиям
66
+ spectrum up version --help
67
+ ```
68
+
69
+ ## ✨ Особенности
70
+
71
+ - 🎯 **Минималистичный интерфейс** - только необходимые команды
72
+ - 🎨 **Цветной вывод** с эмодзи для лучшего UX
73
+ - 🔄 **Автоматическое определение** пакетного менеджера (npm/yarn/bun)
74
+ - 📊 **Детальная обратная связь** по каждой операции
75
+ - 🛡️ **Обработка ошибок** и fallback'ы
76
+ - 🚀 **Полная совместимость** с Git workflow
77
+
78
+ ## 🔧 Требования
79
+
80
+ - Node.js >= 20
81
+ - Git
82
+
83
+ ## 🏗️ Архитектура
84
+
85
+ ```
86
+ spectrum-cli/
87
+ ├── index.js # 🚀 Главный CLI интерфейс
88
+ ├── src/ # 📁 Исходный код
89
+ │ ├── utils.js # 🛠️ Утилиты и логирование
90
+ │ ├── git.js # 📝 Git операции
91
+ │ ├── version.js # 📦 Управление версиями SemVer
92
+ │ ├── changelog.js # 📋 Работа с CHANGELOG.md
93
+ │ ├── development.js # ⚡ Dev команды (внутренние)
94
+ │ └── release.js # 🚀 Release процесс
95
+ ├── package.json # 📦 Конфигурация проекта
96
+ ├── install.sh # 🔧 Автоматический установщик
97
+ ├── INSTALL.md # 📋 Инструкции по установке
98
+ └── README.md # 📖 Документация
99
+ ```
100
+
101
+ ### Команды:
102
+
103
+ | Команда | Описание |
104
+ | --------------------------- | ---------------------------- |
105
+ | `spectrum up version major` | Увеличить major версию |
106
+ | `spectrum up version minor` | Увеличить minor версию |
107
+ | `spectrum up version patch` | Увеличить patch версию |
108
+ | `spectrum release start` | Запустить полный цикл релиза |
109
+ | `spectrum release close` | Закрыть релиз |
110
+ | `spectrum release deploy` | Деплой релиза |
111
+
112
+ ## 🔄 Workflow релиза
113
+
114
+ ### `spectrum release start`
115
+
116
+ 1. Переключается на dev ветку
117
+ 2. Создает release/X.Y.Z ветку
118
+ 3. Обновляет заголовок в CHANGELOG.md
119
+ 4. Удаляет пустые секции из changelog
120
+ 5. Добавляет новый блок Unreleased
121
+ 6. Коммитит изменения
122
+ 7. Пушит release ветку
123
+
124
+ ### `spectrum release close`
125
+
126
+ 1. Переключается на main ветку
127
+ 2. Обновляет main ветку
128
+ 3. Переключается на dev ветку
129
+ 4. Мержит main в dev
130
+ 5. Пушит dev ветку
131
+
132
+ ### `spectrum release deploy`
133
+
134
+ 1. Переключается на main ветку
135
+ 2. Создает тег с текущей версией
136
+ 3. Пушит тег в remote
137
+
138
+ ## 🎯 Философия
139
+
140
+ - **Простота** - минимум команд, максимум функциональности
141
+ - **Безопасность** - все операции с обработкой ошибок
142
+ - **Скорость** - быстрые операции без лишних зависимостей
143
+ - **Читаемость** - понятные логи и сообщения
144
+
145
+ ## 📚 Дополнительная документация
146
+
147
+ - 📋 **[Установка](./INSTALL.md)** - подробные инструкции по установке
148
+ - 🚀 **[Релизы](./RELEASE.md)** - инструкции по выпуску новых версий
149
+ - 📦 **[Дистрибьюция](./DISTRIBUTION.md)** - варианты распространения
150
+
151
+ ## 🤝 Участие в разработке
152
+
153
+ ```bash
154
+ # Форк репозитория
155
+ git clone https://github.com/dnwSilver/spectrum-cli.git
156
+ cd spectrum-cli
157
+
158
+ # Установка dev зависимостей
159
+ npm install
160
+
161
+ # Тестирование
162
+ ./index.js --help
163
+ ```
164
+
165
+ ## 📄 Лицензия
166
+
167
+ MIT License - см. [LICENSE](./LICENSE)
168
+
169
+ ---
170
+
171
+ _Создано для автоматизации повседневных задач разработки_ 🛠️
package/index.js ADDED
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env node
2
+ const { Command } = require('commander');
3
+ const program = new Command();
4
+
5
+ const git = require('./src/git');
6
+ const version = require('./src/version');
7
+ const release = require('./src/release');
8
+
9
+ program
10
+ .name('spectrum')
11
+ .description('🚀 Spectrum CLI for development workflow')
12
+ .version('1.0.0');
13
+
14
+ // Release commands
15
+ const releaseCmd = program
16
+ .command('release')
17
+ .description('Release management commands');
18
+
19
+ releaseCmd
20
+ .command('start')
21
+ .description('Start full release process')
22
+ .action(() => release.releaseStart());
23
+
24
+ releaseCmd
25
+ .command('close')
26
+ .description('Close release and merge to dev')
27
+ .action(() => release.releaseClose());
28
+
29
+ releaseCmd
30
+ .command('deploy')
31
+ .description('Deploy release (create and push tag)')
32
+ .action(() => git.gitCreateTagAndPush());
33
+
34
+ // Up version commands
35
+ const upCmd = program
36
+ .command('up')
37
+ .description('Version management commands');
38
+
39
+ const versionCmd = upCmd
40
+ .command('version')
41
+ .description('Update version using semantic versioning');
42
+
43
+ versionCmd
44
+ .command('major')
45
+ .description('Bump major version (x.0.0)')
46
+ .action(() => version.setVersionTypescript('major'));
47
+
48
+ versionCmd
49
+ .command('minor')
50
+ .description('Bump minor version (x.y.0)')
51
+ .action(() => version.setVersionTypescript('minor'));
52
+
53
+ versionCmd
54
+ .command('patch')
55
+ .description('Bump patch version (x.y.z)')
56
+ .action(() => version.setVersionTypescript('patch'));
57
+
58
+ // Override help to show custom format with aliases
59
+ program.configureHelp({
60
+ formatHelp: (cmd, helper) => {
61
+ const termWidth = helper.padWidth(cmd, helper);
62
+ const helpWidth = helper.helpWidth || 80;
63
+ const itemIndentWidth = 2;
64
+ const itemSeparatorWidth = 2;
65
+ const cmdUsage = helper.commandUsage(cmd);
66
+ const cmdDescription = helper.commandDescription(cmd);
67
+ const options = helper.visibleOptions(cmd);
68
+ const commands = helper.visibleCommands(cmd);
69
+
70
+ let output = '';
71
+
72
+ // Usage
73
+ if (cmdUsage) {
74
+ output += `Usage: ${cmdUsage}\n\n`;
75
+ }
76
+
77
+ // Description
78
+ if (cmdDescription) {
79
+ output += `${cmdDescription}\n\n`;
80
+ }
81
+
82
+ // Commands with aliases
83
+ if (commands.length > 0) {
84
+ output += 'Commands:\n';
85
+ commands.forEach(cmd => {
86
+ const nameAndArgs = cmd.name() + cmd.usage().replace(/^[^\s]+\s*/, ' ');
87
+ const aliases = cmd.aliases();
88
+ const description = cmd.description();
89
+
90
+ let cmdLine = ` ${nameAndArgs}`;
91
+ if (aliases.length > 0) {
92
+ cmdLine = cmdLine.padEnd(25) + `[${aliases.join(', ')}]`;
93
+ }
94
+ cmdLine = cmdLine.padEnd(40) + description;
95
+ output += cmdLine + '\n';
96
+ });
97
+ output += '\n';
98
+ }
99
+
100
+ // Options
101
+ if (options.length > 0) {
102
+ output += 'Options:\n';
103
+ options.forEach(option => {
104
+ const flags = helper.optionTerm(option);
105
+ const description = helper.optionDescription(option);
106
+ output += ` ${flags.padEnd(25)} ${description}\n`;
107
+ });
108
+ }
109
+
110
+ return output;
111
+ }
112
+ });
113
+
114
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "spectrum-cli",
3
+ "version": "1.0.3",
4
+ "description": "🚀 Modern CLI for development workflow automation - release management, versioning, and changelog generation",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "spectrum": "./index.js"
8
+ },
9
+ "scripts": {
10
+ "test": "echo \"Error: no test specified\" && exit 1",
11
+ "prepublishOnly": "echo \"Publishing spectrum-cli v$(node -p 'require(\"./package.json\").version')\"",
12
+ "postpack": "echo \"Packed successfully\""
13
+ },
14
+ "files": [
15
+ "index.js",
16
+ "src/",
17
+ "README.md",
18
+ "LICENSE",
19
+ "CHANGELOG.md"
20
+ ],
21
+ "keywords": [
22
+ "cli",
23
+ "tools",
24
+ "development",
25
+ "git",
26
+ "release",
27
+ "changelog",
28
+ "version",
29
+ "semver",
30
+ "workflow",
31
+ "automation",
32
+ "devops",
33
+ "continuous-integration"
34
+ ],
35
+ "author": {
36
+ "name": "Kolosov Aleksandr",
37
+ "email": "dnwSilver@gmail.com",
38
+ "url": "https://github.com/dnwsilver"
39
+ },
40
+ "license": "MIT",
41
+ "homepage": "https://github.com/dnwSilver/spectrum-cli#readme",
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "git+https://github.com/dnwSilver/spectrum-cli.git"
45
+ },
46
+ "bugs": {
47
+ "url": "https://github.com/dnwSilver/spectrum-cli/issues"
48
+ },
49
+ "dependencies": {
50
+ "commander": "^11.1.0"
51
+ },
52
+ "engines": {
53
+ "node": ">=20.0.0",
54
+ "npm": ">=6.0.0"
55
+ },
56
+ "os": [
57
+ "darwin",
58
+ "linux",
59
+ "win32"
60
+ ],
61
+ "preferGlobal": true,
62
+ "publishConfig": {
63
+ "access": "public"
64
+ }
65
+ }
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env node
2
+ const fs = require('fs');
3
+ const { logSuccess, execCommand, getVersion, colors } = require('./utils');
4
+
5
+ function changelogChangeHeader() {
6
+ try {
7
+ const currentVersion = getVersion();
8
+ if (!currentVersion) {
9
+ return false;
10
+ }
11
+
12
+ const changelog = fs.readFileSync('CHANGELOG.md', 'utf8');
13
+ const updatedChangelog = changelog.replace(
14
+ /## \[Unreleased\]/g,
15
+ `## 🚀 [${currentVersion}]`
16
+ );
17
+
18
+ fs.writeFileSync('CHANGELOG.md', updatedChangelog);
19
+ console.log(` ${colors.yellow} ${colors.reset} Update header ${colors.green}🚀 [${currentVersion}]${colors.reset}.`);
20
+ return true;
21
+ } catch (error) {
22
+ return false;
23
+ }
24
+ }
25
+
26
+ function changelogRemoveEmptyChapters() {
27
+ try {
28
+ const data = fs.readFileSync('CHANGELOG.md', 'utf8');
29
+ const updatedData = data.replaceAll(/###.*\n\n_.*_\n\n/gm, '');
30
+ fs.writeFileSync('CHANGELOG.md', updatedData);
31
+
32
+ console.log(` ${colors.yellow} ${colors.reset} Remove empty chapters.`);
33
+ return true;
34
+ } catch (error) {
35
+ return false;
36
+ }
37
+ }
38
+
39
+ function changelogAddUnreleasedBlock() {
40
+ try {
41
+ const currentVersion = getVersion();
42
+ if (!currentVersion) {
43
+ return false;
44
+ }
45
+
46
+ const unreleased = `## [Unreleased]
47
+
48
+ ### 🆕 Added
49
+
50
+ _Список новой функциональности._
51
+
52
+ ### 🛠 Changed
53
+
54
+ _Список изменившейся функциональности._
55
+
56
+ ### 📜 Deprecated
57
+
58
+ _Список устаревшей функциональности._
59
+
60
+ ### 🗑 Removed
61
+
62
+ _Список удаленной функциональности._
63
+
64
+ ### 🪲 Fixed
65
+
66
+ _Список исправлений багов._
67
+
68
+ ### 🔐 Security
69
+
70
+ _Список правок для обеспечения безопасности._
71
+
72
+ ### 📦 Support
73
+
74
+ _Список правок для обеспечения технической поддержки._
75
+
76
+ `;
77
+
78
+ const changelog = fs.readFileSync('CHANGELOG.md', 'utf8');
79
+ const updatedChangelog = changelog.replace(
80
+ new RegExp(`## 🚀 \\[${currentVersion}\\]`),
81
+ `${unreleased}## 🚀 [${currentVersion}]`
82
+ );
83
+
84
+ fs.writeFileSync('CHANGELOG.md', updatedChangelog);
85
+ console.log(` ${colors.yellow} ${colors.reset} Add unreleased block.`);
86
+ return true;
87
+ } catch (error) {
88
+ return false;
89
+ }
90
+ }
91
+
92
+ function changelogCommit() {
93
+ const addSuccess = execCommand('git add CHANGELOG.md', null, null);
94
+ const commitSuccess = execCommand('git commit --message "📝 Update changelog." --no-verify', null, null);
95
+
96
+ if (addSuccess && commitSuccess) {
97
+ logSuccess('󰜘', 'Commit updated changelog.');
98
+ return true;
99
+ }
100
+ return false;
101
+ }
102
+
103
+
104
+ module.exports = {
105
+ changelogChangeHeader,
106
+ changelogRemoveEmptyChapters,
107
+ changelogAddUnreleasedBlock,
108
+ changelogCommit
109
+ };
@@ -0,0 +1,113 @@
1
+ #!/usr/bin/env node
2
+ const { getPackageManager, execCommand, logError } = require('./utils');
3
+
4
+ function dev() {
5
+ const pm = getPackageManager();
6
+
7
+ switch (pm) {
8
+ case 'npm':
9
+ return execCommand('npm run dev');
10
+ case 'yarn':
11
+ return execCommand('yarn dev');
12
+ case 'bun':
13
+ logError('⚠️', 'Bun not implemented');
14
+ return false;
15
+ default:
16
+ logError('⚠️', 'No package manager found');
17
+ return false;
18
+ }
19
+ }
20
+
21
+ function test() {
22
+ const pm = getPackageManager();
23
+
24
+ switch (pm) {
25
+ case 'npm':
26
+ return execCommand('NODE_ENV=test npm run dev');
27
+ case 'yarn':
28
+ return execCommand('NODE_ENV=test yarn dev');
29
+ case 'bun':
30
+ logError('⚠️', 'Bun not implemented');
31
+ return false;
32
+ default:
33
+ logError('⚠️', 'No package manager found');
34
+ return false;
35
+ }
36
+ }
37
+
38
+ function deps() {
39
+ const pm = getPackageManager();
40
+
41
+ switch (pm) {
42
+ case 'npm':
43
+ return execCommand('npm install');
44
+ case 'yarn':
45
+ return execCommand('yarn install');
46
+ case 'bun':
47
+ logError('⚠️', 'Bun not implemented');
48
+ return false;
49
+ default:
50
+ logError('⚠️', 'No package manager found');
51
+ return false;
52
+ }
53
+ }
54
+
55
+ function build() {
56
+ const pm = getPackageManager();
57
+
58
+ switch (pm) {
59
+ case 'npm':
60
+ return execCommand('npm run build');
61
+ case 'yarn':
62
+ return execCommand('yarn build');
63
+ case 'bun':
64
+ return execCommand('bun run build');
65
+ default:
66
+ logError('⚠️', 'No package manager found');
67
+ return false;
68
+ }
69
+ }
70
+
71
+ function e2e() {
72
+ const pm = getPackageManager();
73
+
74
+ switch (pm) {
75
+ case 'npm':
76
+ return execCommand('npm run test:e2e');
77
+ case 'yarn':
78
+ return execCommand('yarn test:e2e');
79
+ case 'bun':
80
+ logError('⚠️', 'Bun not implemented');
81
+ return false;
82
+ default:
83
+ logError('⚠️', 'No package manager found');
84
+ return false;
85
+ }
86
+ }
87
+
88
+ function e2eui() {
89
+ const pm = getPackageManager();
90
+
91
+ switch (pm) {
92
+ case 'npm':
93
+ return execCommand('npm run test:end2end:ui');
94
+ case 'yarn':
95
+ return execCommand('yarn test:e2e --ui');
96
+ case 'bun':
97
+ logError('⚠️', 'Bun not implemented');
98
+ return false;
99
+ default:
100
+ logError('⚠️', 'No package manager found');
101
+ return false;
102
+ }
103
+ }
104
+
105
+
106
+ module.exports = {
107
+ dev,
108
+ test,
109
+ deps,
110
+ build,
111
+ e2e,
112
+ e2eui
113
+ };
package/src/git.js ADDED
@@ -0,0 +1,109 @@
1
+ #!/usr/bin/env node
2
+ const { logSuccess, logError, execSilent, execCommand, getCurrentBranch, getMainBranch, getDevelopBranch, getVersion } = require('./utils');
3
+
4
+ function goToMainBranch() {
5
+ const mainBranch = getMainBranch();
6
+ if (execCommand(`git switch ${mainBranch}`, null, null)) {
7
+ logSuccess('󱓏', `Swap to branch ${mainBranch}.`);
8
+ return true;
9
+ }
10
+ return false;
11
+ }
12
+
13
+ function goToDevBranch() {
14
+ const devBranch = getDevelopBranch();
15
+ if (execCommand(`git switch ${devBranch}`, null, null)) {
16
+ logSuccess('󱓏', `Swap to branch ${getCurrentBranch()}.`);
17
+ return true;
18
+ }
19
+ return false;
20
+ }
21
+
22
+ function updateCurrentBranch() {
23
+ 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);
26
+
27
+ if (pullSuccess && fetchSuccess) {
28
+ logSuccess('󱓍', `Pull and fetch from branch ${currentBranch}.`);
29
+ return true;
30
+ }
31
+ return false;
32
+ }
33
+
34
+ function gitMergeOriginDev() {
35
+ const devBranch = getDevelopBranch();
36
+ const currentBranch = getCurrentBranch();
37
+
38
+ goToDevBranch();
39
+ updateCurrentBranch();
40
+
41
+ if (execCommand(`git switch ${currentBranch}`, null, null)) {
42
+ return execCommand(`git merge origin/${devBranch}`, null, null);
43
+ }
44
+ return false;
45
+ }
46
+
47
+ function gitLfsReset() {
48
+ const commands = [
49
+ 'git lfs uninstall',
50
+ 'git reset --hard',
51
+ 'git lfs install',
52
+ 'git lfs pull'
53
+ ];
54
+
55
+ let success = true;
56
+ for (const command of commands) {
57
+ if (!execCommand(command, null, null)) {
58
+ success = false;
59
+ break;
60
+ }
61
+ }
62
+
63
+ if (success) {
64
+ execCommand('rm .gitattributes', null, null);
65
+ execCommand('git restore .gitattributes', null, null);
66
+ logSuccess('󰴋', 'Reinstall git-lfs and clear files.');
67
+ }
68
+
69
+ return success;
70
+ }
71
+
72
+ 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;
99
+ }
100
+
101
+
102
+ module.exports = {
103
+ goToMainBranch,
104
+ goToDevBranch,
105
+ updateCurrentBranch,
106
+ gitMergeOriginDev,
107
+ gitLfsReset,
108
+ gitCreateTagAndPush
109
+ };
package/src/release.js ADDED
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+ const { goToDevBranch, goToMainBranch, updateCurrentBranch } = require('./git');
3
+ const { changelogChangeHeader, changelogRemoveEmptyChapters, changelogAddUnreleasedBlock, changelogCommit } = require('./changelog');
4
+ const { getVersion, logSuccess, logError, execCommand, getCurrentBranch, getMainBranch, colors } = require('./utils');
5
+
6
+ function releaseCreate() {
7
+ goToDevBranch();
8
+ updateCurrentBranch();
9
+
10
+ const currentVersion = getVersion();
11
+ if (!currentVersion) {
12
+ logError('󰜣', 'Cannot get version from package.json');
13
+ return false;
14
+ }
15
+
16
+ if (execCommand(`git switch -c release/${currentVersion}`, null, null)) {
17
+ logSuccess('󱓊', `Create new release branch ${getCurrentBranch()}.`);
18
+ return true;
19
+ }
20
+
21
+ return false;
22
+ }
23
+
24
+ function releasePush() {
25
+ const currentBranch = getCurrentBranch();
26
+
27
+ if (execCommand(`git push origin ${currentBranch}`, null, null)) {
28
+ logSuccess('󱓎', `Push release branch ${currentBranch}.`);
29
+ console.log(` ${colors.yellow} ${colors.reset}Go to https://gitlab.spectrumdata.tech/ and merge branch manually.`);
30
+ goToMainBranch();
31
+ return true;
32
+ }
33
+
34
+ return false;
35
+ }
36
+
37
+ function releaseClose() {
38
+ const mainBranch = getMainBranch();
39
+
40
+ goToMainBranch();
41
+ updateCurrentBranch();
42
+
43
+ goToDevBranch();
44
+ updateCurrentBranch();
45
+
46
+ if (execCommand(`git merge ${mainBranch}`, null, null)) {
47
+ logSuccess('󰘬', `Merge branch ${getCurrentBranch()} with ${mainBranch}.`);
48
+
49
+ if (execCommand(`git push origin ${getCurrentBranch()} -o ci.skip`, null, null)) {
50
+ logSuccess('󱓎', `Push branch ${getCurrentBranch()}.`);
51
+ return true;
52
+ }
53
+ }
54
+
55
+ return false;
56
+ }
57
+
58
+ function releaseStart() {
59
+ const steps = [
60
+ { name: 'Create release branch', fn: releaseCreate },
61
+ { name: 'Change header', fn: changelogChangeHeader },
62
+ { name: 'Remove empty chapters', fn: changelogRemoveEmptyChapters },
63
+ { name: 'Add unreleased block', fn: changelogAddUnreleasedBlock },
64
+ { name: 'Commit changelog', fn: changelogCommit },
65
+ { name: 'Push release', fn: releasePush }
66
+ ];
67
+
68
+ for (const step of steps) {
69
+ if (!step.fn()) {
70
+ logError('✖', `Failed at step: ${step.name}`);
71
+ return false;
72
+ }
73
+ }
74
+
75
+ logSuccess('🚀', 'Release started successfully!');
76
+ return true;
77
+ }
78
+
79
+
80
+ module.exports = {
81
+ releaseCreate,
82
+ releasePush,
83
+ releaseClose,
84
+ releaseStart
85
+ };
package/src/utils.js ADDED
@@ -0,0 +1,89 @@
1
+ #!/usr/bin/env node
2
+ const { execSync, exec } = require('child_process');
3
+ const fs = require('fs');
4
+
5
+ const colors = {
6
+ red: '\x1b[91m',
7
+ green: '\x1b[32m',
8
+ yellow: '\x1b[33m',
9
+ blue: '\x1b[94m',
10
+ reset: '\x1b[0m'
11
+ };
12
+
13
+ function log(emoji, message, color = colors.green) {
14
+ console.log(` ${colors.yellow} ${emoji}${colors.reset} ${message}`);
15
+ }
16
+
17
+ function logSuccess(emoji, message) {
18
+ log(emoji, `${colors.green}${message}${colors.reset}`);
19
+ }
20
+
21
+ function logError(emoji, message) {
22
+ log(emoji, `${colors.red}${message}${colors.reset}`);
23
+ }
24
+
25
+ function execSilent(command) {
26
+ try {
27
+ return execSync(command, { stdio: 'pipe', encoding: 'utf8' }).trim();
28
+ } catch (error) {
29
+ return null;
30
+ }
31
+ }
32
+
33
+ function execCommand(command, successMessage, errorMessage) {
34
+ try {
35
+ execSync(command, { stdio: 'pipe' });
36
+ return true;
37
+ } catch (error) {
38
+ if (errorMessage) {
39
+ console.error(errorMessage);
40
+ }
41
+ return false;
42
+ }
43
+ }
44
+
45
+ function getCurrentBranch() {
46
+ return execSilent('git branch --show-current');
47
+ }
48
+
49
+ function getMainBranch() {
50
+ return execSilent('git symbolic-ref refs/remotes/origin/HEAD | sed "s@^refs/remotes/origin/@@"') || 'main';
51
+ }
52
+
53
+ function getDevelopBranch() {
54
+ const branches = execSilent('git branch -r');
55
+ if (branches && branches.includes('origin/develop')) {
56
+ return 'develop';
57
+ }
58
+ return 'dev';
59
+ }
60
+
61
+ function getPackageManager() {
62
+ if (fs.existsSync('package-lock.json')) return 'npm';
63
+ if (fs.existsSync('yarn.lock')) return 'yarn';
64
+ if (fs.existsSync('bun.lockb')) return 'bun';
65
+ return null;
66
+ }
67
+
68
+ function getVersion() {
69
+ try {
70
+ const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
71
+ return packageJson.version;
72
+ } catch (error) {
73
+ return null;
74
+ }
75
+ }
76
+
77
+ module.exports = {
78
+ colors,
79
+ log,
80
+ logSuccess,
81
+ logError,
82
+ execSilent,
83
+ execCommand,
84
+ getCurrentBranch,
85
+ getMainBranch,
86
+ getDevelopBranch,
87
+ getPackageManager,
88
+ getVersion
89
+ };
package/src/version.js ADDED
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+ const fs = require('fs');
3
+ const { execCommand, logSuccess, logError, colors } = require('./utils');
4
+
5
+ function upVersion(oldVersion, upType) {
6
+ const [major, minor, patch] = oldVersion.split('.').map(Number);
7
+
8
+ switch (upType) {
9
+ case 'major':
10
+ return `${major + 1}.0.0`;
11
+ case 'minor':
12
+ return `${major}.${minor + 1}.0`;
13
+ case 'patch':
14
+ default:
15
+ return `${major}.${minor}.${patch + 1}`;
16
+ }
17
+ }
18
+
19
+ function getVersionTypescript() {
20
+ try {
21
+ const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
22
+ return packageJson.version;
23
+ } catch (error) {
24
+ return null;
25
+ }
26
+ }
27
+
28
+ function setVersionTypescript(versionType) {
29
+ try {
30
+ const packageJson = JSON.parse(fs.readFileSync('package.json', 'utf8'));
31
+ const oldVersion = packageJson.version;
32
+ const newVersion = upVersion(oldVersion, versionType);
33
+
34
+ packageJson.version = newVersion;
35
+ fs.writeFileSync('package.json', JSON.stringify(packageJson, null, 2) + '\n');
36
+
37
+ console.log(` ${colors.yellow}󱜱${colors.reset} Current version ${oldVersion} up to ${colors.green}${newVersion}${colors.reset}.`);
38
+ return true;
39
+ } catch (error) {
40
+ logError('󰜣', 'Error updating version in package.json');
41
+ return false;
42
+ }
43
+ }
44
+
45
+
46
+ module.exports = {
47
+ upVersion,
48
+ getVersionTypescript,
49
+ setVersionTypescript
50
+ };