@nitra/cursor 3.2.1 → 3.2.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 +16 -0
- package/package.json +1 -1
- package/rules/k8s/js/manifests.mjs +33 -7
- package/rules/k8s/k8s.mdc +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [3.2.3] - 2026-06-01
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- k8s `workloadAppLabel`: CronJob/workload без `spec` (чи `spec: null`) повертає `null` замість TypeError — `check k8s` більше не падає на неповному маніфесті
|
|
8
|
+
|
|
9
|
+
## [3.2.2] - 2026-06-01
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- js-lint: додано e18e/\* deny-правила та канонічні ignorePatterns у .oxlintrc.json
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- k8s NetworkPolicy: мітку `app` для Job беремо з `spec.template.metadata.labels.app`, для CronJob — з `spec.jobTemplate.spec.template.metadata.labels.app` (ручний `spec.selector` у Job/CronJob невалідний без `manualSelector: true`)
|
|
18
|
+
|
|
3
19
|
## [3.2.1] - 2026-06-01
|
|
4
20
|
|
|
5
21
|
### Fixed
|
package/package.json
CHANGED
|
@@ -4009,23 +4009,49 @@ function appLabelFromSpecSelector(spec) {
|
|
|
4009
4009
|
return typeof app === 'string' && app.trim() !== '' ? app : null
|
|
4010
4010
|
}
|
|
4011
4011
|
|
|
4012
|
+
/**
|
|
4013
|
+
* Витягує мітку `app` з `spec.template.metadata.labels.app` (pod-template labels).
|
|
4014
|
+
*
|
|
4015
|
+
* Джерело для Job і CronJob: у Job/CronJob **не можна** задавати ручний `spec.selector`
|
|
4016
|
+
* без `manualSelector: true` — apiserver сам генерує селектор з `controller-uid`, тож
|
|
4017
|
+
* `spec.selector.matchLabels.app` там невалідне джерело. Pod-template labels — валідне
|
|
4018
|
+
* й завжди присутнє поле.
|
|
4019
|
+
* @param {Record<string, unknown>} spec об'єкт `spec` (Job — `spec`, CronJob — `jobTemplate.spec`)
|
|
4020
|
+
* @returns {string | null} непорожнє значення `app` або null
|
|
4021
|
+
*/
|
|
4022
|
+
function appLabelFromPodTemplate(spec) {
|
|
4023
|
+
const template = getNestedObject(spec, 'template')
|
|
4024
|
+
if (template === null) return null
|
|
4025
|
+
const metadata = getNestedObject(template, 'metadata')
|
|
4026
|
+
if (metadata === null) return null
|
|
4027
|
+
const labels = getNestedObject(metadata, 'labels')
|
|
4028
|
+
if (labels === null) return null
|
|
4029
|
+
const app = labels.app
|
|
4030
|
+
return typeof app === 'string' && app.trim() !== '' ? app : null
|
|
4031
|
+
}
|
|
4032
|
+
|
|
4012
4033
|
/**
|
|
4013
4034
|
* Витягує мітку `app` для workload, для якого потрібен NetworkPolicy.
|
|
4014
|
-
* Deployment / StatefulSet / DaemonSet
|
|
4015
|
-
*
|
|
4035
|
+
* Deployment / StatefulSet / DaemonSet — `spec.selector.matchLabels.app`;
|
|
4036
|
+
* Job — `spec.template.metadata.labels.app`;
|
|
4037
|
+
* CronJob — `spec.jobTemplate.spec.template.metadata.labels.app`.
|
|
4038
|
+
*
|
|
4039
|
+
* Job і CronJob читаються з pod-template labels, бо ручний `spec.selector` у них невалідний
|
|
4040
|
+
* без `manualSelector: true` (селектор генерує контролер). Див. `appLabelFromPodTemplate`.
|
|
4016
4041
|
* @param {Record<string, unknown>} manifest AST workload
|
|
4017
4042
|
* @returns {string | null} непорожнє значення `app` або null
|
|
4018
4043
|
*/
|
|
4019
4044
|
export function workloadAppLabel(manifest) {
|
|
4020
4045
|
const kind = manifest.kind
|
|
4021
4046
|
if (typeof kind !== 'string') return null
|
|
4047
|
+
const spec = getNestedObject(manifest, 'spec')
|
|
4048
|
+
if (spec === null) return null
|
|
4022
4049
|
if (kind === 'CronJob') {
|
|
4023
|
-
const jobTemplate = getNestedObject(
|
|
4050
|
+
const jobTemplate = getNestedObject(spec, 'jobTemplate')
|
|
4024
4051
|
const jobSpec = jobTemplate === null ? null : getNestedObject(jobTemplate, 'spec')
|
|
4025
|
-
return jobSpec === null ? null :
|
|
4052
|
+
return jobSpec === null ? null : appLabelFromPodTemplate(jobSpec)
|
|
4026
4053
|
}
|
|
4027
|
-
|
|
4028
|
-
if (spec === null) return null
|
|
4054
|
+
if (kind === 'Job') return appLabelFromPodTemplate(spec)
|
|
4029
4055
|
return appLabelFromSpecSelector(spec)
|
|
4030
4056
|
}
|
|
4031
4057
|
|
|
@@ -5631,7 +5657,7 @@ async function validateNetworkPoliciesForK8sWorkloads(root, yamlFilesAbs, fail,
|
|
|
5631
5657
|
}
|
|
5632
5658
|
if (appLabel === null) {
|
|
5633
5659
|
fail(
|
|
5634
|
-
`${deployRel}: ${workloadKind} '${workloadName}' без мітки app
|
|
5660
|
+
`${deployRel}: ${workloadKind} '${workloadName}' без мітки app (spec.selector.matchLabels.app; Job — spec.template.metadata.labels.app; CronJob — spec.jobTemplate.spec.template.metadata.labels.app) (k8s.mdc)`
|
|
5635
5661
|
)
|
|
5636
5662
|
continue
|
|
5637
5663
|
}
|
package/rules/k8s/k8s.mdc
CHANGED
|
@@ -385,7 +385,7 @@ images:
|
|
|
385
385
|
|
|
386
386
|
Для **кожного** `kind: Deployment` у каталозі **`…/k8s/…/base/`** (у будь-якому файлі `.yaml`, наприклад **`deploy.yaml`**, **`deployment.yaml`**) сам Deployment має канонічні **`spec.template.spec.topologySpreadConstraints`**, а **HPA і PDB** живуть у **sibling каталозі** **`…/k8s/…/components/`** (Kustomize Component, фіксована назва каталогу — `components`). У `base/` локальні `hpa.yaml` і `pdb.yaml` **заборонені** (file-existence error). У дереві base-kustomize HPA / PDB також **не дозволені** через `resources` / `components` / `bases`.
|
|
387
387
|
|
|
388
|
-
**NetworkPolicy** — інша історія: оскільки обмеження мережі мають діяти **і на dev**, NP лежить **у `base/`** (а не в `components/`). Для **кожного** з **`Deployment`**, **`StatefulSet`**, **`DaemonSet`**, **`Job`**, **`CronJob`** під `k8s` обов'язковий **NetworkPolicy**: у **`…/k8s/…/base/`** — у **`base/networkpolicy.yaml`** поруч з workload-маніфестом (multi-doc, якщо workload-ів кілька); у **не-base** — **`networkpolicy.yaml`** поруч із маніфестом workload у тому ж каталозі (overlay-specific override). `metadata.name` NetworkPolicy **= `metadata.name`** workload; `spec.podSelector.matchLabels.app` **= мітка `app`** з `spec.selector.matchLabels` (для **CronJob** — з `spec.jobTemplate.spec.
|
|
388
|
+
**NetworkPolicy** — інша історія: оскільки обмеження мережі мають діяти **і на dev**, NP лежить **у `base/`** (а не в `components/`). Для **кожного** з **`Deployment`**, **`StatefulSet`**, **`DaemonSet`**, **`Job`**, **`CronJob`** під `k8s` обов'язковий **NetworkPolicy**: у **`…/k8s/…/base/`** — у **`base/networkpolicy.yaml`** поруч з workload-маніфестом (multi-doc, якщо workload-ів кілька); у **не-base** — **`networkpolicy.yaml`** поруч із маніфестом workload у тому ж каталозі (overlay-specific override). `metadata.name` NetworkPolicy **= `metadata.name`** workload; `spec.podSelector.matchLabels.app` **= мітка `app`** з `spec.selector.matchLabels` (для **Job** — з `spec.template.metadata.labels.app`, для **CronJob** — з `spec.jobTemplate.spec.template.metadata.labels.app`; у Job/CronJob ручний `spec.selector` невалідний без `manualSelector: true`, тож джерело — pod-template labels). У `base/kustomization.yaml` `resources:` має бути `networkpolicy.yaml`. Відсутні документи **`check k8s`** створює автоматично і додає `networkpolicy.yaml` у `base/kustomization.yaml` `resources:`.
|
|
389
389
|
|
|
390
390
|
**Канонічна структура `<pkg>/k8s/components/`** (sibling до `base/`) — лише HPA і PDB:
|
|
391
391
|
|