spectrum-cli 3.2.0 → 5.0.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 +29 -1
- package/README.md +61 -30
- package/index.js +6 -174
- package/package.json +4 -4
- package/src/changelog/commands.js +44 -0
- package/src/{changelog-config.js → changelog/config.js} +1 -1
- package/src/changelog/format.js +51 -0
- package/src/changelog/fragments.js +223 -0
- package/src/{hotfix-changelog.js → changelog/hotfix.js} +2 -2
- package/src/changelog/index.js +7 -0
- package/src/{open-release.js → changelog/open-release.js} +6 -6
- package/src/changelog/release-block.js +80 -0
- package/src/chart/deploy.js +216 -0
- package/src/chart/helmrelease.js +90 -0
- package/src/chart/index.js +30 -0
- package/src/chart/metadata.js +114 -0
- package/src/chart/registry.js +139 -0
- package/src/chart/routes.js +244 -0
- package/src/chart/start.js +98 -0
- package/src/chart/verify.js +166 -0
- package/src/cli/command-executor.js +181 -0
- package/src/cli/commands.js +136 -0
- package/src/{development.js → cli/development.js} +1 -1
- package/src/cli/help.js +55 -0
- package/src/cli/run-action.js +28 -0
- package/src/{update-check.js → cli/update-check.js} +8 -2
- package/src/{git.js → git/index.js} +4 -3
- package/src/hotfix/checks.js +144 -0
- package/src/hotfix/close.js +46 -0
- package/src/hotfix/deploy.js +37 -0
- package/src/hotfix/git.js +35 -0
- package/src/hotfix/index.js +5 -0
- package/src/hotfix/start.js +57 -0
- package/src/integrations/gitlab-url.js +16 -0
- package/src/preflight/changelog.js +130 -0
- package/src/preflight/chart.js +57 -0
- package/src/preflight/git.js +133 -0
- package/src/preflight/helmrelease.js +201 -0
- package/src/preflight/index.js +10 -0
- package/src/preflight/result.js +18 -0
- package/src/preflight/source.js +95 -0
- package/src/preflight/tags.js +139 -0
- package/src/release/close.js +39 -0
- package/src/release/index.js +7 -0
- package/src/{stable-tags.js → release/stable-tags.js} +1 -1
- package/src/release/start.js +51 -0
- package/src/release/steps.js +83 -0
- package/src/release/version.js +20 -0
- package/src/token/config.js +163 -0
- package/src/token/gitlab-api.js +59 -0
- package/src/token/index.js +6 -0
- package/src/token/rotate.js +157 -0
- package/src/changelog.js +0 -418
- package/src/chart.js +0 -1071
- package/src/command-executor.js +0 -70
- package/src/hotfix.js +0 -208
- package/src/preflight.js +0 -796
- package/src/release.js +0 -207
- package/src/token.js +0 -399
- /package/src/{utils.js → common/utils.js} +0 -0
- /package/src/{version.js → common/version.js} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,13 +5,41 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
This is the changelog of the `spectrum-cli` npm package. Its version comes from
|
|
9
|
+
`package.json`; the release commands use Git tags and `CHANGELOG.md` in the
|
|
10
|
+
**target project** and do not update that project's `package.json`.
|
|
11
|
+
|
|
12
|
+
## 🚀 [5.0.0] - 2026-10-01
|
|
13
|
+
|
|
14
|
+
### 💥 Breaking change
|
|
15
|
+
|
|
16
|
+
- Fragment `.changelog/*.removed.md` теперь повышает версию приложения до следующего major-релиза вместо patch. Такой fragment нельзя включить в hotfix; для него нужен обычный релиз.
|
|
17
|
+
|
|
18
|
+
## 🚀 [4.0.0] - 2026-10-01
|
|
19
|
+
|
|
20
|
+
### 💥 Breaking change
|
|
21
|
+
|
|
22
|
+
- `spectrum chart create <version>` заменена на `spectrum chart start`: версия берётся из верхнего заголовка `charts/<chart-name>/CHANGELOG.md` и больше не передаётся аргументом.
|
|
23
|
+
- `chart start` по умолчанию ждёт публикации чарта в Helm-registry. Прежний `--wait` заменён на `-n, --no-wait` для запуска без ожидания.
|
|
24
|
+
- Исходные модули перемещены из файлов `src/*.js` в каталоги с `index.js`; прямые импорты файлов со старыми путями требуют обновления.
|
|
25
|
+
|
|
26
|
+
### 🆕 Added
|
|
27
|
+
|
|
28
|
+
- Все команды с действием поддерживают `-d, --dry` для запуска только предпроверок и `-s, --silence` для скрытия сообщений об успешно пройденных проверках. Для всех флагов доступны короткие формы.
|
|
29
|
+
- Перед созданием chart-тега проверяется, что версия из changelog ещё не существует среди локальных и удалённых Git-тегов и в Helm-registry.
|
|
30
|
+
|
|
31
|
+
### 🛠 Changed
|
|
32
|
+
|
|
33
|
+
- Предпроверки сообщают, что именно проверено, выполняются все доступные проверки и завершают команду с ошибкой, если хотя бы одна не прошла; имя запущенной команды из сообщений убрано.
|
|
34
|
+
- Код CLI и тесты распределены по тематическим модулям; документация по установке, релизам и безопасности приведена в соответствие с текущим кодом.
|
|
35
|
+
|
|
8
36
|
## 🚀 [3.2.0] - 2026-10-01
|
|
9
37
|
|
|
10
38
|
### 🆕 Added
|
|
11
39
|
|
|
12
40
|
- Добавлена команда `spectrum changelog write`: выравнивает заголовки релизов и хотфиксов и форматирует `CHANGELOG.md` через Prettier.
|
|
13
41
|
- Добавлена команда `spectrum upgrade` для глобального обновления CLI через npm.
|
|
14
|
-
- Перед выполнением команд CLI проверяет наличие новой версии в npm с таймаутом 200 мс и выводит версии и команду обновления; ошибка проверки не прерывает команду.
|
|
42
|
+
- Перед выполнением команд с действием CLI проверяет наличие новой версии в npm с таймаутом 200 мс и выводит версии и команду обновления; ошибка проверки не прерывает команду. `--help` и `--version` проверку не запускают.
|
|
15
43
|
|
|
16
44
|
### 🪲 Fixed
|
|
17
45
|
|
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ npm install
|
|
|
40
40
|
# Показать справку
|
|
41
41
|
spectrum --help
|
|
42
42
|
# Показать текущую версию CLI
|
|
43
|
-
spectrum -v
|
|
43
|
+
spectrum -v # или spectrum --version
|
|
44
44
|
|
|
45
45
|
# 🚀 Управление релизами
|
|
46
46
|
spectrum release start # Схлопнуть fragments и атомарно отправить release commit в dev и main/master
|
|
@@ -53,9 +53,9 @@ spectrum hotfix deploy # После merge MR: stable-тег на
|
|
|
53
53
|
spectrum hotfix close # После stable pipeline: main/master → dev
|
|
54
54
|
|
|
55
55
|
# 📈 Теги chart
|
|
56
|
-
spectrum chart
|
|
57
|
-
spectrum chart
|
|
58
|
-
spectrum chart
|
|
56
|
+
spectrum chart start # Создать тег по CHANGELOG.md чарта и дождаться публикации в Helm-registry
|
|
57
|
+
spectrum chart start -n # Не ждать публикации после отправки тега
|
|
58
|
+
spectrum chart start --force # Разрешить версию не выше последнего remote-тега, если ее еще нет в registry и Git
|
|
59
59
|
spectrum chart deploy # Обновить helmrelease.yaml до последнего chart-тега и запушить
|
|
60
60
|
spectrum chart deploy --instances sd,cbch # Обновить только выбранные инстансы instances/<name>
|
|
61
61
|
spectrum chart verify ~/repo # Сравнить ingress paths AS IS vs TO BE для Next.js исходников
|
|
@@ -69,6 +69,31 @@ spectrum changelog write # Выравнять заголовки C
|
|
|
69
69
|
spectrum token rotate # Пролить GITLAB_PRIVATE_TOKEN в CI variables
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
+
Все команды с действием показывают, какая предпроверка успешно пройдена;
|
|
73
|
+
при ошибке выводят её имя и причину. Независимые предпроверки продолжают
|
|
74
|
+
выполняться после ошибки; зависимые проверки без нужных данных помечаются как
|
|
75
|
+
невыполненные. Шаги команды запускаются, только если все проверки прошли.
|
|
76
|
+
`-s, --silence` скрывает сообщения об успешно пройденных предпроверках.
|
|
77
|
+
Ошибки проверок и итоговое сообщение команды остаются видны; флаг можно
|
|
78
|
+
совмещать с `-d, --dry`.
|
|
79
|
+
`-d, --dry` выполняет все предпроверки,
|
|
80
|
+
показывает их результаты и не запускает шаги записи, создания тегов,
|
|
81
|
+
публикации или деплоя. Предпроверки могут обращаться к `origin`, registry и
|
|
82
|
+
GitLab; `token rotate -d` запрашивает токены и проверяет доступ к целям, но не
|
|
83
|
+
изменяет CI variables. Если конфиг токенов отсутствует, `--dry` завершится
|
|
84
|
+
ошибкой и не создаст его. Для `upgrade -d` предпроверок нет: команда сообщает
|
|
85
|
+
об успехе, не запуская npm.
|
|
86
|
+
|
|
87
|
+
| Короткий флаг | Полный флаг | Где действует |
|
|
88
|
+
| --- | --- | --- |
|
|
89
|
+
| `-d` | `--dry` | Все команды с действием: только предпроверки |
|
|
90
|
+
| `-s` | `--silence` | Все команды с действием: скрыть успешные предпроверки |
|
|
91
|
+
| `-f` | `--force` | `chart start`: разрешить версию не больше последнего тега на `origin`; проверки Git-тега и Helm-registry обязательны |
|
|
92
|
+
| `-n` | `--no-wait` | `chart start`: не ждать появления версии в Helm-registry после push; по умолчанию команда ждёт |
|
|
93
|
+
| `-i <names>` | `--instances <names>` | `chart deploy`: выбрать инстансы через запятую |
|
|
94
|
+
| `-h` | `--help` | Справка CLI и команд |
|
|
95
|
+
| `-v` | `--version` | Версия CLI |
|
|
96
|
+
|
|
72
97
|
### Справка по командам:
|
|
73
98
|
|
|
74
99
|
```bash
|
|
@@ -103,24 +128,29 @@ spectrum token --help
|
|
|
103
128
|
|
|
104
129
|
```
|
|
105
130
|
spectrum-cli/
|
|
106
|
-
├── index.js
|
|
107
|
-
├── .changelog/
|
|
108
|
-
├── src/
|
|
109
|
-
│ ├──
|
|
110
|
-
│ ├──
|
|
111
|
-
│ ├──
|
|
112
|
-
│ ├──
|
|
113
|
-
│ ├── changelog
|
|
114
|
-
│ ├── chart
|
|
115
|
-
│ ├──
|
|
116
|
-
│ ├──
|
|
117
|
-
│
|
|
118
|
-
├──
|
|
119
|
-
├──
|
|
120
|
-
├──
|
|
121
|
-
|
|
131
|
+
├── index.js # Точка входа CLI
|
|
132
|
+
├── .changelog/ # Записи для следующего релиза
|
|
133
|
+
├── src/
|
|
134
|
+
│ ├── cli/ # Команды, справка и запуск действий
|
|
135
|
+
│ ├── common/ # Общие утилиты и версии
|
|
136
|
+
│ ├── git/ # Git операции
|
|
137
|
+
│ ├── preflight/ # Независимые предпроверки по областям
|
|
138
|
+
│ ├── changelog/ # Fragments, конфиг и релизные разделы
|
|
139
|
+
│ ├── chart/ # Метаданные, теги, registry, verify и deploy
|
|
140
|
+
│ ├── release/ # Версии и этапы обычного релиза
|
|
141
|
+
│ ├── hotfix/ # Проверки и этапы hotfix
|
|
142
|
+
│ ├── token/ # Конфиг, GitLab API и ротация
|
|
143
|
+
│ ├── integrations/ # Общие функции внешних сервисов
|
|
144
|
+
├── __tests__/ # Модульные и интеграционные тесты
|
|
145
|
+
├── package.json
|
|
146
|
+
├── install.sh
|
|
147
|
+
├── INSTALL.md
|
|
148
|
+
└── README.md
|
|
122
149
|
```
|
|
123
150
|
|
|
151
|
+
Входы модулей находятся в `index.js` соответствующих каталогов. Например,
|
|
152
|
+
`require('./src/chart')` загружает `src/chart/index.js`; в корне `src` файлов нет.
|
|
153
|
+
|
|
124
154
|
### Команды
|
|
125
155
|
|
|
126
156
|
| Команда | Описание |
|
|
@@ -130,7 +160,7 @@ spectrum-cli/
|
|
|
130
160
|
| `spectrum release close` | Закрыть релиз |
|
|
131
161
|
| `spectrum changelog append` | Создать changelog fragment |
|
|
132
162
|
| `spectrum changelog check` | Проверить changelog и fragments |
|
|
133
|
-
| `spectrum chart
|
|
163
|
+
| `spectrum chart start` | Создать и запушить chart тег |
|
|
134
164
|
| `spectrum chart deploy` | Обновить chart версию в helmrelease |
|
|
135
165
|
| `spectrum chart verify` | Проверить ingress paths chart |
|
|
136
166
|
| `spectrum token rotate` | Пролить GITLAB_PRIVATE_TOKEN в CI |
|
|
@@ -142,7 +172,7 @@ spectrum-cli/
|
|
|
142
172
|
- `spectrum release close`: чистая и актуальная main/master, версия из верхнего заголовка `CHANGELOG.md` и remote stable-тег поддерживаемой формы, указывающий на текущий commit.
|
|
143
173
|
- `spectrum changelog append <message>`: `git-repo`, `changelog-exists`, валидные ID задачи, git identity и тип fragment. Команда не изменяет общий `CHANGELOG.md`.
|
|
144
174
|
- `spectrum changelog check`: `git-repo`, `changelog-exists`, `changelog-prettier-check`, наличие и формат всех changelog fragments.
|
|
145
|
-
- `spectrum chart
|
|
175
|
+
- `spectrum chart start`: `git-repo`, `clean-working-tree`, `on-main-branch`, `single-chart` (ровно один `charts/<chart-name>/Chart.yaml`), валидный верхний SemVer-заголовок в `charts/<chart-name>/CHANGELOG.md`, отсутствие тега `chart-<name>-<version>` локально и на `origin`, отсутствие этой версии чарта в Helm-registry. Для запроса registry нужен `GITLAB_PRIVATE_TOKEN`; ошибка доступа блокирует команду. `-f, --force` обходит только проверку повышения версии относительно последнего remote-тега. После push команда по умолчанию ждёт версию в registry; `-n, --no-wait` отключает ожидание.
|
|
146
176
|
- `spectrum chart deploy`: `git-repo`, `clean-working-tree`, `on-main-branch` (текущая ветка `main`), `remote-origin` (настроен `origin`), `remote-reachable` (доступен `origin`), `single-chart`, `helmrelease-files` (найдены `helmrelease.yaml`).
|
|
147
177
|
- `spectrum chart verify <source_path>`: `git-repo`, `single-values-yaml` (ровно один `charts/**/values.yaml`), `values-ingress-sections` (есть `ingress.paths.api/pages/assets`), `source-path-directory`, `next-project`, `build-command-support`.
|
|
148
178
|
- `spectrum token rotate`: `load-config` (есть валидный `~/.config/spectrum-cli/config.yaml`), `ask-tokens` (owner PAT и `GITLAB_PRIVATE_TOKEN` только в памяти), `check-access` (все группы и проекты доступны owner PAT).
|
|
@@ -155,7 +185,7 @@ spectrum-cli/
|
|
|
155
185
|
|
|
156
186
|
1. Проверяет чистую актуальную dev-ветку, включающую `origin/main` или `origin/master`, changelog и fragments.
|
|
157
187
|
2. После `git fetch origin --prune --tags` находит максимальный stable-тег среди `release/X.Y.Z`, `hotfix/X.Y.Z` и `vX.Y.Z`, достижимый из production-ветки.
|
|
158
|
-
3. Если открытого релиза нет, вычисляет версию по fragments: `breaking` → major, `added` → minor, остальные → patch. Если раздел уже открыт в main/master, сохраняет его версию и дату, объединяет прежние записи с новыми по разделам без дублей. Тип новых fragments не повышает уже выбранную версию.
|
|
188
|
+
3. Если открытого релиза нет, вычисляет версию по fragments: `breaking` и `removed` → major, `added` → minor, остальные → patch. Если раздел уже открыт в main/master, сохраняет его версию и дату, объединяет прежние записи с новыми по разделам без дублей. Тип новых fragments не повышает уже выбранную версию.
|
|
159
189
|
4. Форматирует и проверяет `CHANGELOG.md`, затем удаляет использованные fragments.
|
|
160
190
|
5. Коммитит изменения и атомарно пушит dev в `origin/dev` и `origin/main` или `origin/master`, без Merge Request. Если новых записей нет, пустой коммит не создаётся; можно повторить отправку после её сбоя.
|
|
161
191
|
|
|
@@ -199,14 +229,14 @@ spectrum-cli/
|
|
|
199
229
|
или `origin/master`, либо работайте прямо в актуальной production-ветке
|
|
200
230
|
`main/master`. Включайте только срочное исправление и его patch fragments
|
|
201
231
|
(`fixed`, `security`, `support` либо другой совместимый patch-тип).
|
|
202
|
-
`added` и `
|
|
232
|
+
`added`, `breaking` и `removed` требуют обычного релиза. Все команды запускаются из корня
|
|
203
233
|
репозитория; для `start` нужен Prettier, как для обычной сборки changelog.
|
|
204
234
|
|
|
205
235
|
1. **`spectrum hotfix start`** обновляет сведения об origin и выбирает опубликованный
|
|
206
236
|
stable-тег, достижимый из production. Цель — этот stable плюс один patch.
|
|
207
237
|
Как и `release start`, команда читает все файлы текущей `.changelog/` независимо
|
|
208
238
|
от того, когда они попали в Git. Проверяет их общими правилами changelog и
|
|
209
|
-
допускает только patch-типы; файлы `added` и `
|
|
239
|
+
допускает только patch-типы; файлы `added`, `breaking` и `removed` требуют обычного релиза.
|
|
210
240
|
Формат CHANGELOG.md проверяется только в текущей ветке. История может отличаться
|
|
211
241
|
от stable-тега: её исправления не блокируют хотфикс. Снимок production используется
|
|
212
242
|
для сохранения записей уже подготовленного хотфикса, без строгой проверки старых заголовков.
|
|
@@ -266,14 +296,14 @@ pipeline и фактического выката выполняется отд
|
|
|
266
296
|
revision обязательных образов и копирует точные RC digest без пересборки. Эту
|
|
267
297
|
CI-часть реализует подключенный release component, а не Spectrum CLI.
|
|
268
298
|
|
|
269
|
-
### `spectrum chart
|
|
299
|
+
### `spectrum chart start`
|
|
270
300
|
|
|
271
301
|
1. Ищет `Chart.yaml` в `charts/<chart-name>/Chart.yaml` и читает поле `name`
|
|
272
302
|
2. Проверяет, что текущая ветка — `main`
|
|
273
|
-
3.
|
|
303
|
+
3. Читает версию из верхнего заголовка `charts/<chart-name>/CHANGELOG.md` и проверяет SemVer
|
|
274
304
|
4. Собирает тег `chart-<name>-<version>`
|
|
275
|
-
5. Проверяет, что такого тега еще нет
|
|
276
|
-
6. Создает тег и пушит его в `origin`
|
|
305
|
+
5. Проверяет, что такого тега еще нет локально и на `origin`, а версия отсутствует в Helm-registry
|
|
306
|
+
6. Создает тег и пушит его в `origin`, затем ждёт появления версии в registry; `-n, --no-wait` отключает ожидание
|
|
277
307
|
|
|
278
308
|
### `spectrum chart deploy`
|
|
279
309
|
|
|
@@ -351,8 +381,9 @@ projects: []
|
|
|
351
381
|
| Суффикс | Раздел | Повышение версии |
|
|
352
382
|
| --- | --- | --- |
|
|
353
383
|
| `breaking` | Breaking change | major |
|
|
384
|
+
| `removed` | Removed | major |
|
|
354
385
|
| `added` | Added | minor |
|
|
355
|
-
| `changed`, `deprecated
|
|
386
|
+
| `changed`, `deprecated` | Соответствующий раздел | patch |
|
|
356
387
|
| `fixed`, `security`, `support` | Соответствующий раздел | patch |
|
|
357
388
|
|
|
358
389
|
**📌 Пример использования:**
|
package/index.js
CHANGED
|
@@ -1,177 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
const { Command } = require(
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
const git = require("./src/git");
|
|
6
|
-
const release = require("./src/release");
|
|
7
|
-
const hotfix = require("./src/hotfix");
|
|
8
|
-
const changelog = require("./src/changelog");
|
|
9
|
-
const chart = require("./src/chart");
|
|
10
|
-
const token = require("./src/token");
|
|
11
|
-
const { checkForUpdates, upgrade } = require("./src/update-check");
|
|
12
|
-
const { version: pkgVersion } = require("./package.json");
|
|
13
|
-
|
|
14
|
-
async function runAction(action, ...args) {
|
|
15
|
-
try {
|
|
16
|
-
await checkForUpdates();
|
|
17
|
-
} catch {
|
|
18
|
-
// A failed update check must not affect the command.
|
|
19
|
-
}
|
|
20
|
-
try {
|
|
21
|
-
const result = await action(...args);
|
|
22
|
-
if (!result) {
|
|
23
|
-
process.exit(1);
|
|
24
|
-
}
|
|
25
|
-
} catch (error) {
|
|
26
|
-
console.error(`❌ Ошибка: ${error.message}`);
|
|
27
|
-
process.exit(1);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
program
|
|
32
|
-
.name("spectrum")
|
|
33
|
-
.description("🚀 Spectrum CLI для процесса разработки")
|
|
34
|
-
.version(pkgVersion, "-v, --version");
|
|
35
|
-
|
|
36
|
-
program
|
|
37
|
-
.command("upgrade")
|
|
38
|
-
.description("Обновить Spectrum CLI через npm install -g spectrum-cli")
|
|
39
|
-
.action(() => runAction(upgrade));
|
|
40
|
-
|
|
41
|
-
// Команды релиза
|
|
42
|
-
const releaseCmd = program
|
|
43
|
-
.command("release")
|
|
44
|
-
.description("Команды управления релизом");
|
|
45
|
-
|
|
46
|
-
releaseCmd
|
|
47
|
-
.command("start")
|
|
48
|
-
.description("Схлопнуть fragments и атомарно отправить release commit в dev и main/master")
|
|
49
|
-
.action(() => runAction(release.releaseStart));
|
|
50
|
-
|
|
51
|
-
releaseCmd
|
|
52
|
-
.command("close")
|
|
53
|
-
.description("Свести стабильный релиз из main/master в dev")
|
|
54
|
-
.action(() => runAction(release.releaseClose));
|
|
55
|
-
|
|
56
|
-
releaseCmd
|
|
57
|
-
.command("deploy")
|
|
58
|
-
.description("Создать и отправить только стабильный тег release/X.Y.Z")
|
|
59
|
-
.action(() => runAction(git.gitCreateTagAndPush));
|
|
60
|
-
|
|
61
|
-
const hotfixCmd = program.command("hotfix").description("Изолированный цикл срочного patch-релиза");
|
|
62
|
-
|
|
63
|
-
hotfixCmd.command("start")
|
|
64
|
-
.description("Подготовить 🩹 CHANGELOG на hotfix/* или main/master, без commit, push и merge")
|
|
65
|
-
.action(() => runAction(hotfix.hotfixStart));
|
|
66
|
-
hotfixCmd.command("deploy")
|
|
67
|
-
.description("После merge хотфикса отправить stable-тег с main/master")
|
|
68
|
-
.action(() => runAction(hotfix.hotfixDeploy));
|
|
69
|
-
hotfixCmd.command("close")
|
|
70
|
-
.description("После stable pipeline свести production в dev")
|
|
71
|
-
.action(() => runAction(hotfix.hotfixClose));
|
|
72
|
-
|
|
73
|
-
// Команды changelog
|
|
74
|
-
const changelogCmd = program
|
|
75
|
-
.command("changelog")
|
|
76
|
-
.description("Команды управления changelog fragments");
|
|
77
|
-
|
|
78
|
-
changelogCmd
|
|
79
|
-
.command("append <message>")
|
|
80
|
-
.description("Создать changelog fragment с номером задачи из ветки")
|
|
81
|
-
.action((message) => runAction(() => changelog.changelogAppend(message)));
|
|
82
|
-
|
|
83
|
-
changelogCmd
|
|
84
|
-
.command("check")
|
|
85
|
-
.description("Проверить CHANGELOG.md и changelog fragments")
|
|
86
|
-
.action(() => runAction(changelog.changelogCheck));
|
|
87
|
-
|
|
88
|
-
changelogCmd
|
|
89
|
-
.command("write")
|
|
90
|
-
.description("Привести заголовки CHANGELOG.md к формату релиза и запустить Prettier")
|
|
91
|
-
.action(() => runAction(changelog.changelogWrite));
|
|
92
|
-
|
|
93
|
-
// Команды chart
|
|
94
|
-
const chartCmd = program
|
|
95
|
-
.command("chart")
|
|
96
|
-
.description("Команды управления тегами chart");
|
|
97
|
-
|
|
98
|
-
chartCmd
|
|
99
|
-
.command("create <version>")
|
|
100
|
-
.description("Создать и отправить chart-тег (chart-<name>-<version>)")
|
|
101
|
-
.option("--force", "Разрешить версию не больше последней опубликованной")
|
|
102
|
-
.option("--wait", "Дождаться публикации версии чарта в Helm-registry")
|
|
103
|
-
.action((version, options) => runAction(() => chart.chartCreateTag(version, options)));
|
|
104
|
-
|
|
105
|
-
chartCmd
|
|
106
|
-
.command("verify <source_path>")
|
|
107
|
-
.description("Проверить пути ingress chart относительно исходников Next.js")
|
|
108
|
-
.action((sourcePath) => runAction(() => chart.chartVerify(sourcePath)));
|
|
109
|
-
|
|
110
|
-
chartCmd
|
|
111
|
-
.command("deploy")
|
|
112
|
-
.description("Задеплоить последнюю версию chart в файлы helmrelease")
|
|
113
|
-
.option("--instances <names>", "Список инстансов через запятую (по умолчанию все)")
|
|
114
|
-
.action((options) => runAction(() => chart.chartDeploy(options)));
|
|
115
|
-
|
|
116
|
-
const tokenCmd = program
|
|
117
|
-
.command("token")
|
|
118
|
-
.description("Команды управления GitLab токенами");
|
|
119
|
-
|
|
120
|
-
tokenCmd
|
|
121
|
-
.command("rotate")
|
|
122
|
-
.description("Пролить GITLAB_PRIVATE_TOKEN в CI variables через owner PAT")
|
|
123
|
-
.action(() => runAction(token.tokenRotate));
|
|
124
|
-
|
|
125
|
-
// Переопределяем help, чтобы показать кастомный формат с алиасами
|
|
126
|
-
program.configureHelp({
|
|
127
|
-
formatHelp: (cmd, helper) => {
|
|
128
|
-
const cmdUsage = helper.commandUsage(cmd);
|
|
129
|
-
const cmdDescription = helper.commandDescription(cmd);
|
|
130
|
-
const options = helper.visibleOptions(cmd);
|
|
131
|
-
const commands = helper.visibleCommands(cmd);
|
|
132
|
-
|
|
133
|
-
let output = "";
|
|
134
|
-
|
|
135
|
-
// Использование
|
|
136
|
-
if (cmdUsage) {
|
|
137
|
-
output += `Использование: ${cmdUsage}\n\n`;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Описание
|
|
141
|
-
if (cmdDescription) {
|
|
142
|
-
output += `${cmdDescription}\n\n`;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Команды с алиасами
|
|
146
|
-
if (commands.length > 0) {
|
|
147
|
-
output += "Команды:\n";
|
|
148
|
-
commands.forEach((cmd) => {
|
|
149
|
-
const nameAndArgs = cmd.name() + cmd.usage().replace(/^[^\s]+\s*/, " ");
|
|
150
|
-
const aliases = cmd.aliases();
|
|
151
|
-
const description = cmd.description();
|
|
152
|
-
|
|
153
|
-
let cmdLine = ` ${nameAndArgs}`;
|
|
154
|
-
if (aliases.length > 0) {
|
|
155
|
-
cmdLine = cmdLine.padEnd(25) + `[${aliases.join(", ")}]`;
|
|
156
|
-
}
|
|
157
|
-
cmdLine = cmdLine.padEnd(40) + description;
|
|
158
|
-
output += cmdLine + "\n";
|
|
159
|
-
});
|
|
160
|
-
output += "\n";
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Опции
|
|
164
|
-
if (options.length > 0) {
|
|
165
|
-
output += "Опции:\n";
|
|
166
|
-
options.forEach((option) => {
|
|
167
|
-
const flags = helper.optionTerm(option);
|
|
168
|
-
const description = helper.optionDescription(option);
|
|
169
|
-
output += ` ${flags.padEnd(25)} ${description}\n`;
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return output;
|
|
174
|
-
},
|
|
175
|
-
});
|
|
2
|
+
const { Command } = require('commander');
|
|
3
|
+
const { registerCommands } = require('./src/cli/commands');
|
|
4
|
+
const { configureHelp } = require('./src/cli/help');
|
|
176
5
|
|
|
6
|
+
const program = new Command();
|
|
7
|
+
registerCommands(program);
|
|
8
|
+
configureHelp(program);
|
|
177
9
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spectrum-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "🚀 Modern CLI for development workflow automation - release management, versioning, and changelog generation",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -71,9 +71,9 @@
|
|
|
71
71
|
"testEnvironment": "node",
|
|
72
72
|
"collectCoverageFrom": [
|
|
73
73
|
"index.js",
|
|
74
|
-
"src/command-executor.js",
|
|
75
|
-
"src/development.js",
|
|
76
|
-
"src/utils.js"
|
|
74
|
+
"src/cli/command-executor.js",
|
|
75
|
+
"src/cli/development.js",
|
|
76
|
+
"src/common/utils.js"
|
|
77
77
|
],
|
|
78
78
|
"testMatch": [
|
|
79
79
|
"**/__tests__/**/*.js",
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
const { runCommand } = require('../cli/command-executor');
|
|
2
|
+
const { requireGitRepo, requireFileExists, requirePrettierAvailable, requireChangelogFormatted, requireChangelogFragments } = require('../preflight');
|
|
3
|
+
const { CHANGELOG_FILE } = require('./config');
|
|
4
|
+
const { prepareChangelogEntry, appendPreparedChangelogEntry } = require('./fragments');
|
|
5
|
+
const { writeCurrentChangelog } = require('./format');
|
|
6
|
+
function changelogAppend(message) {
|
|
7
|
+
return runCommand({
|
|
8
|
+
name: 'changelog append',
|
|
9
|
+
checks: [
|
|
10
|
+
{ name: 'git-repo', run: requireGitRepo },
|
|
11
|
+
{ name: 'changelog-exists', run: () => requireFileExists(CHANGELOG_FILE) },
|
|
12
|
+
{ name: 'prepare-fragment', dependsOn: ['git-repo', 'changelog-exists'], run: () => prepareChangelogEntry(message) }
|
|
13
|
+
],
|
|
14
|
+
steps: [
|
|
15
|
+
{ name: 'write-fragment', run: appendPreparedChangelogEntry }
|
|
16
|
+
]
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function changelogCheck() {
|
|
21
|
+
return runCommand({
|
|
22
|
+
name: 'changelog check',
|
|
23
|
+
checks: [
|
|
24
|
+
{ name: 'git-repo', run: requireGitRepo },
|
|
25
|
+
{ name: 'changelog-exists', run: () => requireFileExists(CHANGELOG_FILE) },
|
|
26
|
+
{ name: 'changelog-prettier-check', run: requireChangelogFormatted },
|
|
27
|
+
{ name: 'changelog-fragments', run: requireChangelogFragments }
|
|
28
|
+
]
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function changelogWrite() {
|
|
33
|
+
return runCommand({
|
|
34
|
+
name: 'changelog write',
|
|
35
|
+
checks: [
|
|
36
|
+
{ name: 'git-repo', run: requireGitRepo },
|
|
37
|
+
{ name: 'changelog-exists', run: () => requireFileExists(CHANGELOG_FILE) },
|
|
38
|
+
{ name: 'prettier-available', run: requirePrettierAvailable }
|
|
39
|
+
],
|
|
40
|
+
steps: [{ name: 'write-changelog', run: writeCurrentChangelog }]
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = { changelogAppend, changelogCheck, changelogWrite };
|
|
@@ -8,7 +8,7 @@ const FRAGMENT_TYPES = Object.freeze({
|
|
|
8
8
|
added: Object.freeze({ section: '### 🆕 Added', bump: 'minor' }),
|
|
9
9
|
changed: Object.freeze({ section: '### 🛠 Changed', bump: 'patch' }),
|
|
10
10
|
deprecated: Object.freeze({ section: '### 📜 Deprecated', bump: 'patch' }),
|
|
11
|
-
removed: Object.freeze({ section: '### 🗑 Removed', bump: '
|
|
11
|
+
removed: Object.freeze({ section: '### 🗑 Removed', bump: 'major' }),
|
|
12
12
|
fixed: Object.freeze({ section: '### 🪲 Fixed', bump: 'patch' }),
|
|
13
13
|
security: Object.freeze({ section: '### 🔐 Security', bump: 'patch' }),
|
|
14
14
|
support: Object.freeze({ section: '### 📦 Support', bump: 'patch' })
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const { logError, execCommand } = require('../common/utils');
|
|
3
|
+
const { CHANGELOG_FILE } = require('./config');
|
|
4
|
+
function normalizeChangelogHeadings(text) {
|
|
5
|
+
const version = '(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)';
|
|
6
|
+
const date = '(\\d{4}-\\d{2}-\\d{2}|\\d{4}\\.\\d{2}\\.\\d{2}|\\d{2}\\.\\d{2}\\.\\d{4})';
|
|
7
|
+
const releaseHeading = new RegExp(`^##[ \\t]*(?:(🚀|🩹)[ \\t]*)?\\[${version}\\](?:[ \\t]+-[ \\t]+${date})?[ \\t]*\\r?$`);
|
|
8
|
+
return text.replace(/^##(?!#)[^\n]*$/gm, (heading) => {
|
|
9
|
+
const match = releaseHeading.exec(heading);
|
|
10
|
+
if (!match) throw new Error(`Некорректный заголовок ${CHANGELOG_FILE}: ${heading.trimEnd()}`);
|
|
11
|
+
const marker = match[1] ? `${match[1]} ` : '';
|
|
12
|
+
const releaseVersion = `${match[2]}.${match[3]}.${match[4]}`;
|
|
13
|
+
const releaseDate = match[5] ? ` - ${match[5]}` : '';
|
|
14
|
+
return `## ${marker}[${releaseVersion}]${releaseDate}${heading.endsWith('\r') ? '\r' : ''}`;
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function writeCurrentChangelog(context) {
|
|
19
|
+
let original;
|
|
20
|
+
let mayHaveChanged = false;
|
|
21
|
+
try {
|
|
22
|
+
original = fs.readFileSync(CHANGELOG_FILE, 'utf8');
|
|
23
|
+
const normalized = normalizeChangelogHeadings(original);
|
|
24
|
+
if (normalized !== original) {
|
|
25
|
+
mayHaveChanged = true;
|
|
26
|
+
fs.writeFileSync(CHANGELOG_FILE, normalized);
|
|
27
|
+
}
|
|
28
|
+
mayHaveChanged = true;
|
|
29
|
+
if (!execCommand(`${context.prettierRunner} --write ${CHANGELOG_FILE}`) ||
|
|
30
|
+
!execCommand(`${context.prettierRunner} --check ${CHANGELOG_FILE}`)) {
|
|
31
|
+
throw new Error('Prettier не смог отформатировать CHANGELOG.md.');
|
|
32
|
+
}
|
|
33
|
+
const formatted = fs.readFileSync(CHANGELOG_FILE, 'utf8');
|
|
34
|
+
if (normalizeChangelogHeadings(formatted) !== formatted) {
|
|
35
|
+
throw new Error('После Prettier заголовки CHANGELOG.md не соответствуют формату релизов.');
|
|
36
|
+
}
|
|
37
|
+
return true;
|
|
38
|
+
} catch (error) {
|
|
39
|
+
if (mayHaveChanged && original !== undefined) {
|
|
40
|
+
try {
|
|
41
|
+
fs.writeFileSync(CHANGELOG_FILE, original);
|
|
42
|
+
} catch (restoreError) {
|
|
43
|
+
logError('❌', 'Не удалось восстановить %s: %s', CHANGELOG_FILE, restoreError.message);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
logError('❌', 'Не удалось отформатировать %s: %s', CHANGELOG_FILE, error.message);
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
module.exports = { normalizeChangelogHeadings, writeCurrentChangelog };
|