@nitra/cursor 1.8.167 → 1.8.168
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 +7 -0
- package/mdc/ga.mdc +6 -4
- package/package.json +2 -2
- package/scripts/lint-ga.mjs +95 -22
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
Формат — [Keep a Changelog](https://keepachangelog.com/uk/1.1.0/), нумерація — [SemVer](https://semver.org/lang/uk/).
|
|
6
6
|
|
|
7
|
+
## [1.8.168] - 2026-05-03
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `lint-ga.mjs`: до preflight на `shellcheck` додано preflight на [`uv`](https://docs.astral.sh/uv/) (постачає `uvx` для `uvx zizmor`). Якщо `uv` відсутній у `PATH` — `n-cursor lint-ga` падає з exit 1 і підказками `brew install uv` / `curl -LsSf https://astral.sh/uv/install.sh | sh` / `pip install uv`. Обидва preflight’и повідомляються незалежно: якщо нема одночасно й `shellcheck`, і `uv`, користувач одразу бачить обидві підказки, а не лише першу.
|
|
12
|
+
- `lint-ga.mjs`: винесено внутрішній `PreflightDep` із `bin`/`winBins`/`explanation`/`install`/`successMsg` — однотипний pattern для додавання нових залежностей у preflight без копіпасти.
|
|
13
|
+
|
|
7
14
|
## [1.8.167] - 2026-05-03
|
|
8
15
|
|
|
9
16
|
### Added
|
package/mdc/ga.mdc
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Правила форматів для .github/workflows
|
|
3
3
|
alwaysApply: true
|
|
4
|
-
version: '1.
|
|
4
|
+
version: '1.6'
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
У `.github/workflows/` лише **`.yml`**. Мають бути **`clean-ga-workflows.yml`**, **`clean-merged-branch.yml`**, **`lint-ga.yml`**, **`git-ai.yml`**. Якщо є **`apply-k8s.yml`** / **`apply-nats-consumer.yml`** — paths у тригері як у фрагментах.
|
|
@@ -243,9 +243,11 @@ jobs:
|
|
|
243
243
|
|
|
244
244
|
CLI виконує:
|
|
245
245
|
|
|
246
|
-
1.
|
|
247
|
-
2. `
|
|
248
|
-
3.
|
|
246
|
+
1. Preflight на [`shellcheck`](https://www.shellcheck.net/) у `PATH` — без нього `actionlint` мовчки пропускає shell-перевірки в `run:` блоках, тож локальний прогін зеленіє, а CI на `ubuntu-latest` (де shellcheck передвстановлений) падає на тих самих workflow. Встановлення: `brew install shellcheck` (macOS), `sudo apt-get install -y shellcheck` (Debian/Ubuntu), `sudo pacman -S shellcheck` (Arch).
|
|
247
|
+
2. Preflight на [`uv`](https://docs.astral.sh/uv/) у `PATH` — постачає `uvx`, без якого не запуститься `uvx zizmor`. Встановлення: `brew install uv` (macOS), `curl -LsSf https://astral.sh/uv/install.sh | sh` (universal), `pip install uv`.
|
|
248
|
+
3. Якщо хоча б один preflight не пройшов — exit 1 (підказки для всіх відсутніх залежностей друкуються разом, а не лише для першої).
|
|
249
|
+
4. `bunx github-actionlint`.
|
|
250
|
+
5. `uvx zizmor --offline --collect=workflows .`.
|
|
249
251
|
|
|
250
252
|
**`.github/zizmor.yml`:** для [unpinned-uses](https://docs.zizmor.sh/audits/#unpinned-uses) — політика **`ref-pin`**, якщо в `uses:` семантичні теги. За потреби вимкни [template-injection](https://docs.zizmor.sh/audits/#template-injection):
|
|
251
253
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nitra/cursor",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.168",
|
|
4
4
|
"description": "CLI для завантаження cursor-правил (префікс n-) у локальний репозиторій",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -49,6 +49,6 @@
|
|
|
49
49
|
"node": ">=25"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@nitra/cursor": "^1.8.
|
|
52
|
+
"@nitra/cursor": "^1.8.168"
|
|
53
53
|
}
|
|
54
54
|
}
|
package/scripts/lint-ga.mjs
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* CLI-обгортка над канонічним `lint-ga` (ga.mdc):
|
|
2
|
+
* CLI-обгортка над канонічним `lint-ga` (ga.mdc): робить preflight на `shellcheck` і `uv` (для `uvx`),
|
|
3
3
|
* тоді послідовно виконує `bunx github-actionlint` і `uvx zizmor --offline --collect=workflows .`.
|
|
4
4
|
*
|
|
5
5
|
* Без preflight `actionlint` (через `bunx github-actionlint`) мовчки пропускає shell-перевірки в
|
|
6
6
|
* `run:` блоках, коли `shellcheck` відсутній у PATH; локально `bun lint-ga` лишається зеленим, а CI
|
|
7
7
|
* на ubuntu-latest (де shellcheck передвстановлений) падає. Preflight робить цю різницю явною.
|
|
8
8
|
*
|
|
9
|
+
* `uv` потрібен для `uvx zizmor`. Якщо його нема — `uvx zizmor` падає неінформативно («command not
|
|
10
|
+
* found»); підказка з командою встановлення коротша й корисніша.
|
|
11
|
+
*
|
|
9
12
|
* Експортовано окремо `runLintGaCli` — використовується з `bin/n-cursor.js` як підкоманда `lint-ga`.
|
|
10
13
|
*/
|
|
11
14
|
import { spawnSync } from 'node:child_process'
|
|
@@ -13,28 +16,94 @@ import { platform } from 'node:process'
|
|
|
13
16
|
|
|
14
17
|
import { resolveCmd } from './utils/resolve-cmd.mjs'
|
|
15
18
|
|
|
16
|
-
/**
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
]
|
|
19
|
+
/**
|
|
20
|
+
* Опис залежності preflight-ом: бінарник, для чого потрібен, і команди встановлення.
|
|
21
|
+
*
|
|
22
|
+
* @typedef {object} PreflightDep
|
|
23
|
+
* @property {string} bin ім'я виконуваного файлу (на Windows додається `.exe` за потреби)
|
|
24
|
+
* @property {string[]} winBins альтернативні імена на Windows (`shellcheck.exe`); якщо нема — fallback на `bin`
|
|
25
|
+
* @property {string} explanation 1-2 рядки про наслідки відсутності
|
|
26
|
+
* @property {string[]} install список рядків з командами встановлення (друкуються як є, з відступом)
|
|
27
|
+
* @property {string} successMsg повідомлення на pass-шлях
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/** @type {PreflightDep} */
|
|
31
|
+
const SHELLCHECK_PREFLIGHT = {
|
|
32
|
+
bin: 'shellcheck',
|
|
33
|
+
winBins: ['shellcheck.exe'],
|
|
34
|
+
explanation: [
|
|
35
|
+
'Без нього `actionlint` пропускає shell-перевірки в run: блоках,',
|
|
36
|
+
'тож локальний прогін зеленіє, а CI на ubuntu-latest (де shellcheck',
|
|
37
|
+
'передвстановлений) падає на тих самих workflow.'
|
|
38
|
+
].join('\n '),
|
|
39
|
+
install: [
|
|
40
|
+
'macOS: brew install shellcheck',
|
|
41
|
+
'Debian/Ubuntu: sudo apt-get install -y shellcheck',
|
|
42
|
+
'Arch: sudo pacman -S shellcheck'
|
|
43
|
+
],
|
|
44
|
+
successMsg: '✅ shellcheck знайдено в PATH — actionlint виконуватиме SC-правила, як у CI'
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** @type {PreflightDep} */
|
|
48
|
+
const UV_PREFLIGHT = {
|
|
49
|
+
bin: 'uv',
|
|
50
|
+
winBins: ['uv.exe'],
|
|
51
|
+
explanation: [
|
|
52
|
+
'Без `uv` (а отже без `uvx`) не виконається `uvx zizmor` — second-stage аудит',
|
|
53
|
+
'workflow на ризики GitHub Actions просто не запуститься.'
|
|
54
|
+
].join('\n '),
|
|
55
|
+
install: [
|
|
56
|
+
'macOS: brew install uv',
|
|
57
|
+
'Universal: curl -LsSf https://astral.sh/uv/install.sh | sh',
|
|
58
|
+
'pip: pip install uv'
|
|
59
|
+
],
|
|
60
|
+
successMsg: '✅ uv знайдено в PATH — uvx zizmor запуститься'
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Шукає бінарник у PATH з урахуванням Windows: спершу `winBins`, потім `bin`.
|
|
65
|
+
* @param {PreflightDep} dep опис залежності
|
|
66
|
+
* @returns {string | null} абсолютний шлях або null
|
|
67
|
+
*/
|
|
68
|
+
function resolvePreflightBin(dep) {
|
|
69
|
+
if (platform === 'win32') {
|
|
70
|
+
for (const name of dep.winBins) {
|
|
71
|
+
const r = resolveCmd(name)
|
|
72
|
+
if (r) return r
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return resolveCmd(dep.bin)
|
|
76
|
+
}
|
|
22
77
|
|
|
23
78
|
/**
|
|
24
|
-
* Друкує блок з причиною fail і командами
|
|
79
|
+
* Друкує блок з причиною fail і командами встановлення.
|
|
80
|
+
* @param {PreflightDep} dep опис залежності
|
|
25
81
|
* @returns {void}
|
|
26
82
|
*/
|
|
27
|
-
function
|
|
28
|
-
console.error(
|
|
29
|
-
console.error(
|
|
30
|
-
console.error('
|
|
31
|
-
|
|
32
|
-
for (const line of SHELLCHECK_INSTALL_HINTS) {
|
|
83
|
+
function printPreflightMissingMessage(dep) {
|
|
84
|
+
console.error(`❌ ${dep.bin} не знайдено в PATH.`)
|
|
85
|
+
console.error(` ${dep.explanation}`)
|
|
86
|
+
console.error(' Встанови:')
|
|
87
|
+
for (const line of dep.install) {
|
|
33
88
|
console.error(` ${line}`)
|
|
34
89
|
}
|
|
35
90
|
console.error(' Деталі: ga.mdc → секція про lint-ga.')
|
|
36
91
|
}
|
|
37
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Запускає preflight-перевірку: pass → лог success і повертає true; fail → лог hint і повертає false.
|
|
95
|
+
* @param {PreflightDep} dep опис залежності
|
|
96
|
+
* @returns {boolean} чи знайдено бінарник
|
|
97
|
+
*/
|
|
98
|
+
function preflight(dep) {
|
|
99
|
+
if (resolvePreflightBin(dep)) {
|
|
100
|
+
console.log(dep.successMsg)
|
|
101
|
+
return true
|
|
102
|
+
}
|
|
103
|
+
printPreflightMissingMessage(dep)
|
|
104
|
+
return false
|
|
105
|
+
}
|
|
106
|
+
|
|
38
107
|
/**
|
|
39
108
|
* Запускає крок lint-ga з відображенням команди користувачу. Stdout/stderr дочірнього процесу
|
|
40
109
|
* передається користувачу як є (`stdio: 'inherit'`), щоб виглядало як прямий виклик у shell.
|
|
@@ -59,23 +128,27 @@ function runStep(title, cmd, args) {
|
|
|
59
128
|
}
|
|
60
129
|
|
|
61
130
|
/**
|
|
62
|
-
* Виконує канонічний `lint-ga` з preflight
|
|
131
|
+
* Виконує канонічний `lint-ga` з preflight-перевірками й послідовним запуском actionlint + zizmor.
|
|
63
132
|
*
|
|
64
133
|
* Послідовність:
|
|
65
|
-
* 1)
|
|
134
|
+
* 1) preflight: `shellcheck` (для actionlint SC-правил) і `uv` (для `uvx zizmor`); відсутній → exit 1;
|
|
66
135
|
* 2) `bunx github-actionlint`;
|
|
67
136
|
* 3) `uvx zizmor --offline --collect=workflows .`.
|
|
68
137
|
*
|
|
69
|
-
*
|
|
138
|
+
* Якщо хоча б один preflight не пройшов — виходимо одразу з кодом 1, **до** запуску actionlint/zizmor,
|
|
139
|
+
* бо їхні власні повідомлення про відсутність залежностей менш інформативні (особливо для shellcheck —
|
|
140
|
+
* actionlint мовчки пропускає SC-правила; ця перевірка — головний сенс обгортки).
|
|
141
|
+
*
|
|
142
|
+
* Першу помилку від actionlint/zizmor повертаємо як код виходу; наступні кроки не запускаються
|
|
143
|
+
* (відповідає `&&` у package.json).
|
|
70
144
|
* @returns {number} 0 — все OK, інакше — код першого кроку, що впав
|
|
71
145
|
*/
|
|
72
146
|
export function runLintGaCli() {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return 1
|
|
147
|
+
let preflightOk = true
|
|
148
|
+
for (const dep of [SHELLCHECK_PREFLIGHT, UV_PREFLIGHT]) {
|
|
149
|
+
if (!preflight(dep)) preflightOk = false
|
|
77
150
|
}
|
|
78
|
-
|
|
151
|
+
if (!preflightOk) return 1
|
|
79
152
|
|
|
80
153
|
const actionlintCode = runStep('actionlint', 'bunx', ['github-actionlint'])
|
|
81
154
|
if (actionlintCode !== 0) return actionlintCode
|