@nitra/cursor 1.9.17 → 1.9.19
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 +39 -0
- package/bin/auto-skills.md +2 -0
- package/mdc/abie.mdc +21 -249
- package/mdc/docker.mdc +2 -19
- package/mdc/hasura.mdc +1 -1
- package/mdc/k8s.mdc +2 -2
- package/package.json +1 -1
- package/policy/abie/base_deployment_preem/base_deployment_preem.rego +2 -2
- package/policy/abie/clean_merged_ignore_branches/clean_merged_ignore_branches.rego +2 -2
- package/policy/abie/clean_merged_ignore_branches/clean_merged_ignore_branches_test.rego +5 -5
- package/policy/docker/lint_docker_yml/lint_docker_yml.rego +91 -0
- package/policy/docker/lint_docker_yml/lint_docker_yml_test.rego +104 -0
- package/policy/docker/package_json/package_json.rego +35 -0
- package/policy/docker/package_json/package_json_test.rego +42 -0
- package/scripts/check-abie.mjs +73 -933
- package/scripts/check-hasura.mjs +8 -14
- package/scripts/check-k8s.mjs +1 -18
- package/scripts/lint-conftest.mjs +10 -1
- package/skills/abie-clean/SKILL.md +138 -0
- package/skills/abie-kustomize/SKILL.md +1 -1
package/scripts/check-hasura.mjs
CHANGED
|
@@ -7,11 +7,9 @@
|
|
|
7
7
|
* вказує на `https://github.com/nitra/...` або `https://github.com/abinbevefes/...`
|
|
8
8
|
* (інші репозиторії пропускаються без помилок — як у check-abie).
|
|
9
9
|
*
|
|
10
|
-
* Очікуваний формат URL —
|
|
10
|
+
* Очікуваний формат URL — кластерний DNS-суфікс `<cluster>.internal`:
|
|
11
11
|
* - GKE / GCP: `http://<service>.<namespace>.svc.<cluster>.internal:<port>`
|
|
12
12
|
* приклад: `http://contract-h.ua-contract.svc.abie-ua.internal:8080`
|
|
13
|
-
* - стандартний k8s / Yandex Cloud: `http://<service>.<namespace>.svc.cluster.local:<port>`
|
|
14
|
-
* приклад: `http://apruv-h-hl.ru-apruv.svc.cluster.local:8080`
|
|
15
13
|
*
|
|
16
14
|
* Сегменти беруться з `hasura/k8s/base/svc-hl.yaml` (`metadata.name` —
|
|
17
15
|
* має закінчуватись на `-h`, headless-сервіс) і `hasura/k8s/base/namespace.yaml`
|
|
@@ -43,18 +41,15 @@ const HASURA_NAMESPACE_FILE = `${HASURA_BASE_DIR}/namespace.yaml`
|
|
|
43
41
|
|
|
44
42
|
const ENV_FILE_RE = /\.env$/u
|
|
45
43
|
const HASURA_ENDPOINT_LINE_RE = /^[ \t]*(?:export[ \t]+)?HASURA_GRAPHQL_ENDPOINT[ \t]*=[ \t]*['"]?([^'"\r\n#]+)/mu
|
|
46
|
-
// Дозволяємо
|
|
47
|
-
|
|
48
|
-
const INTERNAL_HASURA_URL_RE = /^http:\/\/([^./]+)\.([^./]+)\.svc\.((?:[^./:]+\.internal)|cluster\.local):(\d+)\/?$/u
|
|
44
|
+
// Дозволяємо лише DNS-суфікс кластера `<name>.internal` (GKE/GCP).
|
|
45
|
+
const INTERNAL_HASURA_URL_RE = /^http:\/\/([^./]+)\.([^./]+)\.svc\.([^./:]+\.internal):(\d+)\/?$/u
|
|
49
46
|
const INTERNAL_DNS_SUFFIX = '.internal'
|
|
50
47
|
|
|
51
48
|
/**
|
|
52
49
|
* Розбір значення `HASURA_GRAPHQL_ENDPOINT` як внутрішнього кластерного URL.
|
|
53
|
-
* Дозволяє лише `http://` (TLS усередині кластера зайвий) та
|
|
54
|
-
*
|
|
55
|
-
* (
|
|
56
|
-
* кластера без `.internal` (наприклад `abie-ua`); для YC — повний суфікс
|
|
57
|
-
* `cluster.local` (бо своєї «назви кластера» в DNS немає).
|
|
50
|
+
* Дозволяє лише `http://` (TLS усередині кластера зайвий) та DNS-суфікс
|
|
51
|
+
* `<cluster>.internal` (GKE/GCP). Поле `cluster` містить ім'я кластера без
|
|
52
|
+
* `.internal` (наприклад `abie-ua`).
|
|
58
53
|
* @param {string} url значення з `.env` (без огорнутих лапок)
|
|
59
54
|
* @returns {{ ok: true, service: string, namespace: string, cluster: string, port: string } | { ok: false }}
|
|
60
55
|
* розібрані сегменти або `{ ok: false }`, якщо формат не відповідає внутрішньому кластерному URL
|
|
@@ -65,7 +60,7 @@ export function parseInternalHasuraEndpoint(url) {
|
|
|
65
60
|
return { ok: false }
|
|
66
61
|
}
|
|
67
62
|
const suffix = m[3]
|
|
68
|
-
const cluster = suffix.
|
|
63
|
+
const cluster = suffix.slice(0, -INTERNAL_DNS_SUFFIX.length)
|
|
69
64
|
return { ok: true, service: m[1], namespace: m[2], cluster, port: m[4] }
|
|
70
65
|
}
|
|
71
66
|
|
|
@@ -148,8 +143,7 @@ async function checkEnvFile(relPath, expected, reporter) {
|
|
|
148
143
|
const value = m[1].trim()
|
|
149
144
|
const parsed = parseInternalHasuraEndpoint(value)
|
|
150
145
|
if (!parsed.ok) {
|
|
151
|
-
const example =
|
|
152
|
-
'https://<service>.<namespace>.svc.<cluster>.internal:<port> або http://<service>.<namespace>.svc.cluster.local:<port>'
|
|
146
|
+
const example = 'http://<service>.<namespace>.svc.<cluster>.internal:<port>'
|
|
153
147
|
fail(
|
|
154
148
|
`${relPath}: HASURA_GRAPHQL_ENDPOINT="${value}" — потрібен внутрішній кластерний URL виду ${example} (hasura.mdc)`
|
|
155
149
|
)
|
package/scripts/check-k8s.mjs
CHANGED
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
* `hpa.yaml` і `pdb.yaml` (як єдині або принаймні обов'язкові), `hpa.yaml` (валідний `autoscaling/v2`
|
|
98
98
|
* HorizontalPodAutoscaler з `scaleTargetRef.name` = ім'я Deployment, dev-like `min=max=1`), `pdb.yaml` (валідний
|
|
99
99
|
* `policy/v1` PodDisruptionBudget з `selector.matchLabels.app` = мітка `app` Deployment, dev-like `minAvailable=0`).
|
|
100
|
-
* Overlays (`ua/`,
|
|
100
|
+
* Overlays (`ua/`, прод-overlays) підключають `components: [- ../components]` і додають JSON6902-патчі для
|
|
101
101
|
* прод-значень: `/spec/minReplicas`, `/spec/maxReplicas` (HPA), `/spec/minAvailable` (PDB). HPA поруч із Deployment
|
|
102
102
|
* у не-base оверлеях — як раніше (див. k8s.mdc).
|
|
103
103
|
* Env-залежні межі за сегментом після `/k8s/`: **dev-like** (`base`, `dev`, `*-qa`) — для HPA, що лишився після
|
|
@@ -324,10 +324,6 @@ const API_VERSION_FIELD_RE = /^\s*apiVersion:\s*(\S+)\s*$/
|
|
|
324
324
|
const KIND_FIELD_RE = /^\s*kind:\s*(\S+)\s*$/
|
|
325
325
|
const TYPE_FIELD_RE = /^\s*type:\s*(\S+)\s*$/
|
|
326
326
|
const YAML_DOC_SEPARATOR_LINE_RE = /^---\s*$/
|
|
327
|
-
const HEALTHCHECK_DELETE_RE = /\$patch:\s*delete/u
|
|
328
|
-
const HEALTHCHECK_KIND_RE = /kind:\s*HealthCheckPolicy/u
|
|
329
|
-
const METADATA_LINE_RE = /metadata:/u
|
|
330
|
-
const NAME_NON_EMPTY_RE = /name:\s*\S+/u
|
|
331
327
|
const K8S_BASE_KUSTOMIZATION_PATH_RE = /(^|\/)k8s\/base\/kustomization\.yaml$/u
|
|
332
328
|
const K8S_BASE_SEGMENT_RE = /(^|\/)k8s\/base\//u
|
|
333
329
|
const OXLINT_SCHEMA_MODELINE_RE = /^\s*#\s*yaml-language-server:\s*\$schema=\S+/u
|
|
@@ -2025,19 +2021,6 @@ export function k8sYamlFirstDocIsAlbYcHttpBackendGroup(yamlBody) {
|
|
|
2025
2021
|
return apiVersion === 'alb.yc.io/v1alpha1' && kind === 'HttpBackendGroup'
|
|
2026
2022
|
}
|
|
2027
2023
|
|
|
2028
|
-
/**
|
|
2029
|
-
* Чи вміст overlay **`ru/kustomization.yaml`** містить Kustomize patch видалення **HealthCheckPolicy**.
|
|
2030
|
-
* @param {string} raw повний текст файлу
|
|
2031
|
-
* @returns {boolean} true, якщо є `$patch: delete` і блоки kind/metadata для HealthCheckPolicy
|
|
2032
|
-
*/
|
|
2033
|
-
export function ruKustomizationHasHealthCheckDeletePatch(raw) {
|
|
2034
|
-
if (!HEALTHCHECK_DELETE_RE.test(raw)) return false
|
|
2035
|
-
if (!HEALTHCHECK_KIND_RE.test(raw)) return false
|
|
2036
|
-
if (!METADATA_LINE_RE.test(raw)) return false
|
|
2037
|
-
if (!NAME_NON_EMPTY_RE.test(raw)) return false
|
|
2038
|
-
return true
|
|
2039
|
-
}
|
|
2040
|
-
|
|
2041
2024
|
/**
|
|
2042
2025
|
* Чи абсолютний шлях лежить усередині кореня репозиторію (без виходу через `..`).
|
|
2043
2026
|
* @param {string} rootAbs абсолютний корінь
|
|
@@ -136,6 +136,15 @@ const TARGETS = [
|
|
|
136
136
|
single: '.github/workflows/lint-php.yml'
|
|
137
137
|
},
|
|
138
138
|
|
|
139
|
+
// ── docker ──────────────────────────────────────────────────────────────
|
|
140
|
+
{ namespace: 'docker.package_json', policyDir: 'docker', rule: 'docker', single: 'package.json' },
|
|
141
|
+
{
|
|
142
|
+
namespace: 'docker.lint_docker_yml',
|
|
143
|
+
policyDir: 'docker',
|
|
144
|
+
rule: 'docker',
|
|
145
|
+
single: '.github/workflows/lint-docker.yml'
|
|
146
|
+
},
|
|
147
|
+
|
|
139
148
|
// ── npm-module ──────────────────────────────────────────────────────────
|
|
140
149
|
{
|
|
141
150
|
namespace: 'npm_module.root_package_json',
|
|
@@ -354,7 +363,7 @@ const TARGETS = [
|
|
|
354
363
|
}
|
|
355
364
|
},
|
|
356
365
|
|
|
357
|
-
// abie clean-merged-branch.yml: with.ignore_branches має містити dev/ua
|
|
366
|
+
// abie clean-merged-branch.yml: with.ignore_branches має містити dev/ua.
|
|
358
367
|
{
|
|
359
368
|
namespace: 'abie.clean_merged_ignore_branches',
|
|
360
369
|
policyDir: 'abie/clean_merged_ignore_branches',
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: n-abie-clean
|
|
3
|
+
description: >-
|
|
4
|
+
Очистка проєкту від ru-середовища: гілка `ru`, директорії `ru/`, файли з суфіксом
|
|
5
|
+
`-ru`/`values-ru.*`, гілки `endsWith(...'ru')` у GitHub Actions, ru-умови у
|
|
6
|
+
Dockerfile/nginx, посилання на `cr.yandex` та раннер `ya`
|
|
7
|
+
version: '1.1'
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Скіл прибирає з проєкту все, що належить **ru-середовищу**. Залишаються тільки `dev` (як база) та `ua` як активне продакшн-середовище. Працюй послідовно по секціях нижче — після кожної секції перевіряй, що проєкт лишається консистентним (`kustomization.yaml` посилається лише на наявні файли, GitHub Actions-вирази синтаксично коректні).
|
|
11
|
+
|
|
12
|
+
## 1. Директорії з назвою `ru`
|
|
13
|
+
|
|
14
|
+
Видали всі директорії з назвою `ru` у проєкті:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
find . -type d -name "ru" -exec rm -rf {} +
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Це чистить як `country/ru/`, так і `k8s/<...>/ru/` (overlay у kustomize). Після видалення overlay `ru/` обов’язково прибери відповідний запис у `resources:` у батьківському `kustomization.yaml`, якщо він там лишився.
|
|
21
|
+
|
|
22
|
+
## 2. Файли з ru-суфіксом
|
|
23
|
+
|
|
24
|
+
Видали файли, у назві яких є явний ru-маркер:
|
|
25
|
+
|
|
26
|
+
- `values-ru.ini`, `values-ru.yaml`, `values-ru.*` (Helm/абстракції values на середовище)
|
|
27
|
+
- будь-які файли, що закінчуються на `-ru` або `-ru.<ext>`, наприклад `site/.env.prod-ru`, `*.env.prod-ru`, `*.prod-ru.conf`
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
find . -type f \( -name "values-ru.*" -o -name "*-ru" -o -name "*.prod-ru" -o -name "*.prod-ru.*" \) -delete
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## 3. `.github/workflows/*.yml`
|
|
34
|
+
|
|
35
|
+
### 3.1. Тригери `on.push.branches`
|
|
36
|
+
|
|
37
|
+
Прибирай `ru` зі списку гілок.
|
|
38
|
+
|
|
39
|
+
Було:
|
|
40
|
+
|
|
41
|
+
```yaml
|
|
42
|
+
on:
|
|
43
|
+
push:
|
|
44
|
+
branches: [dev, ru, ua]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Стало:
|
|
48
|
+
|
|
49
|
+
```yaml
|
|
50
|
+
on:
|
|
51
|
+
push:
|
|
52
|
+
branches: [dev, ua]
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### 3.2. Тернарні вирази `endsWith(github.ref_name, …)`
|
|
56
|
+
|
|
57
|
+
У ланцюжках `endsWith(...)` залишай тільки гілки `dev` та `ua`. Гілку `ru` (а також пов’язаний з нею fallback на раннер `ya`, реєстр `cr.yandex/...`, NATS `cluster.local` тощо) — прибирай. Останнє значення в ланцюжку стає fallback’ом для всього, що не `dev`.
|
|
58
|
+
|
|
59
|
+
`runs-on` — було:
|
|
60
|
+
|
|
61
|
+
```yaml
|
|
62
|
+
runs-on: ${{ endsWith(github.ref_name, 'dev') && 'dev' || ( endsWith(github.ref_name, 'ua') && 'ua' || 'ya' ) }}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Стало:
|
|
66
|
+
|
|
67
|
+
```yaml
|
|
68
|
+
runs-on: ${{ endsWith(github.ref_name, 'dev') && 'dev' || 'ua' }}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`NATS_URL` — було:
|
|
72
|
+
|
|
73
|
+
```yaml
|
|
74
|
+
NATS_URL: ${{ endsWith(github.ref_name, 'dev') && 'nats.nats.svc.abie-dev.internal:4222' || ( endsWith(github.ref_name, 'ua') && 'nats.nats.svc.abie-ua.internal:4222' || 'nats.nats.svc.cluster.local:4222' ) }}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Стало:
|
|
78
|
+
|
|
79
|
+
```yaml
|
|
80
|
+
NATS_URL: ${{ endsWith(github.ref_name, 'dev') && 'nats.nats.svc.abie-dev.internal:4222' || 'nats.nats.svc.abie-ua.internal:4222' }}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
`NATS_STREAM` — було:
|
|
84
|
+
|
|
85
|
+
```yaml
|
|
86
|
+
NATS_STREAM: ${{ endsWith(github.ref_name, 'dev') && 'dev' || ( endsWith(github.ref_name, 'ua') && 'ua' || 'ru' ) }}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Стало:
|
|
90
|
+
|
|
91
|
+
```yaml
|
|
92
|
+
NATS_STREAM: ${{ endsWith(github.ref_name, 'dev') && 'dev' || 'ua' }}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
`REGISTRY` — було:
|
|
96
|
+
|
|
97
|
+
```yaml
|
|
98
|
+
REGISTRY: ${{ endsWith(github.ref_name, 'ru') && 'cr.yandex/crpaerfcq9t16fse5onm' || ( endsWith(github.ref_name, 'ua') && 'europe-west4-docker.pkg.dev/abie-ua/c' || 'europe-north1-docker.pkg.dev/abie-dev/c' ) }}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Стало:
|
|
102
|
+
|
|
103
|
+
```yaml
|
|
104
|
+
REGISTRY: ${{ endsWith(github.ref_name, 'ua') && 'europe-west4-docker.pkg.dev/abie-ua/c' || 'europe-north1-docker.pkg.dev/abie-dev/c' }}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Загальне правило: у фінальному виразі мають лишитися лише `endsWith(github.ref_name, 'dev')` та `endsWith(github.ref_name, 'ua')` (або лише один із них, якщо середовище одне). Будь-яка згадка `'ru'`, `'ya'`, `cr.yandex`, `cluster.local`-fallback для ru — прибирається.
|
|
108
|
+
|
|
109
|
+
### 3.3. `ignore_branches` / `branches-ignore`
|
|
110
|
+
|
|
111
|
+
У всіх workflow-файлах та конфігах (включно з тими, що використовуються правилом **abie** `clean_merged_ignore_branches`) прибирай `ru` зі списків ignore-гілок.
|
|
112
|
+
|
|
113
|
+
## 4. Dockerfile / nginx / build-скрипти
|
|
114
|
+
|
|
115
|
+
Прибирай умовні гілки `if [ "$BRANCH" = "ru" ]; then …` та копіювання `country/ru/*`. Лишається лише той код, що працює для `dev`/`ua`.
|
|
116
|
+
|
|
117
|
+
Було:
|
|
118
|
+
|
|
119
|
+
```dockerfile
|
|
120
|
+
RUN if [ "$BRANCH" = "ru" ]; then cp -r country/ru/* public/ || true; fi && \
|
|
121
|
+
bun install && \
|
|
122
|
+
if [ "$BRANCH" = "ru" ]; then BASE="/itool/"; else BASE="/contract/"; fi && \
|
|
123
|
+
bun vite build --mode "prod-$BRANCH" --base="$BASE"
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Стало:
|
|
127
|
+
|
|
128
|
+
```dockerfile
|
|
129
|
+
RUN bun install && bun vite build --mode "prod-$BRANCH" --base="$BASE"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Те саме стосується `nginx`-конфігів (`server_name`, `proxy_pass` з ru-доменами), `*.sh`-скриптів та `package.json` scripts (`build:ru`, `deploy:ru`, `prod-ru` тощо).
|
|
133
|
+
|
|
134
|
+
## 5. Після очистки
|
|
135
|
+
|
|
136
|
+
- Переконайся, що `kustomization.yaml` у кожній директорії `k8s/` не посилається на видалені overlay або файли.
|
|
137
|
+
- Пройдись `git grep` по репозиторію на залишки: `git grep -n -i -e '\bru\b' -e cr\.yandex -e country/ru -e prod-ru -e values-ru -e "'ya'"` — переглянь усі знахідки вручну, бо `ru` як слово може траплятися в легітимних контекстах (наприклад, `truncate`, `Aurum`, `cruft`). Видаляй лише ті входження, що належать ru-середовищу.
|
|
138
|
+
- Перевір CI локально: `npx @nitra/cursor check abie` (якщо правило **abie** ввімкнене у проєкті).
|
|
@@ -27,7 +27,7 @@ README має бути в директорії **k8s**.
|
|
|
27
27
|
|
|
28
28
|
Застарілі файли прибирай.
|
|
29
29
|
|
|
30
|
-
Для
|
|
30
|
+
Для overlay **ua** `namespace` задавай у `kustomization.yaml` (без окремих patch лише на зміну namespace). Деталі — **n-k8s** / **abie** у `.cursor/rules/`, якщо ці правила увімкнені в проєкті.
|
|
31
31
|
|
|
32
32
|
## Виключення: CNPG `Cluster`
|
|
33
33
|
|