spectrum-cli 4.0.0 → 5.0.1
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 +20 -0
- package/README.md +13 -12
- package/package.json +1 -1
- package/src/changelog/config.js +1 -1
- package/src/chart/helmrelease.js +1 -1
- package/src/chart/registry.js +9 -4
- package/src/cli/commands.js +1 -1
- package/src/preflight/chart.js +1 -1
- package/src/token/config.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -9,6 +9,26 @@ This is the changelog of the `spectrum-cli` npm package. Its version comes from
|
|
|
9
9
|
`package.json`; the release commands use Git tags and `CHANGELOG.md` in the
|
|
10
10
|
**target project** and do not update that project's `package.json`.
|
|
11
11
|
|
|
12
|
+
## 🚀 [5.0.1] - 2026-10-02
|
|
13
|
+
|
|
14
|
+
### 🛠 Changed
|
|
15
|
+
|
|
16
|
+
- Команды `spectrum chart` читают токен для Helm-registry из переменной окружения `SC_OWNER_PAT` вместо `GITLAB_PRIVATE_TOKEN`.
|
|
17
|
+
- Команда `spectrum token rotate` запрашивает и записывает в CI/CD variables `SC_BOT_PAT` вместо `GITLAB_PRIVATE_TOKEN`.
|
|
18
|
+
- `spectrum chart deploy` выводит строки изменений helmrelease-файлов с отступом.
|
|
19
|
+
|
|
20
|
+
### 🪲 Fixed
|
|
21
|
+
|
|
22
|
+
- Запрос к Helm-registry GitLab авторизуется через HTTP Basic auth; заголовок `PRIVATE-TOKEN` приводил к HTTP 401.
|
|
23
|
+
- Проверка публикации чарта находит версию в `index.yaml` GitLab, где элементы списка записаны без дополнительного отступа; `chart start` больше не ждёт бесконечно уже опубликованную версию.
|
|
24
|
+
- Версия чарта читается из заголовка changelog со ссылкой вида `## [X.Y.Z](url) - YYYY-MM-DD`.
|
|
25
|
+
|
|
26
|
+
## 🚀 [5.0.0] - 2026-10-01
|
|
27
|
+
|
|
28
|
+
### 💥 Breaking change
|
|
29
|
+
|
|
30
|
+
- Fragment `.changelog/*.removed.md` теперь повышает версию приложения до следующего major-релиза вместо patch. Такой fragment нельзя включить в hotfix; для него нужен обычный релиз.
|
|
31
|
+
|
|
12
32
|
## 🚀 [4.0.0] - 2026-10-01
|
|
13
33
|
|
|
14
34
|
### 💥 Breaking change
|
package/README.md
CHANGED
|
@@ -66,7 +66,7 @@ spectrum changelog check # Проверить CHANGELOG.md и вс
|
|
|
66
66
|
spectrum changelog write # Выравнять заголовки CHANGELOG.md и запустить Prettier
|
|
67
67
|
|
|
68
68
|
# 🔑 GitLab токены
|
|
69
|
-
spectrum token rotate # Пролить
|
|
69
|
+
spectrum token rotate # Пролить SC_BOT_PAT в CI variables
|
|
70
70
|
```
|
|
71
71
|
|
|
72
72
|
Все команды с действием показывают, какая предпроверка успешно пройдена;
|
|
@@ -163,7 +163,7 @@ spectrum-cli/
|
|
|
163
163
|
| `spectrum chart start` | Создать и запушить chart тег |
|
|
164
164
|
| `spectrum chart deploy` | Обновить chart версию в helmrelease |
|
|
165
165
|
| `spectrum chart verify` | Проверить ingress paths chart |
|
|
166
|
-
| `spectrum token rotate` | Пролить
|
|
166
|
+
| `spectrum token rotate` | Пролить SC_BOT_PAT в CI |
|
|
167
167
|
|
|
168
168
|
### 🛡️ Preflight-проверки по командам
|
|
169
169
|
|
|
@@ -172,10 +172,10 @@ spectrum-cli/
|
|
|
172
172
|
- `spectrum release close`: чистая и актуальная main/master, версия из верхнего заголовка `CHANGELOG.md` и remote stable-тег поддерживаемой формы, указывающий на текущий commit.
|
|
173
173
|
- `spectrum changelog append <message>`: `git-repo`, `changelog-exists`, валидные ID задачи, git identity и тип fragment. Команда не изменяет общий `CHANGELOG.md`.
|
|
174
174
|
- `spectrum changelog check`: `git-repo`, `changelog-exists`, `changelog-prettier-check`, наличие и формат всех changelog fragments.
|
|
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 нужен `
|
|
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 нужен `SC_OWNER_PAT`; ошибка доступа блокирует команду. `-f, --force` обходит только проверку повышения версии относительно последнего remote-тега. После push команда по умолчанию ждёт версию в registry; `-n, --no-wait` отключает ожидание.
|
|
176
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`).
|
|
177
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`.
|
|
178
|
-
- `spectrum token rotate`: `load-config` (есть валидный `~/.config/spectrum-cli/config.yaml`), `ask-tokens` (owner PAT и `
|
|
178
|
+
- `spectrum token rotate`: `load-config` (есть валидный `~/.config/spectrum-cli/config.yaml`), `ask-tokens` (owner PAT и `SC_BOT_PAT` только в памяти), `check-access` (все группы и проекты доступны owner PAT).
|
|
179
179
|
|
|
180
180
|
## 🔄 Workflow релиза
|
|
181
181
|
|
|
@@ -185,7 +185,7 @@ spectrum-cli/
|
|
|
185
185
|
|
|
186
186
|
1. Проверяет чистую актуальную dev-ветку, включающую `origin/main` или `origin/master`, changelog и fragments.
|
|
187
187
|
2. После `git fetch origin --prune --tags` находит максимальный stable-тег среди `release/X.Y.Z`, `hotfix/X.Y.Z` и `vX.Y.Z`, достижимый из production-ветки.
|
|
188
|
-
3. Если открытого релиза нет, вычисляет версию по fragments: `breaking` → major, `added` → minor, остальные → patch. Если раздел уже открыт в main/master, сохраняет его версию и дату, объединяет прежние записи с новыми по разделам без дублей. Тип новых fragments не повышает уже выбранную версию.
|
|
188
|
+
3. Если открытого релиза нет, вычисляет версию по fragments: `breaking` и `removed` → major, `added` → minor, остальные → patch. Если раздел уже открыт в main/master, сохраняет его версию и дату, объединяет прежние записи с новыми по разделам без дублей. Тип новых fragments не повышает уже выбранную версию.
|
|
189
189
|
4. Форматирует и проверяет `CHANGELOG.md`, затем удаляет использованные fragments.
|
|
190
190
|
5. Коммитит изменения и атомарно пушит dev в `origin/dev` и `origin/main` или `origin/master`, без Merge Request. Если новых записей нет, пустой коммит не создаётся; можно повторить отправку после её сбоя.
|
|
191
191
|
|
|
@@ -229,14 +229,14 @@ spectrum-cli/
|
|
|
229
229
|
или `origin/master`, либо работайте прямо в актуальной production-ветке
|
|
230
230
|
`main/master`. Включайте только срочное исправление и его patch fragments
|
|
231
231
|
(`fixed`, `security`, `support` либо другой совместимый patch-тип).
|
|
232
|
-
`added` и `
|
|
232
|
+
`added`, `breaking` и `removed` требуют обычного релиза. Все команды запускаются из корня
|
|
233
233
|
репозитория; для `start` нужен Prettier, как для обычной сборки changelog.
|
|
234
234
|
|
|
235
235
|
1. **`spectrum hotfix start`** обновляет сведения об origin и выбирает опубликованный
|
|
236
236
|
stable-тег, достижимый из production. Цель — этот stable плюс один patch.
|
|
237
237
|
Как и `release start`, команда читает все файлы текущей `.changelog/` независимо
|
|
238
238
|
от того, когда они попали в Git. Проверяет их общими правилами changelog и
|
|
239
|
-
допускает только patch-типы; файлы `added` и `
|
|
239
|
+
допускает только patch-типы; файлы `added`, `breaking` и `removed` требуют обычного релиза.
|
|
240
240
|
Формат CHANGELOG.md проверяется только в текущей ветке. История может отличаться
|
|
241
241
|
от stable-тега: её исправления не блокируют хотфикс. Снимок production используется
|
|
242
242
|
для сохранения записей уже подготовленного хотфикса, без строгой проверки старых заголовков.
|
|
@@ -324,7 +324,7 @@ CI-часть реализует подключенный release component, а
|
|
|
324
324
|
|
|
325
325
|
### `spectrum token rotate`
|
|
326
326
|
|
|
327
|
-
Пролив уже созданного PAT `
|
|
327
|
+
Пролив уже созданного PAT `SC_BOT_PAT` в CI/CD variables групп и проектов. Команда токен не выпускает.
|
|
328
328
|
|
|
329
329
|
**Конфиг:** `~/.config/spectrum-cli/config.yaml`
|
|
330
330
|
|
|
@@ -340,13 +340,13 @@ projects: []
|
|
|
340
340
|
- `bot` и `token_ttl_months` читаются только из конфига.
|
|
341
341
|
- Скрытым вводом запрашиваются два токена. Оба живут только в памяти.
|
|
342
342
|
- Owner PAT: ходит в API, проверяет доступ, читает/удаляет/создает CI variables. Для групп нужен Owner, для проектов — Maintainer+.
|
|
343
|
-
- `
|
|
344
|
-
- Для каждой группы и проекта CI variable `
|
|
343
|
+
- `SC_BOT_PAT`: только значение, которое пишется в CI variable.
|
|
344
|
+
- Для каждой группы и проекта CI variable `SC_BOT_PAT` удаляется (если есть) и создается заново как masked and hidden.
|
|
345
345
|
- Description переменной: `PAT от бота <bot>, владелец Колосов. Истекает YYYY-MM-DD.` Дата = сегодня + `token_ttl_months`.
|
|
346
346
|
|
|
347
347
|
1. Загружает или создает конфиг
|
|
348
348
|
2. Запрашивает owner PAT
|
|
349
|
-
3. Запрашивает `
|
|
349
|
+
3. Запрашивает `SC_BOT_PAT`
|
|
350
350
|
4. Проверяет доступ ко всем группам и проектам owner PAT
|
|
351
351
|
5. Обновляет CI variables во всех целях
|
|
352
352
|
|
|
@@ -381,8 +381,9 @@ projects: []
|
|
|
381
381
|
| Суффикс | Раздел | Повышение версии |
|
|
382
382
|
| --- | --- | --- |
|
|
383
383
|
| `breaking` | Breaking change | major |
|
|
384
|
+
| `removed` | Removed | major |
|
|
384
385
|
| `added` | Added | minor |
|
|
385
|
-
| `changed`, `deprecated
|
|
386
|
+
| `changed`, `deprecated` | Соответствующий раздел | patch |
|
|
386
387
|
| `fixed`, `security`, `support` | Соответствующий раздел | patch |
|
|
387
388
|
|
|
388
389
|
**📌 Пример использования:**
|
package/package.json
CHANGED
package/src/changelog/config.js
CHANGED
|
@@ -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' })
|
package/src/chart/helmrelease.js
CHANGED
|
@@ -72,7 +72,7 @@ function printDeployChanges(changes) {
|
|
|
72
72
|
const icon = item.changed ? '●' : '○';
|
|
73
73
|
const color = item.changed ? colors.green : '\x1b[90m';
|
|
74
74
|
console.log(
|
|
75
|
-
|
|
75
|
+
` ${color}${icon} ${item.filePath}: ${item.oldVersion} -> ${item.newVersion}${colors.reset}`
|
|
76
76
|
);
|
|
77
77
|
});
|
|
78
78
|
}
|
package/src/chart/registry.js
CHANGED
|
@@ -60,7 +60,8 @@ function helmIndexHasChartVersion(indexYamlContent, chartName, version) {
|
|
|
60
60
|
continue;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
const isChartSequenceItem = indent === chartIndent && trimmed.startsWith('-');
|
|
64
|
+
if (inChart && indent <= chartIndent && !isChartSequenceItem) {
|
|
64
65
|
inChart = false;
|
|
65
66
|
}
|
|
66
67
|
|
|
@@ -77,24 +78,28 @@ function helmIndexHasChartVersion(indexYamlContent, chartName, version) {
|
|
|
77
78
|
return false;
|
|
78
79
|
}
|
|
79
80
|
|
|
81
|
+
function buildBasicAuthHeader(accessToken) {
|
|
82
|
+
return `Basic ${Buffer.from(`token:${accessToken}`).toString('base64')}`;
|
|
83
|
+
}
|
|
84
|
+
|
|
80
85
|
async function fetchChartVersionFromRegistry(chartName, version) {
|
|
81
86
|
const project = getGitlabProject();
|
|
82
87
|
if (!project) {
|
|
83
88
|
return { ok: false, reason: 'Не удалось определить GitLab-проект из remote "origin".' };
|
|
84
89
|
}
|
|
85
90
|
|
|
86
|
-
const accessToken = process.env.
|
|
91
|
+
const accessToken = process.env.SC_OWNER_PAT;
|
|
87
92
|
if (!accessToken) {
|
|
88
93
|
return {
|
|
89
94
|
ok: false,
|
|
90
|
-
reason: 'Не задана переменная окружения
|
|
95
|
+
reason: 'Не задана переменная окружения SC_OWNER_PAT. Она нужна для проверки публикации чарта в Helm-registry.'
|
|
91
96
|
};
|
|
92
97
|
}
|
|
93
98
|
|
|
94
99
|
const indexUrl = `${project.origin}/api/v4/projects/${project.encodedPath}/packages/helm/${HELM_REGISTRY_CHANNEL}/index.yaml`;
|
|
95
100
|
let response;
|
|
96
101
|
try {
|
|
97
|
-
response = await fetch(indexUrl, { headers: {
|
|
102
|
+
response = await fetch(indexUrl, { headers: { Authorization: buildBasicAuthHeader(accessToken) } });
|
|
98
103
|
} catch (error) {
|
|
99
104
|
return { ok: false, reason: `Не удалось запросить Helm-registry (${indexUrl}): ${error.message}.` };
|
|
100
105
|
}
|
package/src/cli/commands.js
CHANGED
|
@@ -127,7 +127,7 @@ const tokenCmd = program
|
|
|
127
127
|
|
|
128
128
|
tokenCmd
|
|
129
129
|
.command("rotate")
|
|
130
|
-
.description("Пролить
|
|
130
|
+
.description("Пролить SC_BOT_PAT в CI variables через owner PAT")
|
|
131
131
|
.option("-d, --dry", "Запустить только предпроверки")
|
|
132
132
|
.option("-s, --silence", "Скрыть сообщения об успешно пройденных предпроверках")
|
|
133
133
|
.action((command) => runAction(token.tokenRotate, command));
|
package/src/preflight/chart.js
CHANGED
|
@@ -15,7 +15,7 @@ function requireChartChangelogVersion(chartDir) {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
const firstHeading = changelog.match(/^##(?!#)[^\r\n]*$/m)?.[0];
|
|
18
|
-
const version = firstHeading?.match(/^##\s+(?:\S+\s+)?\[([^\]]+)\](?:\s|$)/)?.[1];
|
|
18
|
+
const version = firstHeading?.match(/^##\s+(?:\S+\s+)?\[([^\]]+)\](?:\([^)\s]*\))?(?:\s|$)/)?.[1];
|
|
19
19
|
if (!version || !SEMVER_PATTERN.test(version)) {
|
|
20
20
|
return fail(`Верхний раздел "${changelogPath}" должен содержать версию SemVer в заголовке "## [X.Y.Z]".`);
|
|
21
21
|
}
|
package/src/token/config.js
CHANGED
|
@@ -4,7 +4,7 @@ const path = require('path');
|
|
|
4
4
|
const { logSuccess } = require('../common/utils');
|
|
5
5
|
const { isDryRun } = require('../cli/command-executor');
|
|
6
6
|
const { parseGitlabUrl } = require('../integrations/gitlab-url');
|
|
7
|
-
const TOKEN_NAME = '
|
|
7
|
+
const TOKEN_NAME = 'SC_BOT_PAT';
|
|
8
8
|
|
|
9
9
|
function getConfigPath() {
|
|
10
10
|
return path.join(os.homedir(), '.config', 'spectrum-cli', 'config.yaml');
|