@nitra/cursor 1.8.222 → 1.9.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 +66 -0
- package/bin/n-cursor.js +3 -2
- package/mdc/abie.mdc +13 -0
- package/mdc/changelog.mdc +3 -2
- package/mdc/ci4.mdc +8 -0
- package/mdc/ga.mdc +3 -2
- package/mdc/graphql.mdc +3 -2
- package/mdc/hasura.mdc +3 -2
- package/mdc/image-avif.mdc +3 -2
- package/mdc/image-compress.mdc +3 -2
- package/mdc/k8s.mdc +1 -3
- package/mdc/nginx-default-tpl.mdc +3 -1
- package/mdc/php.mdc +3 -2
- package/mdc/style-lint.mdc +3 -2
- package/mdc/vue.mdc +3 -2
- package/package.json +1 -1
- package/policy/abie/base_deployment_preem/base_deployment_preem.rego +56 -0
- package/policy/abie/base_deployment_preem/base_deployment_preem_test.rego +60 -0
- package/policy/abie/clean_merged_ignore_branches/clean_merged_ignore_branches.rego +100 -0
- package/policy/abie/clean_merged_ignore_branches/clean_merged_ignore_branches_test.rego +48 -0
- package/policy/abie/health_check_policy/health_check_policy.rego +91 -22
- package/policy/abie/health_check_policy/health_check_policy_test.rego +99 -0
- package/policy/abie/http_route_base/http_route_base_test.rego +64 -0
- package/policy/k8s/kustomization/kustomization.rego +2 -2
- package/policy/k8s/manifest/manifest.rego +4 -2
- package/scripts/check-abie.mjs +102 -369
- package/scripts/check-ga.mjs +89 -9
- package/scripts/check-k8s.mjs +129 -704
- package/scripts/lint-conftest.mjs +25 -2
- package/scripts/lint-ga.mjs +18 -132
- package/scripts/utils/run-conftest-batch.mjs +117 -0
- package/policy/k8s/kustomize_managed/kustomize_managed.rego +0 -31
- package/policy/k8s/kustomize_managed/kustomize_managed_test.rego +0 -30
package/scripts/check-ga.mjs
CHANGED
|
@@ -22,6 +22,7 @@ import { join } from 'node:path'
|
|
|
22
22
|
import { createCheckReporter } from './utils/check-reporter.mjs'
|
|
23
23
|
import { eventPathsIncludeExact, parseWorkflowYaml } from './utils/gha-workflow.mjs'
|
|
24
24
|
import { resolveCmd } from './utils/resolve-cmd.mjs'
|
|
25
|
+
import { runConftestBatch } from './utils/run-conftest-batch.mjs'
|
|
25
26
|
|
|
26
27
|
/** Шаблони наявності MegaLinter у вмісті workflow */
|
|
27
28
|
const MEGALINTER_USE_PATTERNS = [/oxsecurity\/megalinter-action/i, /megalinter\/megalinter/i]
|
|
@@ -276,7 +277,7 @@ async function checkLintGaScript(passFn, failFn) {
|
|
|
276
277
|
* @param {(msg: string) => void} passFn callback при успішній перевірці
|
|
277
278
|
* @param {(msg: string) => void} failFn callback при помилці
|
|
278
279
|
*/
|
|
279
|
-
function checkShellcheckInstalled(passFn, failFn) {
|
|
280
|
+
export function checkShellcheckInstalled(passFn, failFn) {
|
|
280
281
|
if (resolveCmd('shellcheck')) {
|
|
281
282
|
passFn('shellcheck встановлений локально, actionlint виконуватиме SC-правила, як у CI')
|
|
282
283
|
return
|
|
@@ -325,7 +326,84 @@ function checkGaWorkflowFiles(wfDir, files, pass, fail) {
|
|
|
325
326
|
}
|
|
326
327
|
|
|
327
328
|
/**
|
|
328
|
-
*
|
|
329
|
+
* Per-workflow Rego-полісі: namespace ↔ конкретний workflow-файл. Кожен пакет
|
|
330
|
+
* у `npm/policy/ga/<name>/` містить правила специфічні для ОДНОГО workflow,
|
|
331
|
+
* тому conftest викликаємо з `--namespace` окремо на кожен файл (інакше правила
|
|
332
|
+
* чужого workflow застосуються до неправильного файла).
|
|
333
|
+
* @type {Array<{ workflow: string, namespace: string, policyDirRel: string }>}
|
|
334
|
+
*/
|
|
335
|
+
const GA_PER_WORKFLOW_REGO_TARGETS = [
|
|
336
|
+
{
|
|
337
|
+
workflow: '.github/workflows/clean-ga-workflows.yml',
|
|
338
|
+
namespace: 'ga.clean_ga_workflows',
|
|
339
|
+
policyDirRel: 'ga/clean_ga_workflows'
|
|
340
|
+
},
|
|
341
|
+
{
|
|
342
|
+
workflow: '.github/workflows/clean-merged-branch.yml',
|
|
343
|
+
namespace: 'ga.clean_merged_branch',
|
|
344
|
+
policyDirRel: 'ga/clean_merged_branch'
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
workflow: '.github/workflows/lint-ga.yml',
|
|
348
|
+
namespace: 'ga.lint_ga',
|
|
349
|
+
policyDirRel: 'ga/lint_ga'
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
workflow: '.github/workflows/git-ai.yml',
|
|
353
|
+
namespace: 'ga.git_ai',
|
|
354
|
+
policyDirRel: 'ga/git_ai'
|
|
355
|
+
}
|
|
356
|
+
]
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Plan B (rego-authoritative): на початку перевірки правила ga прогнати усі
|
|
360
|
+
* Rego-полісі з `npm/policy/ga/`. Спочатку — per-workflow (4 окремі спавни,
|
|
361
|
+
* бо кожен namespace застосовний лише до свого файла), потім один батч-спавн
|
|
362
|
+
* `ga.workflow_common` на всі `.github/workflows/*.yml`. Hard-fail без
|
|
363
|
+
* `conftest` у PATH — узгоджено з Plan B (див. `runConftestBatch`).
|
|
364
|
+
* @param {string} wfDir шлях до `.github/workflows`
|
|
365
|
+
* @param {string[]} ymlWorkflows відносні (від `wfDir`) імена файлів `*.yml`
|
|
366
|
+
* @param {(msg: string) => void} pass callback при успішній перевірці
|
|
367
|
+
* @param {(msg: string) => void} fail callback при помилці
|
|
368
|
+
* @returns {Promise<void>}
|
|
369
|
+
*/
|
|
370
|
+
async function runAllGaRego(wfDir, ymlWorkflows, pass, fail) {
|
|
371
|
+
for (const target of GA_PER_WORKFLOW_REGO_TARGETS) {
|
|
372
|
+
if (!existsSync(target.workflow)) continue
|
|
373
|
+
const violations = runConftestBatch({
|
|
374
|
+
policyDirRel: target.policyDirRel,
|
|
375
|
+
namespace: target.namespace,
|
|
376
|
+
files: [target.workflow]
|
|
377
|
+
})
|
|
378
|
+
for (const v of violations) fail(`${target.workflow}: ${v.message}`)
|
|
379
|
+
if (violations.length === 0) {
|
|
380
|
+
pass(`${target.workflow}: відповідає ${target.namespace} (rego)`)
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
if (ymlWorkflows.length === 0) return
|
|
385
|
+
const wfFiles = ymlWorkflows.map(f => join(wfDir, f))
|
|
386
|
+
const violations = runConftestBatch({
|
|
387
|
+
policyDirRel: 'ga/workflow_common',
|
|
388
|
+
namespace: 'ga.workflow_common',
|
|
389
|
+
files: wfFiles
|
|
390
|
+
})
|
|
391
|
+
for (const v of violations) fail(`${v.filename}: ${v.message}`)
|
|
392
|
+
if (violations.length === 0) {
|
|
393
|
+
pass(`${wfFiles.length} workflow(s) відповідають ga.workflow_common (rego)`)
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Перевіряє відповідність проєкту правилам ga.mdc.
|
|
399
|
+
*
|
|
400
|
+
* Plan B-патерн: пер-документна валідація workflow-структури делегована
|
|
401
|
+
* Rego-полісі у `npm/policy/ga/`; виклик через `runAllGaRego` (батч-conftest)
|
|
402
|
+
* — це перший крок `check()`. Далі — JS-частина (cross-file перевірки на
|
|
403
|
+
* наявність файлів, `git ls-files`-залежні `on.push.paths` glob, vscode/zizmor
|
|
404
|
+
* config, megalinter залишки тощо). `bun run lint-ga` додатково запускає
|
|
405
|
+
* `actionlint` + `zizmor` зовнішніми тулчейнами і **викликає цю ж `check()`** —
|
|
406
|
+
* тобто rego-частина живе тут, не в `lint-ga.mjs`.
|
|
329
407
|
* @returns {Promise<number>} 0 — все OK, 1 — є проблеми
|
|
330
408
|
*/
|
|
331
409
|
export async function check() {
|
|
@@ -339,6 +417,13 @@ export async function check() {
|
|
|
339
417
|
return reporter.getExitCode()
|
|
340
418
|
}
|
|
341
419
|
|
|
420
|
+
const files = await readdir(wfDir)
|
|
421
|
+
const ymlWorkflows = files.filter(f => f.endsWith('.yml'))
|
|
422
|
+
|
|
423
|
+
// Rego-крок (per-workflow + workflow_common) — на початку, як єдине джерело
|
|
424
|
+
// істини для пер-документних структурних правил workflow-файлів.
|
|
425
|
+
await runAllGaRego(wfDir, ymlWorkflows, pass, fail)
|
|
426
|
+
|
|
342
427
|
const setupBunDepsAction = '.github/actions/setup-bun-deps/action.yml'
|
|
343
428
|
if (existsSync(setupBunDepsAction)) {
|
|
344
429
|
pass(`${setupBunDepsAction} існує`)
|
|
@@ -348,7 +433,6 @@ export async function check() {
|
|
|
348
433
|
)
|
|
349
434
|
}
|
|
350
435
|
|
|
351
|
-
const files = await readdir(wfDir)
|
|
352
436
|
checkGaWorkflowFiles(wfDir, files, pass, fail)
|
|
353
437
|
|
|
354
438
|
await checkApplyWorkflow(wfDir, files, 'apply-k8s.yml', '**/k8s/**/*.yaml', pass, fail)
|
|
@@ -367,14 +451,10 @@ export async function check() {
|
|
|
367
451
|
|
|
368
452
|
await checkVscodeSettingsForGa(pass, fail)
|
|
369
453
|
|
|
370
|
-
const ymlWorkflows = files.filter(f => f.endsWith('.yml'))
|
|
371
454
|
await checkMegalinter(wfDir, ymlWorkflows, pass, fail)
|
|
372
455
|
|
|
373
|
-
//
|
|
374
|
-
//
|
|
375
|
-
// перенесено в Rego (`npm/policy/ga/workflow_common/`); їх запускає
|
|
376
|
-
// `bun run lint-ga` через conftest. Тут лишилася лише git-залежна перевірка
|
|
377
|
-
// `on.push.paths` glob-ів (вимагає `git ls-files`).
|
|
456
|
+
// git-залежна перевірка `on.push.paths` glob-ів (вимагає `git ls-files`) —
|
|
457
|
+
// лишається в JS, бо conftest не має доступу до файлової системи репо.
|
|
378
458
|
for (const f of ymlWorkflows) {
|
|
379
459
|
const content = await readFile(join(wfDir, f), 'utf8')
|
|
380
460
|
const parsed = parseWorkflowYaml(content)
|