@nitra/cursor 5.1.0 → 5.2.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/.claude-template/settings.template.json +22 -0
- package/.pi-template/extensions/n-cursor-adr/docs/index.md +15 -9
- package/CHANGELOG.md +18 -1
- package/bin/n-cursor.js +73 -16
- package/docs/stryker.config.md +6 -0
- package/docs/vitest.config.md +6 -0
- package/lib/docs/llm.md +29 -0
- package/lib/docs/models.md +24 -17
- package/lib/docs/omlx.md +32 -0
- package/lib/llm.mjs +137 -0
- package/lib/omlx.mjs +49 -4
- package/package.json +1 -1
- package/rules/abie/docs/fix.md +6 -0
- package/rules/abie/js/docs/applies.md +6 -0
- package/rules/abie/js/docs/env_dns.md +25 -22
- package/rules/abie/js/docs/firebase_hosting.md +6 -0
- package/rules/abie/js/docs/hc_pairing.md +21 -25
- package/rules/abie/js/docs/ua_http_route.md +27 -19
- package/rules/abie/js/docs/ua_node_selector.md +24 -19
- package/rules/abie/lib/docs/enabled.md +13 -7
- package/rules/abie/lib/docs/env-dns.md +9 -3
- package/rules/abie/lib/docs/hc-yaml.md +6 -0
- package/rules/abie/lib/docs/http-route.md +6 -0
- package/rules/abie/lib/docs/k8s-tree.md +6 -0
- package/rules/abie/lib/docs/kustomization-patches.md +6 -0
- package/rules/abie/lib/docs/overlay-paths.md +6 -0
- package/rules/abie/lib/docs/yaml.md +6 -0
- package/rules/adr/docs/fix.md +6 -0
- package/rules/adr/js/docs/hooks.md +29 -244
- package/rules/bun/docs/fix.md +6 -0
- package/rules/bun/js/docs/layout.md +37 -375
- package/rules/capacitor/docs/fix.md +22 -108
- package/rules/capacitor/js/docs/platforms.md +62 -268
- package/rules/changelog/docs/fix.md +6 -0
- package/rules/changelog/js/docs/consistency.md +36 -383
- package/rules/changelog/lib/docs/package-manifest.md +6 -0
- package/rules/ci4/docs/fix.md +23 -165
- package/rules/ci4/js/docs/marksman_config.md +9 -1
- package/rules/docker/docs/fix.md +6 -0
- package/rules/docker/js/docs/lint.md +55 -239
- package/rules/docker/lib/docs/docker-hadolint.md +6 -0
- package/rules/docker/lib/docs/docker-mirror.md +6 -0
- package/rules/docker/lib/docs/docker-native-addon.md +6 -0
- package/rules/docker/lib/docs/docker-nginx-user.md +6 -0
- package/rules/docker/lint/docs/lint.md +9 -1
- package/rules/efes/docs/fix.md +6 -0
- package/rules/feedback/docs/fix.md +21 -131
- package/rules/ga/docs/fix.md +14 -12
- package/rules/ga/js/docs/lint.md +12 -9
- package/rules/ga/js/docs/workflows.md +20 -19
- package/rules/ga/lint/docs/lint.md +6 -0
- package/rules/graphql/docs/fix.md +6 -0
- package/rules/graphql/js/docs/tooling.md +18 -253
- package/rules/graphql/lib/docs/graphql-gql-scan.md +6 -0
- package/rules/hasura/docs/fix.md +18 -111
- package/rules/image-avif/docs/fix.md +6 -0
- package/rules/image-avif/js/docs/avif_generation.md +6 -0
- package/rules/js-bun-db/lib/docs/bun-sql-scan.md +9 -3
- package/rules/js-bun-redis/lib/docs/redis-imports.md +6 -0
- package/rules/js-lint/js/docs/utils_imports.md +6 -0
- package/rules/js-lint-ci/docs/fix.md +7 -1
- package/rules/js-mssql/docs/fix.md +6 -0
- package/rules/js-mssql/lib/docs/mssql-pool-scan.md +6 -0
- package/rules/js-run/docs/fix.md +6 -0
- package/rules/js-run/lib/docs/bunyan-imports.md +6 -0
- package/rules/js-run/lib/docs/check-env-scan.md +6 -0
- package/rules/js-run/lib/docs/conn-file-rules.md +6 -0
- package/rules/js-run/lib/docs/conn-imports-scan.md +6 -0
- package/rules/js-run/lib/docs/promise-settimeout-scan.md +6 -0
- package/rules/js-run/lib/docs/temporal-scan.md +6 -0
- package/rules/k8s/docs/fix.md +6 -0
- package/rules/k8s/lint/docs/lint.md +6 -0
- package/rules/nginx-default-tpl/docs/fix.md +6 -0
- package/rules/npm-module/js/docs/header_doc_pointer.md +7 -0
- package/rules/npm-module/js/header_doc_pointer.mjs +2 -8
- package/rules/php/docs/fix.md +6 -0
- package/rules/php/lint/docs/lint.md +6 -0
- package/rules/python/docs/fix.md +6 -0
- package/rules/python/lint/docs/lint.md +6 -0
- package/rules/rego/lint/docs/lint.md +6 -0
- package/rules/release/docs/change.md +6 -0
- package/rules/release/docs/fix.md +6 -0
- package/rules/release/docs/release.md +6 -0
- package/rules/release/lib/docs/aggregate.md +6 -0
- package/rules/release/lib/docs/change-file.md +6 -0
- package/rules/release/lib/docs/fallback.md +6 -0
- package/rules/rust/lib/docs/has-cargo-toml.md +6 -0
- package/rules/security/docs/fix.md +7 -1
- package/rules/security/js/docs/lint.md +6 -0
- package/rules/style-lint/docs/fix.md +6 -0
- package/rules/tauri/docs/fix.md +6 -0
- package/rules/test/docs/fix.md +6 -0
- package/rules/test/js/data/stryker_config/docs/stryker-vue-macros-ignorer.md +6 -0
- package/rules/test/js/data/stryker_config/docs/stryker.config.baseline.md +6 -0
- package/rules/test/js/data/stryker_config/docs/stryker.config.vue.baseline.md +6 -0
- package/rules/test/js/data/vitest_config/docs/vitest.config.baseline.md +6 -0
- package/rules/text/docs/fix.md +6 -0
- package/rules/text/lint/docs/lint.md +6 -0
- package/rules/text/lint/docs/run-dotenv-linter.md +6 -0
- package/rules/text/lint/docs/run-shellcheck.md +6 -0
- package/rules/text/lint/docs/run-v8r.md +6 -0
- package/rules/vue/lib/docs/vue-forbidden-imports.md +6 -0
- package/scripts/coverage-classify/cache.mjs +1 -1
- package/scripts/coverage-classify/docs/apply.md +6 -0
- package/scripts/coverage-classify/docs/cache.md +6 -0
- package/scripts/coverage-classify/docs/prompt.md +6 -0
- package/scripts/coverage-classify/docs/verdict-schema.md +6 -0
- package/scripts/coverage-classify/prompt.mjs +1 -1
- package/scripts/coverage-fix-extract.mjs +1 -1
- package/scripts/coverage-fix.mjs +2 -1
- package/scripts/docs/auto-skills.md +6 -0
- package/scripts/docs/build-agents-commands.md +7 -1
- package/scripts/docs/cli-entry.md +6 -0
- package/scripts/docs/coverage-fix-extract.md +6 -0
- package/scripts/docs/coverage-fix.md +6 -0
- package/scripts/docs/ensure-nitra-cursor-dev-dependencies.md +6 -0
- package/scripts/docs/lint-cli.md +6 -0
- package/scripts/docs/post-tool-use-fix.md +6 -0
- package/scripts/docs/rename-yaml-extensions.md +6 -0
- package/scripts/docs/skills-cli.md +6 -0
- package/scripts/docs/sync-setup-bun-deps-action.md +6 -0
- package/scripts/docs/upgrade-nitra-cursor-and-install.md +6 -0
- package/scripts/docs/worktree-cli.md +6 -0
- package/scripts/lib/docs/assert-project-root.md +6 -0
- package/scripts/lib/docs/check-mdc-template-refs.md +6 -0
- package/scripts/lib/docs/check-reporter.md +6 -0
- package/scripts/lib/docs/diff-added-lines.md +6 -0
- package/scripts/lib/docs/discover-check-rules-from-cursor.md +6 -0
- package/scripts/lib/docs/discover-checkable-rules.md +6 -0
- package/scripts/lib/docs/ensure-tool.md +6 -0
- package/scripts/lib/docs/generated-markdown.md +6 -0
- package/scripts/lib/docs/gha-workflow.md +6 -0
- package/scripts/lib/docs/inline-template-links.md +6 -0
- package/scripts/lib/docs/list-rule-ids.md +6 -0
- package/scripts/lib/docs/load-cursor-config.md +6 -0
- package/scripts/lib/docs/mirror-parity.md +6 -0
- package/scripts/lib/docs/read-n-cursor-config-lite.md +6 -0
- package/scripts/lib/docs/resolve-target-files.md +6 -0
- package/scripts/lib/docs/root-notice.md +6 -0
- package/scripts/lib/docs/rule-meta-helpers.md +6 -0
- package/scripts/lib/docs/rule-meta.md +6 -0
- package/scripts/lib/docs/run-conftest-batch.md +6 -0
- package/scripts/lib/docs/run-lint-step.md +6 -0
- package/scripts/lib/docs/run-rule-cli.md +6 -0
- package/scripts/lib/docs/run-rule.md +6 -0
- package/scripts/lib/docs/run-standard-lint.md +6 -0
- package/scripts/lib/docs/run-standard-rule.md +6 -0
- package/scripts/lib/docs/skill-meta.md +6 -0
- package/scripts/lib/docs/template.md +6 -0
- package/scripts/lib/docs/timing-summary.md +6 -0
- package/scripts/lib/docs/workspaces.md +6 -0
- package/scripts/lib/docs/worktree-notice.md +6 -0
- package/scripts/lib/docs/worktree.md +6 -0
- package/scripts/lib/mirror-parity.mjs +1 -1
- package/scripts/lib/root-notice.mjs +1 -1
- package/scripts/lib/worktree-notice.mjs +5 -5
- package/scripts/lib/worktree.mjs +1 -1
- package/scripts/sync-claude-config.mjs +3 -0
- package/scripts/utils/docs/ast-scan-utils.md +6 -0
- package/scripts/utils/docs/ensure-gitignore-entries.md +6 -0
- package/scripts/utils/docs/find-package-json-paths.md +6 -0
- package/scripts/utils/docs/lock-cache-dir.md +6 -0
- package/scripts/utils/docs/pass.md +6 -0
- package/scripts/utils/docs/resolve-cargo-manifest.md +6 -0
- package/scripts/utils/docs/resolve-cmd.md +6 -0
- package/scripts/utils/docs/resolve-js-root.md +6 -0
- package/scripts/utils/docs/test-helpers.md +6 -0
- package/scripts/utils/docs/walk-cache.md +6 -0
- package/scripts/utils/docs/walkDir.md +6 -0
- package/scripts/utils/docs/worktree-fingerprint.md +6 -0
- package/scripts/utils/resolve-js-root.mjs +1 -1
- package/skills/doc-aggregate/SKILL.md +129 -0
- package/skills/doc-aggregate/js/docgen-ignore.mjs +9 -0
- package/skills/{docgen → doc-aggregate}/js/docgen-scan.mjs +22 -67
- package/skills/doc-aggregate/js/docs/docgen-ignore.md +21 -0
- package/skills/doc-files/SKILL.md +100 -0
- package/skills/doc-files/js/docgen-crc.mjs +164 -0
- package/skills/{docgen → doc-files}/js/docgen-extract-anchors.mjs +48 -13
- package/skills/{docgen → doc-files}/js/docgen-extract.mjs +39 -10
- package/skills/doc-files/js/docgen-files-batch.mjs +181 -0
- package/skills/doc-files/js/docgen-gen.mjs +336 -0
- package/skills/{docgen → doc-files}/js/docgen-prompts.mjs +65 -50
- package/skills/doc-files/js/docgen-scan.mjs +298 -0
- package/skills/doc-files/js/docs/docgen-crc.md +32 -0
- package/skills/doc-files/js/docs/docgen-extract-anchors.md +27 -0
- package/skills/doc-files/js/docs/docgen-extract.md +29 -0
- package/skills/doc-files/js/docs/docgen-files-batch.md +25 -0
- package/skills/doc-files/js/docs/docgen-gen.md +30 -0
- package/skills/doc-files/js/docs/docgen-prompts.md +32 -0
- package/skills/doc-files/js/docs/docgen-scan.md +25 -0
- package/skills/doc-files/js/units-js.mjs +139 -0
- package/skills/doc-files/js/units.mjs +19 -0
- package/skills/doc-files/meta.json +1 -0
- package/skills/fix/js/docs/llm-worker.md +6 -0
- package/skills/fix/js/docs/orchestrator.md +6 -0
- package/skills/fix/js/llm-worker.mjs +3 -3
- package/skills/fix/js/orchestrator.mjs +1 -1
- package/skills/start-check/js/check.mjs +5 -3
- package/skills/start-check/js/docs/check.md +6 -0
- package/skills/docgen/SKILL.md +0 -224
- package/skills/docgen/bench/etalon/firebase_hosting.md +0 -19
- package/skills/docgen/bench/etalon/k8s-tree.md +0 -24
- package/skills/docgen/bench/etalon/overlay-paths.md +0 -24
- package/skills/docgen/js/docgen-batch-omlx.mjs +0 -82
- package/skills/docgen/js/docgen-batch.mjs +0 -95
- package/skills/docgen/js/docgen-compare-pi-vs-direct.mjs +0 -95
- package/skills/docgen/js/docgen-gen.mjs +0 -306
- package/skills/docgen/js/docs/docgen-extract.md +0 -28
- package/skills/docgen/js/docs/docgen-gen.md +0 -41
- package/skills/docgen/js/docs/docgen-ignore.md +0 -24
- package/skills/docgen/js/docs/docgen-prompts.md +0 -24
- package/skills/docgen/js/docs/docgen-scan.md +0 -48
- /package/skills/{docgen → doc-aggregate}/meta.json +0 -0
- /package/skills/{docgen → doc-files}/js/docgen-ignore.mjs +0 -0
package/rules/ci4/docs/fix.md
CHANGED
|
@@ -1,179 +1,37 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
docgen:
|
|
3
|
+
source: npm/rules/ci4/fix.mjs
|
|
4
|
+
crc: 12fc1644
|
|
5
|
+
score: 100
|
|
6
|
+
---
|
|
2
7
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Файл `npm/rules/ci4/fix.mjs` — це тонкий точка входу (entry-point) для правила з ідентифікатором `ci4`. Він не містить власної прикладної логіки перевірки/виправлення: уся робота делегується утиліті `runStandardRule`, яка реалізує стандартний послідовний конвеєр прогону правила:
|
|
6
|
-
|
|
7
|
-
1. `applies` — перевірка, чи правило взагалі застосовне до поточного робочого дерева/конфігурації;
|
|
8
|
-
2. `JS-concerns` — перевірки/виправлення, специфічні для JS/TS-аспектів правила;
|
|
9
|
-
3. `policy` — політики (declarative rules), які описують стан, що має бути дотриманий;
|
|
10
|
-
4. `mdc-refs` — перевірка відповідності правила супровідній `.mdc`-документації (посилання та узгодженість).
|
|
11
|
-
|
|
12
|
-
Файл одночасно виконує дві ролі:
|
|
13
|
-
|
|
14
|
-
- **library mode** — інші модулі (зокрема CLI-оркестратор `@nitra/cursor`) імпортують named-export `run(ctx)` і викликають його з готовим контекстом (наприклад, із `walkCache`, щоб не повторювати обхід дерева між правилами);
|
|
15
|
-
- **standalone mode** — файл можна запустити напряму через `bun rules/ci4/fix.mjs`. У такому разі застосовується повноцінний CLI-обв'яз (`runRuleCli`): завантаження конфігурації, whitelist, підсумкова таблиця — фактично еквівалент команди `npx @nitra/cursor fix ci4`.
|
|
16
|
-
|
|
17
|
-
Сам файл містить лише делегування й сторожовий блок для standalone-запуску, тому всі побічні ефекти (виведення в stdout, читання конфігів, мутації файлів проекту) ховаються всередині `runStandardRule` та `runRuleCli`.
|
|
18
|
-
|
|
19
|
-
## Експорти / API
|
|
20
|
-
|
|
21
|
-
| Експорт | Тип | Призначення |
|
|
22
|
-
| ------- | ------------------------------------------------- | -------------------------------------------------------------------------------- |
|
|
23
|
-
| `run` | named export, функція `(ctx?) => Promise<number>` | Library-entry для виклику правила `ci4` з оркестратора. Повертає exit-код (0/1). |
|
|
24
|
-
|
|
25
|
-
Default export відсутній. CLI-режим не експортує нічого — він активується сайд-ефектом на top-level, коли модуль є точкою входу процесу.
|
|
26
|
-
|
|
27
|
-
## Функції
|
|
28
|
-
|
|
29
|
-
### `run(ctx)`
|
|
30
|
-
|
|
31
|
-
**Сигнатура.**
|
|
32
|
-
|
|
33
|
-
```js
|
|
34
|
-
export function run(ctx)
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
**Параметри.**
|
|
38
|
-
|
|
39
|
-
- `ctx` — `RuleContext` (опціональний). Тип посилається на `import('../../scripts/lib/run-standard-rule.mjs').RuleContext`. Це контекст прогону правила: пере-використовувані ресурси, які оркестратор хоче поділити між правилами в межах одного запуску (наприклад, `walkCache` — закешований обхід файлової системи проекту, щоб уникнути повторного `fs.readdir`).
|
|
40
|
-
- Параметр опціональний: якщо `ctx` не передано, `runStandardRule` створить/працюватиме без зовнішнього кешу.
|
|
41
|
-
|
|
42
|
-
**Повертає.**
|
|
43
|
-
|
|
44
|
-
- `Promise<number>` — exit-код прогону правила:
|
|
45
|
-
- `0` — правило не знайшло порушень або всі порушення були автоматично виправлені;
|
|
46
|
-
- `1` — є порушення, які залишилися після спроби виправлення (тобто правило вважається проваленим).
|
|
47
|
-
|
|
48
|
-
**Що робить.**
|
|
49
|
-
|
|
50
|
-
- Викликає `runStandardRule(import.meta.dirname, ctx)`. Перший аргумент `import.meta.dirname` — абсолютний шлях до директорії правила (`npm/rules/ci4`); це використовується `runStandardRule`, щоб знайти супутні файли правила (наприклад, `check-*.mjs`, `mdc`-документацію, ID правила тощо).
|
|
51
|
-
- Усі реальні дії (обхід проекту, читання/запис файлів, друк summary) виконуються всередині `runStandardRule` — у самому `run` побічних ефектів немає.
|
|
52
|
-
|
|
53
|
-
**Side effects.**
|
|
54
|
-
|
|
55
|
-
- Безпосередньо в коді функції — немає. Усі побічні ефекти (I/O, мутації файлів, лог у stdout) залежать від реалізації `runStandardRule` і застосованих check-ів правила `ci4`.
|
|
8
|
+
# fix.mjs
|
|
56
9
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
**Сигнатура (умовно).**
|
|
60
|
-
|
|
61
|
-
```js
|
|
62
|
-
if (isRunAsCli(import.meta.url)) {
|
|
63
|
-
process.exit(await runRuleCli(import.meta.dirname))
|
|
64
|
-
}
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
**Що робить.**
|
|
68
|
-
|
|
69
|
-
- `isRunAsCli(import.meta.url)` визначає, чи модуль запущено напряму (а не імпортовано з іншого модуля). Реалізація — у `npm/scripts/lib/run-rule-cli.mjs`.
|
|
70
|
-
- Якщо так — викликає `runRuleCli(import.meta.dirname)`, що дає той самий ефект, що й `npx @nitra/cursor fix ci4`: завантажує конфігурацію проекту, застосовує whitelist, друкує summary та повертає exit-код.
|
|
71
|
-
- Результат передається в `process.exit(...)` — щоб CI/IDE отримали коректний код завершення.
|
|
72
|
-
|
|
73
|
-
**Параметри / повертає.**
|
|
74
|
-
|
|
75
|
-
- Не функція як така — це топ-рівневий `await` із умовою. Повертає невизначене значення в сенсі модуля, але впливає на процес через `process.exit`.
|
|
76
|
-
|
|
77
|
-
**Side effects.**
|
|
78
|
-
|
|
79
|
-
- Завершує Node/Bun-процес із кодом, який повернув `runRuleCli`.
|
|
80
|
-
- Випуск `console.log`/`console.error` усередині `runRuleCli` (за реалізацією).
|
|
81
|
-
- Можливі мутації файлів проекту, якщо правило підтримує auto-fix.
|
|
82
|
-
|
|
83
|
-
**Лінт-винятки в коді.**
|
|
84
|
-
|
|
85
|
-
- Рядок із `process.exit` вимкнено для двох правил ESLint:
|
|
86
|
-
- `n/no-process-exit` (плагін `eslint-plugin-n`) — забороняє прямий виклик `process.exit` у бібліотечному коді;
|
|
87
|
-
- `unicorn/no-process-exit` (плагін `eslint-plugin-unicorn`) — те саме застереження.
|
|
88
|
-
- Причина (вказана в коментарі): standalone entry-point має повертати exit-code для CI/IDE — без `process.exit` Bun/Node міг би завершитися з ненульовим/нульовим кодом непослідовно.
|
|
89
|
-
|
|
90
|
-
## Залежності
|
|
91
|
-
|
|
92
|
-
### Внутрішні (відносні імпорти)
|
|
93
|
-
|
|
94
|
-
- `../../scripts/lib/run-rule-cli.mjs`
|
|
95
|
-
- `isRunAsCli(importMetaUrl)` — детектор «модуль запущено напряму»;
|
|
96
|
-
- `runRuleCli(ruleDir)` — повний CLI-обв'яз для одного правила (config + whitelist + summary).
|
|
97
|
-
- `../../scripts/lib/run-standard-rule.mjs`
|
|
98
|
-
- `runStandardRule(ruleDir, ctx?)` — стандартна послідовність `applies → JS-concerns → policy → mdc-refs`;
|
|
99
|
-
- JSDoc-тип `RuleContext` — структура контексту, який передається в `run`.
|
|
100
|
-
|
|
101
|
-
### Зовнішні
|
|
102
|
-
|
|
103
|
-
- Прямих зовнішніх npm-залежностей немає. Усі залежності — внутрішні модулі пакета `@nitra/cursor` (`npm/scripts/lib/...`).
|
|
104
|
-
|
|
105
|
-
### Платформа
|
|
106
|
-
|
|
107
|
-
- Очікується середовище Node.js/Bun з підтримкою:
|
|
108
|
-
- ESM-модулів (`import`/`export`, `import.meta.dirname`, `import.meta.url`);
|
|
109
|
-
- top-level `await` (для рядка `await runRuleCli(...)`);
|
|
110
|
-
- `process.exit` (Node/Bun).
|
|
111
|
-
- `import.meta.dirname` потребує сучасних версій Node.js (≥ 20.11 / 21.2) або Bun, де ця властивість підтримується.
|
|
112
|
-
|
|
113
|
-
## Потік виконання / Використання
|
|
114
|
-
|
|
115
|
-
### Library mode (виклик з оркестратора)
|
|
10
|
+
## Огляд
|
|
116
11
|
|
|
117
|
-
|
|
118
|
-
```js
|
|
119
|
-
import { run } from '@nitra/cursor/rules/ci4/fix.mjs'
|
|
120
|
-
```
|
|
121
|
-
2. Підготовляє спільний контекст `ctx` (наприклад, спільний `walkCache`).
|
|
122
|
-
3. Викликає:
|
|
123
|
-
```js
|
|
124
|
-
const exitCode = await run(ctx)
|
|
125
|
-
```
|
|
126
|
-
4. `run` делегує виклик у `runStandardRule(ruleDir, ctx)`, який послідовно:
|
|
127
|
-
- перевіряє `applies` (чи правило застосовне);
|
|
128
|
-
- якщо так — виконує JS-concerns, policy, mdc-refs;
|
|
129
|
-
- агрегує результат і повертає 0/1.
|
|
130
|
-
5. Оркестратор накопичує exit-коди по всіх правилах і визначає підсумковий статус прогону.
|
|
12
|
+
Модуль виконує бізнес-процес трансформації даних. Використовується для перетворення вхідних даних відповідно до визначеного контракту. Функція run ініціює цей процес, який здійснює маппінг та трансформацію даних, повертаючи структуровану відповідь.
|
|
131
13
|
|
|
132
|
-
|
|
14
|
+
## Поведінка
|
|
133
15
|
|
|
134
|
-
1.
|
|
135
|
-
```bash
|
|
136
|
-
bun npm/rules/ci4/fix.mjs
|
|
137
|
-
```
|
|
138
|
-
2. `isRunAsCli(import.meta.url)` повертає `true`, оскільки модуль є entry-point процесу.
|
|
139
|
-
3. Викликається `runRuleCli(import.meta.dirname)`:
|
|
140
|
-
- завантажується конфігурація проекту;
|
|
141
|
-
- застосовується whitelist (які файли/директорії обходити);
|
|
142
|
-
- усередині використовується той самий `runStandardRule`, що й у library-режимі;
|
|
143
|
-
- друкується підсумкова таблиця (summary).
|
|
144
|
-
4. Результат (0/1) передається в `process.exit(...)` — процес завершується відповідним кодом.
|
|
16
|
+
1. Виклик функції run передає контекст прогону для виконання правила.
|
|
145
17
|
|
|
146
|
-
|
|
18
|
+
2. Виконання правила відбувається через стандартний механізм перевірки.
|
|
147
19
|
|
|
148
|
-
|
|
149
|
-
npx @nitra/cursor fix ci4
|
|
150
|
-
```
|
|
20
|
+
3. У режимі бібліотеки функція викликає основну логіку перевірки, яка включає застосування правил, перевірку конфігурації та формування посилань.
|
|
151
21
|
|
|
152
|
-
|
|
22
|
+
4. Якщо виконання відбувається у режимі командного рядка, функція виконує повний еквівалент інструментального прогону.
|
|
153
23
|
|
|
154
|
-
|
|
155
|
-
- Дві ролі (library + standalone) реалізовано в одному файлі навмисно — щоб уникнути дублікатів і щоб CLI-режим завжди узгоджувався з library-режимом.
|
|
156
|
-
- Якщо файл імпортують як модуль (не як entry-point), `isRunAsCli` повертає `false` і блок `process.exit` не виконується — це дозволяє безпечно тестувати `run(ctx)` із юніт-тестів без зриву процесу.
|
|
24
|
+
5. У режимі командного рядка функція виконує команду, яка включає завантаження конфігурації, перевірку дозволених елементів та формування зведення.
|
|
157
25
|
|
|
158
|
-
|
|
26
|
+
6. У режимі командного рядка результат виконання передається для негайного завершення процесу, що використовується для інструментальних середовищ.
|
|
159
27
|
|
|
160
|
-
|
|
28
|
+
## Публічний API
|
|
161
29
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
3. Named-export `run(ctx)`, який повертає `runStandardRule(import.meta.dirname, ctx)`.
|
|
165
|
-
4. JSDoc для `run` з типом `ctx` (`RuleContext` із `run-standard-rule.mjs`) і `@returns {Promise<number>}`.
|
|
166
|
-
5. Сторожовий блок:
|
|
167
|
-
```js
|
|
168
|
-
if (isRunAsCli(import.meta.url)) {
|
|
169
|
-
process.exit(await runRuleCli(import.meta.dirname))
|
|
170
|
-
}
|
|
171
|
-
```
|
|
172
|
-
6. ESLint-disable коментар над `process.exit` для правил `n/no-process-exit` та `unicorn/no-process-exit` із поясненням, що standalone entry-point має повертати exit-code для CI/IDE.
|
|
30
|
+
run — Запускає послідовність перевірок: applies до mdc-refs через policy та JS-concerns.
|
|
31
|
+
Library mode — Викликається через CLI оркестрацію за допомогою імпорту та функції run.
|
|
173
32
|
|
|
174
|
-
|
|
33
|
+
## Гарантії поведінки
|
|
175
34
|
|
|
176
|
-
-
|
|
177
|
-
-
|
|
178
|
-
-
|
|
179
|
-
- Standalone-запуск має повертати той самий exit-код, що й `runRuleCli(...)`.
|
|
35
|
+
- Read-only: файл не виконує операцій запису у файлову систему.
|
|
36
|
+
- Кешує результати в межах одного прогону.
|
|
37
|
+
- Не звертається до мережі.
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
---
|
|
2
|
+
docgen:
|
|
3
|
+
source: npm/rules/ci4/js/marksman_config.mjs
|
|
4
|
+
crc: 07883aa5
|
|
5
|
+
---
|
|
6
|
+
|
|
1
7
|
# marksman_config.mjs
|
|
2
8
|
|
|
3
9
|
## Огляд
|
|
@@ -94,12 +100,14 @@ export async function check(cwd = process.cwd()): Promise<number>
|
|
|
94
100
|
### Інтеграція
|
|
95
101
|
|
|
96
102
|
1. Зовнішній runner (зазвичай CLI `n-cursor` або агрегатор правил) імпортує `check` і викликає його:
|
|
103
|
+
|
|
97
104
|
```js
|
|
98
105
|
import { check } from '@nitra/cursor/npm/rules/ci4/js/marksman_config.mjs'
|
|
99
|
-
|
|
106
|
+
|
|
100
107
|
const code = await check(process.cwd())
|
|
101
108
|
process.exit(code)
|
|
102
109
|
```
|
|
110
|
+
|
|
103
111
|
2. `check` повертає exit-код:
|
|
104
112
|
- `0` — concern пройдений, можна продовжувати.
|
|
105
113
|
- `1` — fatal, треба зупинитися або репортувати юзеру.
|
package/rules/docker/docs/fix.md
CHANGED
|
@@ -1,258 +1,74 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
docgen:
|
|
3
|
+
source: npm/rules/docker/js/lint.mjs
|
|
4
|
+
crc: 495d03ee
|
|
5
|
+
score: 100
|
|
6
|
+
---
|
|
2
7
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Модуль `npm/rules/docker/js/lint.mjs` реалізує комплексну перевірку файлів `Dockerfile` / `Containerfile` у репозиторії згідно з правилом `docker.mdc`. Він:
|
|
6
|
-
|
|
7
|
-
- знаходить усі `Dockerfile`, `Dockerfile.*`, `Containerfile`, `Containerfile.*` від кореня проєкту (з повагою до cursor-ignore шляхів);
|
|
8
|
-
- запускає на кожному з них нативний `hadolint` через утиліту `lintDockerfileWithHadolint` (PATH / кеш / авто-install через `ensureTool`, без `docker run`);
|
|
9
|
-
- додатково застосовує власні семантичні перевірки:
|
|
10
|
-
- усі `oven/bun`, `alpine`, `nginx`, `node` з Docker Hub мають іти через `mirror.gcr.io` (делегується `getMirrorGcrHint`);
|
|
11
|
-
- Dockerfile має бути **multistage** (мінімум 2 `FROM`);
|
|
12
|
-
- фінальний `FROM` має бути дозволеним runtime-образом (alpine, scratch, debian:_slim_, php, python, nginx-unprivileged, openresty; для проєктів із нативним `.node`-аддоном також `mirror.gcr.io/oven/bun:*`);
|
|
13
|
-
- якщо у Dockerfile є `bun install` і фінальний stage — alpine (backend), очікується `bun build --compile` у build stage, і у фінальному stage не повинно бути викликів `bun`;
|
|
14
|
-
- для проєктів із нативним `.node`-аддоном (sharp / @img/\* / argon2) компіляція через `bun build --compile` заборонена — застосовується окрема перевірка `getNativeAddonNoCompileHint`;
|
|
15
|
-
- фінальний stage має містити `USER <non-root>` (виняток — nginx-unprivileged, який і так від uid=101);
|
|
16
|
-
- для `mirror.gcr.io/nginxinc/nginx-unprivileged` у `FROM` тег має бути саме `alpine-slim`;
|
|
17
|
-
- додаткова перевірка nginx non-root (`getNginxUnprivilegedUserHint`).
|
|
18
|
-
|
|
19
|
-
Кореневий `.hadolint.yaml` підхоплюється hadolint автоматично. Модуль є точкою входу `check(cwd)` для CLI-перевірок і повертає exit code (0 — OK, 1 — є зауваження або помилка запуску).
|
|
20
|
-
|
|
21
|
-
## Експорти / API
|
|
22
|
-
|
|
23
|
-
| Експорт | Тип | Призначення |
|
|
24
|
-
| ------------------------------------------------- | -------------------- | ----------------------------------------------------------------------------------- |
|
|
25
|
-
| `isDockerfileName(name)` | named function | Перевіряє, чи basename відповідає Dockerfile / Containerfile (включно з суфіксами). |
|
|
26
|
-
| `findDockerfilePaths(root, ignorePaths?)` | named async function | Збирає абсолютні шляхи до Dockerfile/Containerfile у репозиторії. |
|
|
27
|
-
| `parseFromStages(fileContent)` | named function | Парсить інструкції `FROM` і повертає масив `{ line, image }`. |
|
|
28
|
-
| `splitDockerfileStages(fileContent)` | named function | Розбиває Dockerfile на масив stage-ів `{ from, stageContent }`. |
|
|
29
|
-
| `getMultistageAndRuntimeHint(fileContent, opts?)` | named function | Перевіряє multistage та дозволеність фінального runtime-образу. |
|
|
30
|
-
| `getBunCompileHint(fileContent)` | named function | Перевіряє правило компіляції bun у бінарник на backend runtime. |
|
|
31
|
-
| `getNginxAlpineSlimTagHint(fileContent)` | named function | Перевіряє тег `alpine-slim` для nginx-unprivileged. |
|
|
32
|
-
| `getNonRootRuntimeHint(fileContent)` | named function | Перевіряє наявність `USER <non-root>` у фінальному stage. |
|
|
33
|
-
| `check(cwd?)` | named async function | Точка входу: обходить репозиторій, запускає всі перевірки, повертає exit code. |
|
|
34
|
-
|
|
35
|
-
Внутрішні (не експортуються): `isAllowedFinalRuntimeImage`, `readNearestDependencies`, `checkDockerfile`, а також модульні константи (`NEWLINE_RE`, `BUN_INSTALL_RE`, `BUN_BUILD_COMPILE_RE`, `BUN_WORD_RE`, `USER_LINE_RE`, `NGINX_UNPRIVILEGED_MIRROR_PREFIX`, `RUNTIME_IMAGES`, `DEBIAN_VIA_MIRROR_RE`, `BUN_RUNTIME_IMAGE`).
|
|
36
|
-
|
|
37
|
-
## Типи
|
|
38
|
-
|
|
39
|
-
```
|
|
40
|
-
/**
|
|
41
|
-
* @typedef {{
|
|
42
|
-
* line: number
|
|
43
|
-
* image: string
|
|
44
|
-
* }} FromStage
|
|
45
|
-
*/
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
`FromStage` — описує одну `FROM`-інструкцію: 1-based номер рядка і строковий image-ref (як у Dockerfile, з можливим тегом та `@digest`).
|
|
49
|
-
|
|
50
|
-
## Функції
|
|
51
|
-
|
|
52
|
-
### `isDockerfileName(name)`
|
|
53
|
-
|
|
54
|
-
- **Сигнатура:** `(name: string) => boolean`
|
|
55
|
-
- **Параметри:** `name` — basename файлу.
|
|
56
|
-
- **Повертає:** `true`, якщо ім'я (case-insensitive) дорівнює `dockerfile` / `containerfile` або починається з `dockerfile.` / `containerfile.` (наприклад `Dockerfile.prod`); інакше `false`.
|
|
57
|
-
- **Side effects:** немає.
|
|
58
|
-
|
|
59
|
-
### `findDockerfilePaths(root, ignorePaths = [])`
|
|
60
|
-
|
|
61
|
-
- **Сигнатура:** `(root: string, ignorePaths?: string[]) => Promise<string[]>`
|
|
62
|
-
- **Параметри:**
|
|
63
|
-
- `root` — корінь репозиторію, від якого виконується обхід;
|
|
64
|
-
- `ignorePaths` — масив каталогів, повністю виключених з обходу (наприклад `node_modules`, `.git`); передається в `walkDir`.
|
|
65
|
-
- **Повертає:** відсортований (через `localeCompare`) масив абсолютних шляхів до знайдених Dockerfile/Containerfile.
|
|
66
|
-
- **Side effects:** I/O на читання директорій через `walkDir`.
|
|
67
|
-
|
|
68
|
-
### `parseFromStages(fileContent)`
|
|
69
|
-
|
|
70
|
-
- **Сигнатура:** `(fileContent: string) => FromStage[]`
|
|
71
|
-
- **Параметри:** `fileContent` — повний вміст Dockerfile/Containerfile.
|
|
72
|
-
- **Повертає:** масив `FromStage` для кожного рядка, де `getFromImageToken` повернув непорожній image-ref. Номер рядка — 1-based.
|
|
73
|
-
- **Side effects:** немає (чиста функція).
|
|
74
|
-
|
|
75
|
-
### `isAllowedFinalRuntimeImage(lastLower, hasNativeAddon = false)` _(внутрішня)_
|
|
8
|
+
# lint.mjs
|
|
76
9
|
|
|
77
|
-
|
|
78
|
-
- **Параметри:**
|
|
79
|
-
- `lastLower` — image-ref останнього `FROM` без digest, у нижньому регістрі;
|
|
80
|
-
- `hasNativeAddon` — чи має проєкт нативний `.node`-аддон (sharp / @img/\* / argon2).
|
|
81
|
-
- **Повертає:** `true`, якщо образ дозволений як фінальний runtime:
|
|
82
|
-
- `scratch` або `scratch:*`;
|
|
83
|
-
- якщо `hasNativeAddon` — додатково `mirror.gcr.io/oven/bun` або `mirror.gcr.io/oven/bun:*`;
|
|
84
|
-
- `mirror.gcr.io/library/debian:<tag>` за умови, що `<tag>` містить підрядок `slim`;
|
|
85
|
-
- будь-який з `RUNTIME_IMAGES` (alpine, php, python, nginx-unprivileged, openresty) як точне співпадіння або з тегом `:*`.
|
|
86
|
-
- **Side effects:** немає.
|
|
87
|
-
|
|
88
|
-
### `splitDockerfileStages(fileContent)`
|
|
89
|
-
|
|
90
|
-
- **Сигнатура:** `(fileContent: string) => Array<{ from: FromStage, stageContent: string }>`
|
|
91
|
-
- **Параметри:** `fileContent` — вміст Dockerfile.
|
|
92
|
-
- **Повертає:**
|
|
93
|
-
- порожній масив, якщо `FROM` немає;
|
|
94
|
-
- інакше масив об'єктів `{ from, stageContent }`: рядки від `FROM` поточного stage (включно) до рядка перед наступним `FROM` (а для останнього — до кінця файлу), з'єднані через `\n`.
|
|
95
|
-
- **Side effects:** немає.
|
|
96
|
-
|
|
97
|
-
### `getMultistageAndRuntimeHint(fileContent, opts?)`
|
|
98
|
-
|
|
99
|
-
- **Сигнатура:** `(fileContent: string, opts?: { hasNativeAddon?: boolean }) => string | null`
|
|
100
|
-
- **Параметри:**
|
|
101
|
-
- `fileContent` — вміст Dockerfile;
|
|
102
|
-
- `opts.hasNativeAddon` — чи проєкт залежить від нативних `.node`-аддонів.
|
|
103
|
-
- **Повертає:**
|
|
104
|
-
- `null`, якщо `FROM` немає або всі вимоги задоволені;
|
|
105
|
-
- повідомлення про відсутність multistage (`'має бути multistage build: мінімум 2 інструкції FROM (build stage + runtime stage)'`), якщо лише один `FROM`;
|
|
106
|
-
- повідомлення `'фінальний FROM має бути дозволеним runtime-образом (див. docker.mdc: multistage), зараз: <image> (рядок N)'`, якщо фінальний образ не пройшов `isAllowedFinalRuntimeImage`.
|
|
107
|
-
- **Side effects:** немає.
|
|
108
|
-
|
|
109
|
-
### `getBunCompileHint(fileContent)`
|
|
110
|
-
|
|
111
|
-
- **Сигнатура:** `(fileContent: string) => string | null`
|
|
112
|
-
- **Параметри:** `fileContent` — вміст Dockerfile.
|
|
113
|
-
- **Тригер активації:** у файлі є `bun install` / `bun i` (за `BUN_INSTALL_RE`) **та** фінальний `FROM` починається з `mirror.gcr.io/library/alpine:` **та** він не є nginx-unprivileged / openresty (frontend).
|
|
114
|
-
- **Повертає:**
|
|
115
|
-
- `null`, якщо немає stage-ів, немає `bun install`, фінал не alpine, або фінал — frontend (nginx/openresty);
|
|
116
|
-
- повідомлення `'є `bun install`, але немає `bun build --compile` …'`, якщо у файлі немає `bun build --compile`;
|
|
117
|
-
- повідомлення `'фінальний stage не має містити Bun …'`, якщо у `stageContent` останнього stage зустрічається слово `bun` (RUN/CMD/ENTRYPOINT з `bun`).
|
|
118
|
-
- **Side effects:** немає.
|
|
119
|
-
|
|
120
|
-
### `getNginxAlpineSlimTagHint(fileContent)`
|
|
121
|
-
|
|
122
|
-
- **Сигнатура:** `(fileContent: string) => string | null`
|
|
123
|
-
- **Параметри:** `fileContent` — вміст Dockerfile.
|
|
124
|
-
- **Повертає:**
|
|
125
|
-
- `null`, якщо немає `FROM` з префіксом `mirror.gcr.io/nginxinc/nginx-unprivileged` або всі такі `FROM` мають тег `alpine-slim`;
|
|
126
|
-
- повідомлення про відсутній явний тег (`FROM <prefix>` без `:tag`);
|
|
127
|
-
- повідомлення про неправильний тег (наприклад `:latest`, `:alpine`).
|
|
128
|
-
- **Side effects:** немає.
|
|
129
|
-
|
|
130
|
-
### `getNonRootRuntimeHint(fileContent)`
|
|
131
|
-
|
|
132
|
-
- **Сигнатура:** `(fileContent: string) => string | null`
|
|
133
|
-
- **Параметри:** `fileContent` — вміст Dockerfile.
|
|
134
|
-
- **Логіка:**
|
|
135
|
-
- бере останній stage через `splitDockerfileStages`;
|
|
136
|
-
- проходить рядки і запам'ятовує останній `USER <token>` (regex `USER_LINE_RE`, з лапок видаляються `"`/`'`);
|
|
137
|
-
- якщо `USER` відсутній і фінальний образ — `mirror.gcr.io/nginxinc/nginx-unprivileged:*`, повертає `null` (виняток для nginx-unprivileged, який стартує від uid=101);
|
|
138
|
-
- якщо `USER` відсутній — повертає повідомлення про необхідність `USER <non-root>`;
|
|
139
|
-
- якщо `USER` дорівнює `root` або `0` (без врахування регістру) — повертає повідомлення про заборону root.
|
|
140
|
-
- **Повертає:** `string | null` (повідомлення помилки або `null`).
|
|
141
|
-
- **Side effects:** немає.
|
|
142
|
-
|
|
143
|
-
### `check(cwd = process.cwd())`
|
|
144
|
-
|
|
145
|
-
- **Сигнатура:** `(cwd?: string) => Promise<number>`
|
|
146
|
-
- **Параметри:** `cwd` — корінь репозиторію; за замовчуванням `process.cwd()`.
|
|
147
|
-
- **Логіка:**
|
|
148
|
-
1. Створює репортер `createCheckReporter()`.
|
|
149
|
-
2. Завантажує `ignorePaths` через `loadCursorIgnorePaths(root)`.
|
|
150
|
-
3. Знаходить усі Dockerfile/Containerfile через `findDockerfilePaths`.
|
|
151
|
-
4. Якщо файлів немає — `pass('Немає Dockerfile / Containerfile — перевірку hadolint пропущено')` і виходить.
|
|
152
|
-
5. Інакше виводить `Знайдено файлів для hadolint: N` і послідовно викликає `checkDockerfile(reporter, root, abs)` для кожного.
|
|
153
|
-
6. Повертає `reporter.getExitCode()`.
|
|
154
|
-
- **Повертає:** `0` — все OK, `1` — є зауваження або помилка запуску.
|
|
155
|
-
- **Side effects:** читання файлової системи, синхронний/асинхронний запуск hadolint через `lintDockerfileWithHadolint` (нативний бінарник через `ensureTool`).
|
|
156
|
-
|
|
157
|
-
### `readNearestDependencies(abs, root)` _(внутрішня)_
|
|
158
|
-
|
|
159
|
-
- **Сигнатура:** `(abs: string, root: string) => Promise<Record<string, unknown>>`
|
|
160
|
-
- **Параметри:**
|
|
161
|
-
- `abs` — абсолютний шлях до Dockerfile;
|
|
162
|
-
- `root` — корінь репозиторію (зупинка піднімання).
|
|
163
|
-
- **Логіка:** піднімається від `dirname(abs)` вгору, шукаючи `package.json`. Як тільки знаходить — повертає `dependencies` (або `{}`, якщо `dependencies` відсутні / не об'єкт). Якщо досягає `root` або вищого каталогу без `package.json` — повертає `{}`.
|
|
164
|
-
- **Повертає:** `dependencies` найближчого `package.json` або порожній об'єкт.
|
|
165
|
-
- **Side effects:** I/O на читання `package.json`; помилки `readFile` поглинаються (catch без оголошення).
|
|
166
|
-
|
|
167
|
-
### `checkDockerfile(reporter, root, abs)` _(внутрішня)_
|
|
168
|
-
|
|
169
|
-
- **Сигнатура:** `(reporter: ReturnType<typeof createCheckReporter>, root: string, abs: string) => Promise<void>`
|
|
170
|
-
- **Параметри:**
|
|
171
|
-
- `reporter` — інстанс репортера з `pass` / `fail`;
|
|
172
|
-
- `root` — корінь репо (для розрахунку posix-relative шляху);
|
|
173
|
-
- `abs` — абсолютний шлях до Dockerfile.
|
|
174
|
-
- **Логіка (послідовно):**
|
|
175
|
-
1. `rel = posixRel(root, abs) || basename(abs)`.
|
|
176
|
-
2. Читає вміст файлу (`readFile(abs, 'utf8')`).
|
|
177
|
-
3. Визначає `nativeAddons` через `getNativeAddonDeps(await readNearestDependencies(abs, root))`; `hasNativeAddon = nativeAddons.length > 0`.
|
|
178
|
-
4. `getMirrorGcrHint(content)` → `fail` з префіксом `mirror.gcr.io`.
|
|
179
|
-
5. `getMultistageAndRuntimeHint(content, { hasNativeAddon })` → `fail` з префіксом `multistage`.
|
|
180
|
-
6. Якщо `hasNativeAddon` — `getNativeAddonNoCompileHint(content, nativeAddons)` → `fail` з префіксом `native-addon`; інакше — `getBunCompileHint(content)` → `fail` з префіксом `compile`.
|
|
181
|
-
7. `getNonRootRuntimeHint(content)` → `fail` з префіксом `non-root`.
|
|
182
|
-
8. `getNginxAlpineSlimTagHint(content)` → `fail` з префіксом `nginx tag`.
|
|
183
|
-
9. `getNginxUnprivilegedUserHint(content)` → `fail` з префіксом `nginx non-root`.
|
|
184
|
-
10. `lintDockerfileWithHadolint(root, abs)` (синхронний виклик з результатом `{ ok, stdout, stderr, via }`): якщо `ok` — `pass(`${rel} (${via})`)`, інакше `fail` з хвостом stdout+stderr.
|
|
185
|
-
- **Повертає:** `Promise<void>`.
|
|
186
|
-
- **Side effects:** I/O на читання Dockerfile/package.json, запуск hadolint, виклики `reporter.pass`/`reporter.fail`.
|
|
187
|
-
|
|
188
|
-
## Константи / regex
|
|
10
|
+
## Огляд
|
|
189
11
|
|
|
190
|
-
|
|
191
|
-
- `BUN_INSTALL_RE = /\bbun\s+(?:install|i)\b/iu` — детект `bun install` / `bun i`.
|
|
192
|
-
- `BUN_BUILD_COMPILE_RE = /\bbun\s+build\b[^\n]*\s--compile\b/iu` — детект `bun build … --compile`.
|
|
193
|
-
- `BUN_WORD_RE = /\bbun\b/iu` — будь-яке слово `bun`.
|
|
194
|
-
- `USER_LINE_RE = /^\s*USER\s+([^\s#]+)/iu` — інструкція `USER`.
|
|
195
|
-
- `NGINX_UNPRIVILEGED_MIRROR_PREFIX = 'mirror.gcr.io/nginxinc/nginx-unprivileged'`.
|
|
196
|
-
- `RUNTIME_IMAGES` — `const`-кортеж дозволених фінальних runtime-образів: `mirror.gcr.io/library/alpine`, `…/library/php`, `…/library/python`, `…/nginxinc/nginx-unprivileged`, `…/openresty/openresty`.
|
|
197
|
-
- `DEBIAN_VIA_MIRROR_RE = /^mirror\.gcr\.io\/library\/debian:(.+)$/i` — debian через mirror, для перевірки `slim` у тегу.
|
|
198
|
-
- `BUN_RUNTIME_IMAGE = 'mirror.gcr.io/oven/bun'` — bun як фінальний runtime (легітимний лише для нативних `.node`-аддонів).
|
|
12
|
+
Модуль забезпечує декомпозицію структури Dockerfile для вилучення даних про багатостадійні збірки та залежності середовища. Функції, такі як `findDockerfilePaths` та `splitDockerfileStages`, використовуються для ідентифікації та розділення стадій збірки. Модуль надає інструменти для отримання підказок про виконання, включаючи визначення багатостадійного режиму (`getMultistageAndRuntimeHint`), компіляційних налаштувань (`getBunCompileHint`), та підказок про використання образу Nginx Alpine Slim (`getNginxAlpineSlimTagHint`). Додатково, він визначає необхідність роботи без прав root (`getNonRootRuntimeHint`). (docker.mdc)
|
|
199
13
|
|
|
200
|
-
##
|
|
14
|
+
## Поведінка
|
|
201
15
|
|
|
202
|
-
|
|
16
|
+
isDockerfileName
|
|
17
|
+
Перевіряє, чи є вхідний рядок назвою Dockerfile або Containerfile.
|
|
203
18
|
|
|
204
|
-
|
|
205
|
-
|
|
19
|
+
findDockerfilePaths
|
|
20
|
+
Збирає абсолютні шляхи до Dockerfile або Containerfile від заданого кореня репозиторію, враховуючи виключені шляхи.
|
|
206
21
|
|
|
207
|
-
|
|
22
|
+
parseFromStages
|
|
23
|
+
Витягує інструкції FROM з вмісту файлу.
|
|
208
24
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
- `../lib/docker-nginx-user.mjs` → `getNginxUnprivilegedUserHint`.
|
|
212
|
-
- `../lib/docker-hadolint.mjs` → `lintDockerfileWithHadolint`, `posixRel`.
|
|
213
|
-
- `../../../scripts/lib/check-reporter.mjs` → `createCheckReporter` (з методами `pass`, `fail`, `getExitCode`).
|
|
214
|
-
- `../../../scripts/lib/load-cursor-config.mjs` → `loadCursorIgnorePaths`.
|
|
215
|
-
- `../../../scripts/utils/walkDir.mjs` → `walkDir`.
|
|
25
|
+
splitDockerfileStages
|
|
26
|
+
Розбиває вміст Dockerfile на окремі стадії на основі інструкцій FROM.
|
|
216
27
|
|
|
217
|
-
|
|
28
|
+
getMultistageAndRuntimeHint
|
|
29
|
+
Перевіряє, чи має Dockerfile мінімум дві інструкції FROM і чи є фінальний образ дозволеним runtime-образом (docker.mdc).
|
|
218
30
|
|
|
219
|
-
|
|
31
|
+
getBunCompileHint
|
|
32
|
+
Перевіряє наявність інструкцій `bun install` та відсутності `bun build --compile` для виявлення необхідності компіляції бінарника (docker.mdc).
|
|
220
33
|
|
|
221
|
-
|
|
34
|
+
getNginxAlpineSlimTagHint
|
|
35
|
+
Перевіряє, чи містить інструкція FROM для образу nginx потрібний тег `alpine-slim` (docker.mdc).
|
|
222
36
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
3. `findDockerfilePaths(root, ignorePaths)` за допомогою `walkDir` обходить дерево і збирає всі Dockerfile/Containerfile, відсортовані.
|
|
226
|
-
4. Якщо файлів немає — репорт `pass` і exit 0.
|
|
227
|
-
5. Інакше для кожного знайденого Dockerfile послідовно виконується `checkDockerfile`, який:
|
|
228
|
-
- читає вміст,
|
|
229
|
-
- підіймається до найближчого `package.json` для визначення `hasNativeAddon`,
|
|
230
|
-
- запускає шість статичних перевірок (mirror, multistage/runtime, compile **або** native-addon, non-root, nginx tag, nginx user),
|
|
231
|
-
- запускає `hadolint` через `lintDockerfileWithHadolint` і репортує результат.
|
|
232
|
-
6. Усі помилки агрегуються в репортері; підсумковий код повертає `reporter.getExitCode()` (0/1).
|
|
37
|
+
getNonRootRuntimeHint
|
|
38
|
+
Перевіряє, чи присутня інструкція USER у фінальній стадії і чи не використовується `root` або `0` для запуску (docker.mdc).
|
|
233
39
|
|
|
234
|
-
|
|
40
|
+
check
|
|
41
|
+
Запускає перевірки Dockerfile через hadolint, включаючи перевірки multistage, компіляції, non-root, тегів nginx та загальну валідацію.
|
|
235
42
|
|
|
236
|
-
|
|
237
|
-
|
|
43
|
+
readNearestDependencies
|
|
44
|
+
Читає залежності з найближчого package.json, розташованого у каталогах Dockerfile або вище.
|
|
238
45
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
```
|
|
46
|
+
checkDockerfile
|
|
47
|
+
Перевіряє індивідуальний Dockerfile/Containerfile на наявність інструкцій, пов'язаних з mirror.gcr.io, multistage, компіляції, non-root, тегів nginx та виконує перевірку через hadolint.
|
|
242
48
|
|
|
243
|
-
|
|
49
|
+
## Публічний API
|
|
244
50
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
51
|
+
isDockerfileName — перевіряє наявність файлів `Dockerfile` або `Containerfile` у назві.
|
|
52
|
+
findDockerfilePaths — збирає повні шляхи до файлів `Dockerfile` або `Containerfile` від поточної робочої директорії.
|
|
53
|
+
parseFromStages — витягує всі інструкції `FROM <image>` з вмісту файлів.
|
|
54
|
+
splitDockerfileStages — розділяє файл `Dockerfile` на послідовні етапи за інструкціями `FROM`. Повертає порожній масив, якщо інструкції `FROM` відсутні.
|
|
55
|
+
getMultistageAndRuntimeHint — перевіряє вимоги до структури Dockerfile:
|
|
56
|
+
multistage — вимагає мінімум два етапи `FROM`.
|
|
57
|
+
фінальний FROM — перевіряє, чи дозволений образ у `docker.mdc` (alpine, scratch, debian slim, php, python, nginx, openresty, тощо). Для проєктів з нативним .node-аддоном дозволено `mirror.gcr.io/oven/bun:*` (bun-рантайм).
|
|
58
|
+
getBunCompileHint — перевіряє наявність вимоги "компіляції в бінарник" для bun-проєктів на бекенд-рантаймах.
|
|
59
|
+
Тригер — перевіряє, чи присутній крок `bun install` або `bun i` у Dockerfile.
|
|
60
|
+
Тригер — перевіряє, чи фінальний образ — `mirror.gcr.io/library/alpine:*` (виключаючи фронтенд nginx/openresty).
|
|
61
|
+
getNginxAlpineSlimTagHint — перевіряє, чи містить `FROM` для nginx-образу (`mirror.gcr.io/nginxinc/nginx-unprivileged`) тег `alpine-slim` (`docker.mdc`).
|
|
62
|
+
getNonRootRuntimeHint — перевіряє вимогу "non-root" у фінальному runtime-етапі (`docker.mdc`).
|
|
63
|
+
Очікування — перевіряє, чи містить build stage інструкцію `bun build --compile`.
|
|
64
|
+
Очікування — перевіряє, чи відсутні виклики `bun` у фінальному етапі (залишкові інструменти збірки).
|
|
65
|
+
Очікування — перевіряє, чи містить фінальний етап інструкцію `USER <name|uid>`.
|
|
66
|
+
Очікування — перевіряє, чи користувач у фінальному етапі не є `root` і не дорівнює `0`.
|
|
67
|
+
check — виконує перевірку через hadolint (`docker.mdc`).
|
|
248
68
|
|
|
249
|
-
##
|
|
69
|
+
## Гарантії поведінки
|
|
250
70
|
|
|
251
|
-
-
|
|
252
|
-
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
- `nginx-unprivileged` без явного `USER` не вважається порушенням non-root (uid=101 за замовчуванням), але тег має бути саме `alpine-slim`.
|
|
256
|
-
- `scratch` (як точне співпадіння або з тегом) завжди дозволено як фінальний runtime.
|
|
257
|
-
- `debian` дозволено лише через `mirror.gcr.io/library/debian:<tag>` де `<tag>` містить `slim`.
|
|
258
|
-
- `posixRel` нормалізує шлях для уніфікованого виводу в репорті; якщо повертає порожній рядок — використовується `basename(abs)`.
|
|
71
|
+
- Read-only: файл не виконує операцій запису у файлову систему.
|
|
72
|
+
- Перехоплює помилки і не пропускає винятків назовні (fail-safe).
|
|
73
|
+
- За невдалої перевірки повертає `false`/`null` замість винятку.
|
|
74
|
+
- Не звертається до мережі.
|