@7n/rules 1.8.1 → 1.8.3
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 +13 -0
- package/package.json +1 -1
- package/rules/bun/licensee/docs/main.md +12 -19
- package/rules/bun/licensee/main.mjs +20 -4
- package/rules/k8s/hasura_configmap/hasura_configmap.mdc +1 -1
- package/rules/k8s/manifests/docs/fix-manifests.md +1 -1
- package/rules/k8s/manifests/fix-manifests.mjs +20 -26
- package/rules/k8s/manifests/main.mjs +99 -17
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.8.3] - 2026-07-17
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- release: @7n/rules@1.8.2
|
|
8
|
+
|
|
9
|
+
## [1.8.2] - 2026-07-17
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- bun/licensee: розрізняти crash інструмента (stderr) від реального ліцензійного порушення (stdout, --errors-only)
|
|
14
|
+
- k8s/manifests: знизити когнітивну складність ensureHasuraConfigMapRequiredEnv нижче порогу sonarjs
|
|
15
|
+
|
|
3
16
|
## [1.8.1] - 2026-07-17
|
|
4
17
|
|
|
5
18
|
### Changed
|
package/package.json
CHANGED
|
@@ -3,35 +3,28 @@ type: JS Module
|
|
|
3
3
|
title: main.mjs
|
|
4
4
|
resource: npm/rules/bun/licensee/main.mjs
|
|
5
5
|
docgen:
|
|
6
|
-
crc:
|
|
7
|
-
model:
|
|
8
|
-
score: 90
|
|
9
|
-
issues: surzhik,judge:inaccurate:0.96
|
|
10
|
-
judgeModel: openai-codex/gpt-5.4-mini
|
|
6
|
+
crc: 48c72e2b
|
|
7
|
+
model: manual
|
|
11
8
|
---
|
|
12
9
|
|
|
13
10
|
## Огляд
|
|
14
11
|
|
|
15
|
-
|
|
12
|
+
Read-only detector `bun/licensee`: перевіряє ліцензії npm-залежностей проєкту через зовнішній інструмент `licensee` (`bun x licensee`), звіряючи їх з allowlist у `.licensee.json`. Розрізняє два принципово різні провали: `licensee` знайшов реально заборонену ліцензію (`license-violation`) — і `licensee` сам впав з помилкою (`licensee-crashed`), наприклад через несумісність `@npmcli/arborist` (яким він читає `node_modules`) з деревом, зібраним `bun install`.
|
|
16
13
|
|
|
17
14
|
## Поведінка
|
|
18
15
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
3. Визначається команда `bun`. Якщо `bun` не знайдена у системному шляху, повідомляється про це (bun.mdc).
|
|
26
|
-
4. Виконується команда `bun x licensee --production --quiet` у корені проєкту.
|
|
27
|
-
5. Якщо команда `licensee` завершується успішно (статус 0), повідомляється, що ліцензії відповідають вимогам.
|
|
28
|
-
6. Якщо команда `licensee` завершується з помилкою (не 0), повідомляється про порушення ліцензій (код) (bun.mdc).
|
|
16
|
+
1. Якщо `.licensee.json` відсутній — `licensee-config-missing`; генерація конфігу — окремий T0-фікс (`fix-licensee.mjs`), не тут.
|
|
17
|
+
2. Якщо `bun` не знайдено в PATH — `bun-missing`.
|
|
18
|
+
3. Запускає `bun x licensee --production --errors-only` (без `--quiet` — реальне порушення потребує деталі: ім'я/версія/ліцензія пакета, які `licensee` пише в stdout через `print()`).
|
|
19
|
+
4. Статус 0 — без порушень.
|
|
20
|
+
5. Статус ≠ 0 і є вивід у **stderr** — трактується як crash/`die()` самого `licensee` (invalid config або необроблений виняток усередині тула), НЕ як ліцензійне порушення: `licensee-crashed`, повідомлення включає stderr і підказку перевірити вручну `bunx licensee --production`.
|
|
21
|
+
6. Статус ≠ 0 і stderr порожній, є вивід у **stdout** — це справжній `NOT APPROVED`-звіт від `licensee` (`--errors-only` друкує лише невідповідні пакети): `license-violation` з деталлю пакета/ліцензії у повідомленні.
|
|
29
22
|
|
|
30
23
|
## Публічний API
|
|
31
24
|
|
|
32
|
-
lint —
|
|
33
|
-
licensee — перевіряє відповідність ліцензій усіх використаних npm-залежностей файлу `.licensee.json`.
|
|
25
|
+
- `lint(ctx)` — detector-контракт unified lint surface; повертає `{ violations }`.
|
|
34
26
|
|
|
35
27
|
## Гарантії поведінки
|
|
36
28
|
|
|
37
|
-
- (
|
|
29
|
+
- Read-only: не пише `.licensee.json` і не змінює `node_modules`/lockfile сам (побічний ефект `bun x` — авто-встановлення пакета `licensee`, якщо відсутній у bunx-кеші, — керується bun, не цим модулем).
|
|
30
|
+
- Канал stdout/stderr — єдиний сигнал розрізнення crash vs реальне порушення; текстові евристики за вмістом повідомлення не використовуються.
|
|
@@ -34,11 +34,27 @@ export function lint(ctx) {
|
|
|
34
34
|
return reporter.result()
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
// Без --quiet: `licensee` пише реальні NOT APPROVED записи (name/version/license) у
|
|
38
|
+
// stdout через print() — деталь замість голого "код 1". Crash/die() усередині
|
|
39
|
+
// самого тула (invalid config, внутрішній виняток на кшталт "Cannot read properties
|
|
40
|
+
// of undefined (reading 'localeCompare')" — спостережено з @npmcli/arborist на
|
|
41
|
+
// bun-based node_modules) завжди йде у stderr через die(); легітимний звіт про
|
|
42
|
+
// порушення — лише у stdout. Канал розрізняє crash від реального порушення.
|
|
43
|
+
const r = spawnSync(bun, ['x', 'licensee', '--production', '--errors-only'], { cwd, encoding: 'utf8', shell: false })
|
|
38
44
|
if (r.status !== 0) {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
const stderr = (r.stderr ?? '').trim().slice(0, 2000)
|
|
46
|
+
if (stderr) {
|
|
47
|
+
fail(
|
|
48
|
+
`lint-bun: licensee — інструмент завершився з помилкою, це НЕ підтверджене ліцензійне порушення ` +
|
|
49
|
+
`(код ${r.status}, bun.mdc). Ймовірна причина — несумісність @npmcli/arborist (яким licensee читає ` +
|
|
50
|
+
`node_modules) з деревом, зібраним bun install. Перевір вручну: \`bunx licensee --production\`.\n${stderr}`,
|
|
51
|
+
'licensee-crashed'
|
|
52
|
+
)
|
|
53
|
+
} else {
|
|
54
|
+
const stdout = (r.stdout ?? '').trim().slice(0, 2000)
|
|
55
|
+
const detail = stdout ? `\n${stdout}` : ''
|
|
56
|
+
fail(`lint-bun: licensee — порушення ліцензій (код ${r.status}, bun.mdc)${detail}`, 'license-violation')
|
|
57
|
+
}
|
|
42
58
|
}
|
|
43
59
|
return reporter.result()
|
|
44
60
|
}
|
|
@@ -11,7 +11,7 @@ Rego-пакет: `k8s.hasura_configmap`
|
|
|
11
11
|
| `HASURA_GRAPHQL_ENABLE_REMOTE_SCHEMA_PERMISSIONS` | `"true"` |
|
|
12
12
|
| `HASURA_GRAPHQL_ENABLE_RELAY` | `"false"` |
|
|
13
13
|
| `HASURA_GRAPHQL_ENABLE_TELEMETRY` | `"false"` |
|
|
14
|
-
| `HASURA_GRAPHQL_ENABLED_LOG_TYPES` | `"startup,http-log"` (
|
|
14
|
+
| `HASURA_GRAPHQL_ENABLED_LOG_TYPES` | `"startup,http-log"` (точно; base/dev; overlay має патчем замінити на `"startup"` — `http-log` лише для base/dev) |
|
|
15
15
|
| `HASURA_GRAPHQL_ENABLED_APIS` | `"metadata,graphql,pgdump"` (base/dev; overlay має патчем замінити на `"metadata,graphql"`) |
|
|
16
16
|
| `HASURA_GRAPHQL_DISABLE_EVENTING` | ключ обов'язковий, значення довільне (рекомендовано `"true"`) |
|
|
17
17
|
|
|
@@ -157,6 +157,22 @@ function isFalsyBool(v) {
|
|
|
157
157
|
return typeof v === 'string' && v.trim().toLowerCase() === 'false'
|
|
158
158
|
}
|
|
159
159
|
|
|
160
|
+
/**
|
|
161
|
+
* Визначає значення для одного `HASURA_GRAPHQL_*` ключа за очікуванням із
|
|
162
|
+
* `HASURA_REQUIRED_ENV_VALUES`: `null` — довільне значення, проставляється лише
|
|
163
|
+
* якщо ключ відсутній (дефолт `'true'`); `'true'`/`'false'` — булеве порівняння
|
|
164
|
+
* (case-insensitive, `isTruthyBool`/`isFalsyBool`); інакше — точний рядок.
|
|
165
|
+
* @param {string|null} expected очікуване значення з `HASURA_REQUIRED_ENV_VALUES`
|
|
166
|
+
* @param {unknown} current поточне значення ключа в `data` (може бути `undefined`)
|
|
167
|
+
* @returns {string|null} значення для `setIn`, або `null`, якщо змін не потрібно
|
|
168
|
+
*/
|
|
169
|
+
function resolveHasuraEnvValue(expected, current) {
|
|
170
|
+
if (expected === null) return current === undefined ? 'true' : null
|
|
171
|
+
if (expected === 'true') return isTruthyBool(current) ? null : 'true'
|
|
172
|
+
if (expected === 'false') return isFalsyBool(current) ? null : 'false'
|
|
173
|
+
return current === expected ? null : expected
|
|
174
|
+
}
|
|
175
|
+
|
|
160
176
|
/**
|
|
161
177
|
* Проставляє обов'язкові `HASURA_GRAPHQL_*` env-ключі (`HASURA_REQUIRED_ENV_VALUES`,
|
|
162
178
|
* дзеркалить `k8s.hasura_configmap.rego`) у `data` документа `kind: ConfigMap`. Ключ з
|
|
@@ -177,32 +193,10 @@ export function ensureHasuraConfigMapRequiredEnv(content) {
|
|
|
177
193
|
|
|
178
194
|
let changed = false
|
|
179
195
|
for (const [key, expected] of Object.entries(HASURA_REQUIRED_ENV_VALUES)) {
|
|
180
|
-
const
|
|
181
|
-
if (
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
changed = true
|
|
185
|
-
}
|
|
186
|
-
continue
|
|
187
|
-
}
|
|
188
|
-
if (expected === 'true') {
|
|
189
|
-
if (!isTruthyBool(current)) {
|
|
190
|
-
doc.setIn(['data', key], 'true')
|
|
191
|
-
changed = true
|
|
192
|
-
}
|
|
193
|
-
continue
|
|
194
|
-
}
|
|
195
|
-
if (expected === 'false') {
|
|
196
|
-
if (!isFalsyBool(current)) {
|
|
197
|
-
doc.setIn(['data', key], 'false')
|
|
198
|
-
changed = true
|
|
199
|
-
}
|
|
200
|
-
continue
|
|
201
|
-
}
|
|
202
|
-
if (current !== expected) {
|
|
203
|
-
doc.setIn(['data', key], expected)
|
|
204
|
-
changed = true
|
|
205
|
-
}
|
|
196
|
+
const value = resolveHasuraEnvValue(expected, doc.getIn(['data', key]))
|
|
197
|
+
if (value === null) continue
|
|
198
|
+
doc.setIn(['data', key], value)
|
|
199
|
+
changed = true
|
|
206
200
|
}
|
|
207
201
|
if (!changed) return null
|
|
208
202
|
return doc.toString()
|
|
@@ -4922,6 +4922,12 @@ const HASURA_OVERLAY_ENABLED_APIS = 'metadata,graphql'
|
|
|
4922
4922
|
/** JSON-Pointer ключа `HASURA_GRAPHQL_ENABLED_APIS` у `data` ConfigMap (для JSON6902-патчів). */
|
|
4923
4923
|
const HASURA_ENABLED_APIS_DATA_POINTER = '/data/HASURA_GRAPHQL_ENABLED_APIS'
|
|
4924
4924
|
|
|
4925
|
+
/** Очікуване `HASURA_GRAPHQL_ENABLED_LOG_TYPES` у non-base/dev overlay (без `http-log` — він лише для base/dev). */
|
|
4926
|
+
const HASURA_OVERLAY_ENABLED_LOG_TYPES = 'startup'
|
|
4927
|
+
|
|
4928
|
+
/** JSON-Pointer ключа `HASURA_GRAPHQL_ENABLED_LOG_TYPES` у `data` ConfigMap (для JSON6902-патчів). */
|
|
4929
|
+
const HASURA_ENABLED_LOG_TYPES_DATA_POINTER = '/data/HASURA_GRAPHQL_ENABLED_LOG_TYPES'
|
|
4930
|
+
|
|
4925
4931
|
/**
|
|
4926
4932
|
* Чи дерево kustomization (`resources` / `bases` / `components` / `crds`, рекурсивно) містить
|
|
4927
4933
|
* **Hasura-Deployment** у шарі base (образ `hasura/graphql-engine`). Маркер того, що overlay успадковує
|
|
@@ -4965,18 +4971,19 @@ function firstValidYamlJsonFromPatchText(patchText) {
|
|
|
4965
4971
|
}
|
|
4966
4972
|
|
|
4967
4973
|
/**
|
|
4968
|
-
* Значення `data
|
|
4969
|
-
* Повертає значення першої `add`/`replace`-операції на `/data
|
|
4974
|
+
* Значення `data.<dataKey>` з JSON6902-патчу (масив операцій).
|
|
4975
|
+
* Повертає значення першої `add`/`replace`-операції на `/data/<dataKey>`.
|
|
4970
4976
|
* @param {unknown[]} ops масив JSON6902-операцій
|
|
4977
|
+
* @param {string} dataPointer JSON-Pointer ключа (`/data/<dataKey>`)
|
|
4971
4978
|
* @returns {string | null} присвоєне значення (рядок) або null
|
|
4972
4979
|
*/
|
|
4973
|
-
function
|
|
4980
|
+
function hasuraDataKeyValueFromJson6902(ops, dataPointer) {
|
|
4974
4981
|
for (const item of ops) {
|
|
4975
4982
|
if (item === null || typeof item !== 'object' || Array.isArray(item)) continue
|
|
4976
4983
|
const rec = /** @type {Record<string, unknown>} */ (item)
|
|
4977
4984
|
const op = typeof rec.op === 'string' ? rec.op.trim().toLowerCase() : ''
|
|
4978
4985
|
const path = typeof rec.path === 'string' ? normalizeJsonPatchPath(rec.path) : ''
|
|
4979
|
-
if ((op === 'add' || op === 'replace') && path ===
|
|
4986
|
+
if ((op === 'add' || op === 'replace') && path === dataPointer) {
|
|
4980
4987
|
return typeof rec.value === 'string' ? rec.value : JSON.stringify(rec.value)
|
|
4981
4988
|
}
|
|
4982
4989
|
}
|
|
@@ -4984,42 +4991,58 @@ function enabledApisValueFromJson6902(ops) {
|
|
|
4984
4991
|
}
|
|
4985
4992
|
|
|
4986
4993
|
/**
|
|
4987
|
-
* Значення `data
|
|
4994
|
+
* Значення `data.<dataKey>` зі Strategic-Merge-патчу (об'єкт із `data`).
|
|
4988
4995
|
* @param {object} parsed розпарсений об'єкт patch
|
|
4996
|
+
* @param {string} dataKey ключ у `data` (наприклад `HASURA_GRAPHQL_ENABLED_APIS`)
|
|
4989
4997
|
* @returns {string | null} присвоєне значення (рядок) або null
|
|
4990
4998
|
*/
|
|
4991
|
-
function
|
|
4999
|
+
function hasuraDataKeyValueFromStrategicMerge(parsed, dataKey) {
|
|
4992
5000
|
const data = /** @type {Record<string, unknown>} */ (parsed).data
|
|
4993
5001
|
if (data === null || typeof data !== 'object' || Array.isArray(data)) return null
|
|
4994
5002
|
const d = /** @type {Record<string, unknown>} */ (data)
|
|
4995
|
-
if (!Object.hasOwn(d,
|
|
4996
|
-
const v = d
|
|
5003
|
+
if (!Object.hasOwn(d, dataKey)) return null
|
|
5004
|
+
const v = d[dataKey]
|
|
4997
5005
|
return typeof v === 'string' ? v : JSON.stringify(v)
|
|
4998
5006
|
}
|
|
4999
5007
|
|
|
5000
5008
|
/**
|
|
5001
|
-
* Значення, яке inline-`patch` присвоює `data
|
|
5002
|
-
* **JSON6902** (`op` add/replace на `/data
|
|
5003
|
-
*
|
|
5009
|
+
* Значення, яке inline-`patch` присвоює `data.<dataKey>`. Підтримка двох форматів:
|
|
5010
|
+
* **JSON6902** (`op` add/replace на `/data/<dataKey>`) і **Strategic Merge** (`data.<dataKey>`).
|
|
5011
|
+
* Зовнішні patch-файли (`patches[].path`) не охоплені — Plan B trade-off.
|
|
5004
5012
|
* @param {string} patchText вміст поля `patch`
|
|
5013
|
+
* @param {string} dataKey ключ у `data`
|
|
5014
|
+
* @param {string} dataPointer JSON-Pointer ключа (`/data/<dataKey>`)
|
|
5005
5015
|
* @returns {string | null} присвоєне значення (рядок) або null, якщо patch не чіпає цей ключ
|
|
5006
5016
|
*/
|
|
5007
|
-
|
|
5017
|
+
function hasuraDataKeyValueFromPatchText(patchText, dataKey, dataPointer) {
|
|
5008
5018
|
const t = typeof patchText === 'string' ? patchText.trim() : ''
|
|
5009
5019
|
if (t === '') return null
|
|
5010
5020
|
const parsed = firstValidYamlJsonFromPatchText(t)
|
|
5011
|
-
if (Array.isArray(parsed)) return
|
|
5021
|
+
if (Array.isArray(parsed)) return hasuraDataKeyValueFromJson6902(parsed, dataPointer)
|
|
5012
5022
|
if (parsed === null || typeof parsed !== 'object') return null
|
|
5013
|
-
return
|
|
5023
|
+
return hasuraDataKeyValueFromStrategicMerge(parsed, dataKey)
|
|
5014
5024
|
}
|
|
5015
5025
|
|
|
5016
5026
|
/**
|
|
5017
|
-
* Значення, яке `
|
|
5027
|
+
* Значення, яке inline-`patch` присвоює `data.HASURA_GRAPHQL_ENABLED_APIS`. Підтримка двох форматів:
|
|
5028
|
+
* **JSON6902** (`op` add/replace на `/data/HASURA_GRAPHQL_ENABLED_APIS`) і **Strategic Merge**
|
|
5029
|
+
* (`data.HASURA_GRAPHQL_ENABLED_APIS`). Зовнішні patch-файли (`patches[].path`) не охоплені — Plan B trade-off.
|
|
5030
|
+
* @param {string} patchText вміст поля `patch`
|
|
5031
|
+
* @returns {string | null} присвоєне значення (рядок) або null, якщо patch не чіпає цей ключ
|
|
5032
|
+
*/
|
|
5033
|
+
export function enabledApisValueFromPatchText(patchText) {
|
|
5034
|
+
return hasuraDataKeyValueFromPatchText(patchText, 'HASURA_GRAPHQL_ENABLED_APIS', HASURA_ENABLED_APIS_DATA_POINTER)
|
|
5035
|
+
}
|
|
5036
|
+
|
|
5037
|
+
/**
|
|
5038
|
+
* Значення, яке `patches[]` kustomization присвоюють `data.<dataKey>` на цілі **ConfigMap**.
|
|
5018
5039
|
* Повертає значення першого patch-а, що чіпає цей ключ, або null, якщо такого немає.
|
|
5019
5040
|
* @param {Record<string, unknown>} kust об'єкт kustomization.yaml
|
|
5041
|
+
* @param {string} dataKey ключ у `data`
|
|
5042
|
+
* @param {string} dataPointer JSON-Pointer ключа (`/data/<dataKey>`)
|
|
5020
5043
|
* @returns {string | null} присвоєне значення або null
|
|
5021
5044
|
*/
|
|
5022
|
-
|
|
5045
|
+
function hasuraDataKeyOverrideValue(kust, dataKey, dataPointer) {
|
|
5023
5046
|
const patches = kust.patches
|
|
5024
5047
|
if (!Array.isArray(patches)) return null
|
|
5025
5048
|
for (const p of patches) {
|
|
@@ -5027,12 +5050,32 @@ export function hasuraEnabledApisOverrideValue(kust) {
|
|
|
5027
5050
|
const pr = /** @type {Record<string, unknown>} */ (p)
|
|
5028
5051
|
if (typeof pr.patch !== 'string') continue
|
|
5029
5052
|
if (resolvePatchTargetKind(pr) !== 'ConfigMap') continue
|
|
5030
|
-
const v =
|
|
5053
|
+
const v = hasuraDataKeyValueFromPatchText(pr.patch, dataKey, dataPointer)
|
|
5031
5054
|
if (v !== null) return v
|
|
5032
5055
|
}
|
|
5033
5056
|
return null
|
|
5034
5057
|
}
|
|
5035
5058
|
|
|
5059
|
+
/**
|
|
5060
|
+
* Значення, яке `patches[]` kustomization присвоюють `data.HASURA_GRAPHQL_ENABLED_APIS` на цілі **ConfigMap**.
|
|
5061
|
+
* Повертає значення першого patch-а, що чіпає цей ключ, або null, якщо такого немає.
|
|
5062
|
+
* @param {Record<string, unknown>} kust об'єкт kustomization.yaml
|
|
5063
|
+
* @returns {string | null} присвоєне значення або null
|
|
5064
|
+
*/
|
|
5065
|
+
export function hasuraEnabledApisOverrideValue(kust) {
|
|
5066
|
+
return hasuraDataKeyOverrideValue(kust, 'HASURA_GRAPHQL_ENABLED_APIS', HASURA_ENABLED_APIS_DATA_POINTER)
|
|
5067
|
+
}
|
|
5068
|
+
|
|
5069
|
+
/**
|
|
5070
|
+
* Значення, яке `patches[]` kustomization присвоюють `data.HASURA_GRAPHQL_ENABLED_LOG_TYPES` на цілі **ConfigMap**.
|
|
5071
|
+
* Повертає значення першого patch-а, що чіпає цей ключ, або null, якщо такого немає.
|
|
5072
|
+
* @param {Record<string, unknown>} kust об'єкт kustomization.yaml
|
|
5073
|
+
* @returns {string | null} присвоєне значення або null
|
|
5074
|
+
*/
|
|
5075
|
+
export function hasuraEnabledLogTypesOverrideValue(kust) {
|
|
5076
|
+
return hasuraDataKeyOverrideValue(kust, 'HASURA_GRAPHQL_ENABLED_LOG_TYPES', HASURA_ENABLED_LOG_TYPES_DATA_POINTER)
|
|
5077
|
+
}
|
|
5078
|
+
|
|
5036
5079
|
/**
|
|
5037
5080
|
* Для кожного **non-base/dev** overlay `kustomization.yaml`, що успадковує Hasura-base (Deployment з
|
|
5038
5081
|
* `hasura/graphql-engine`), вимагає у `patches[]` перевизначення **`data.HASURA_GRAPHQL_ENABLED_APIS`**
|
|
@@ -5070,6 +5113,43 @@ async function validateHasuraOverlayEnabledApisOverride(root, yamlFilesAbs, fail
|
|
|
5070
5113
|
}
|
|
5071
5114
|
}
|
|
5072
5115
|
|
|
5116
|
+
/**
|
|
5117
|
+
* Для кожного **non-base/dev** overlay `kustomization.yaml`, що успадковує Hasura-base (Deployment з
|
|
5118
|
+
* `hasura/graphql-engine`), вимагає у `patches[]` перевизначення **`data.HASURA_GRAPHQL_ENABLED_LOG_TYPES`**
|
|
5119
|
+
* до **`"startup"`** (`http-log` лишається строго для base/dev — прод не пише per-request access-лог у
|
|
5120
|
+
* Cloud Logging). `kind: Component` пропускається (env-неутральне джерело, не overlay).
|
|
5121
|
+
* @param {string} root корінь репозиторію
|
|
5122
|
+
* @param {string[]} yamlFilesAbs yaml під k8s
|
|
5123
|
+
* @param {(msg: string) => void} fail callback при помилці
|
|
5124
|
+
* @param {(msg: string) => void} passFn callback при успіху
|
|
5125
|
+
*/
|
|
5126
|
+
async function validateHasuraOverlayEnabledLogTypesOverride(root, yamlFilesAbs, fail, passFn) {
|
|
5127
|
+
const rootNorm = resolve(root)
|
|
5128
|
+
const kustFiles = yamlFilesAbs.filter(abs => basename(abs) === 'kustomization.yaml')
|
|
5129
|
+
for (const kustAbs of kustFiles) {
|
|
5130
|
+
const rel = (relative(rootNorm, kustAbs) || kustAbs).replaceAll('\\', '/')
|
|
5131
|
+
const segment = k8sEnvSegmentFromRelPath(rel)
|
|
5132
|
+
if (segment === null || segment === 'base' || segment === 'dev') continue
|
|
5133
|
+
const kust = await readFirstYamlObject(kustAbs)
|
|
5134
|
+
if (kust === null || kust.kind === 'Component') continue
|
|
5135
|
+
if (!(await kustomizationTreeHasHasuraDeployment(kustAbs, rootNorm))) continue
|
|
5136
|
+
const value = hasuraEnabledLogTypesOverrideValue(kust)
|
|
5137
|
+
if (value === HASURA_OVERLAY_ENABLED_LOG_TYPES) {
|
|
5138
|
+
passFn(
|
|
5139
|
+
`${rel}: overlay '${segment}' перевизначає HASURA_GRAPHQL_ENABLED_LOG_TYPES="${HASURA_OVERLAY_ENABLED_LOG_TYPES}" (k8s.mdc)`
|
|
5140
|
+
)
|
|
5141
|
+
} else if (value === null) {
|
|
5142
|
+
fail(
|
|
5143
|
+
`${rel}: overlay '${segment}' має у patches[] перевизначати data.HASURA_GRAPHQL_ENABLED_LOG_TYPES до "${HASURA_OVERLAY_ENABLED_LOG_TYPES}" (http-log лише для base/dev) (k8s.mdc)`
|
|
5144
|
+
)
|
|
5145
|
+
} else {
|
|
5146
|
+
fail(
|
|
5147
|
+
`${rel}: overlay '${segment}' patch data.HASURA_GRAPHQL_ENABLED_LOG_TYPES має бути "${HASURA_OVERLAY_ENABLED_LOG_TYPES}" (зараз: ${JSON.stringify(value)}) (k8s.mdc)`
|
|
5148
|
+
)
|
|
5149
|
+
}
|
|
5150
|
+
}
|
|
5151
|
+
}
|
|
5152
|
+
|
|
5073
5153
|
/**
|
|
5074
5154
|
* Шукає HPA за `scaleTargetRef.name` серед документів.
|
|
5075
5155
|
* @param {Record<string, unknown>[]} hpaDocs масив HPA-документів
|
|
@@ -6658,6 +6738,8 @@ export async function lint(ctx) {
|
|
|
6658
6738
|
|
|
6659
6739
|
await validateHasuraOverlayEnabledApisOverride(root, yamlFiles, fail, pass)
|
|
6660
6740
|
|
|
6741
|
+
await validateHasuraOverlayEnabledLogTypesOverride(root, yamlFiles, fail, pass)
|
|
6742
|
+
|
|
6661
6743
|
return reporter.result()
|
|
6662
6744
|
}
|
|
6663
6745
|
|