@nitra/cursor 1.9.18 → 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 +21 -0
- package/bin/auto-skills.md +2 -0
- package/mdc/abie.mdc +21 -249
- 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/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 +1 -1
- package/skills/abie-clean/SKILL.md +138 -0
- package/skills/abie-kustomize/SKILL.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,27 @@
|
|
|
4
4
|
|
|
5
5
|
Формат — [Keep a Changelog](https://keepachangelog.com/uk/1.1.0/), нумерація — [SemVer](https://semver.org/lang/uk/).
|
|
6
6
|
|
|
7
|
+
## [1.9.19] - 2026-05-14
|
|
8
|
+
|
|
9
|
+
### Removed
|
|
10
|
+
|
|
11
|
+
- **`abie.mdc` (`1.19 → 1.20`) — повністю прибрано підтримку `ru`-overlay:** видалено секції «overlay **ru** і nginx-sidecar для WebSocket (Hasura)», «overlay **ru** і **Service** (headless → NodePort)», «overlay **ru** і HealthCheckPolicy»; з секцій «HTTPRoute (ua / ru)», «nodeSelector (overlay)», «env-файли», «Git branches» видалено `ru`-гілку. Залишається лише `dev` + `ua`. Таблиця env-файлів — без `ru.env` / `cluster.local` / YC. У workflow `clean-merged-branch.yml` обов'язкові токени `ignore_branches`: `dev,ua` (раніше `dev,ua,ru`).
|
|
12
|
+
- **`check-abie.mjs` — drop ru-логіки:** видалено всі функції з суфіксом / префіксом `Ru` (`isRuKustomizationPath`, `serviceDocumentRequiresAbieRuNodePortOverlay`, `ensureRuKustomizationHealthCheckDelete`, `ensureRuAbieServiceNodePortPatches`, `ensureAbieNginxSidecarForHasura` + усі допоміжні), regex / константи для `ru` overlay (`PATCH_PARENT_REF_NS_RU_RE`, `WEBSOCKET_ANNOTATION_RE`, `REMOVE_CLUSTER_IP*_RE`, `HASURA_IMAGE_MARKER`, `NGINX_SIDECAR_*`, `ABIE_RU_HTTPROUTE_HOST_MARKERS`, `HASURA_JWT_SECRET_IN_KUSTOMIZATION`). Перейменування: `ensureUaRuAbieNodeSelectorPatches` → `ensureUaAbieNodeSelectorPatches`, `ensureUaRuAbieHttpRoutePatches` → `ensureUaAbieHttpRoutePatches`. Тип `mode` — лише `'ua'`. Файл скоротився з ≈2013 до ≈880 рядків.
|
|
13
|
+
- **`check-k8s.mjs` — drop `ruKustomizationHasHealthCheckDeletePatch`:** export видалено разом з допоміжними regex; решта k8s-логіки без змін.
|
|
14
|
+
- **`check-hasura.mjs` — only `<cluster>.internal`:** `INTERNAL_HASURA_URL_RE` більше не приймає `cluster.local`; повідомлення про помилку згадує лише GKE-формат.
|
|
15
|
+
- **Rego — `abie.clean_merged_ignore_branches`:** `required_branches := {"dev", "ua"}` (раніше `{"dev", "ua", "ru"}`); тести оновлено.
|
|
16
|
+
- **`abie.base_deployment_preem` rego — коментар:** «Overlays (ua/ru)» → «Overlay ua».
|
|
17
|
+
- **`.cspell.json`:** зі списку слів прибрано `napitkivmeste` та `выбирайонлайн` (мову `ru-ru` у `language` залишено для коректного спелл-чеку коментарів/документації).
|
|
18
|
+
- **`k8s.mdc` приклади:** у переліку overlays залишилось `ua/`, `prod/` без `ru/`.
|
|
19
|
+
- **`hasura.mdc` / `tests/check-hasura.test.mjs`:** приклад "неправильного" публічного домену змінено з `napitkivmeste.tech` на `vybeerai.com.ua`.
|
|
20
|
+
|
|
21
|
+
### Tests
|
|
22
|
+
|
|
23
|
+
- **`tests/check-abie.test.mjs` — переписано (1210 → ≈480 рядків):** видалено всі тести `ru`-overlay (NodePort Service, HealthCheckPolicy delete, nginx-sidecar, websocket annotation, `ru-apruv` env-URL, ru parentRef regex). Залишено dev/ua сценарії.
|
|
24
|
+
- **`tests/check-hasura.test.mjs`:** видалено 2 тести на `cluster.local` / `ru-apruv`.
|
|
25
|
+
- **`tests/check-k8s-schema.test.mjs`:** видалено `describe('ruKustomizationHasHealthCheckDeletePatch')` і `isDevLikeK8sEnvSegment('ru')` assertion.
|
|
26
|
+
- **`tests/check-k8s-images.test.mjs`:** ASCII-збіг `ru: "true"` як ім'я label у фікстурі перейменовано на `preem: "false"`.
|
|
27
|
+
|
|
7
28
|
## [1.9.18] - 2026-05-13
|
|
8
29
|
|
|
9
30
|
### Changed
|
package/bin/auto-skills.md
CHANGED
package/mdc/abie.mdc
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: Правила для проєктів AbInBev Efes
|
|
3
3
|
alwaysApply: true
|
|
4
|
-
version: '1.
|
|
4
|
+
version: '1.20'
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Правило **abie** для споживачів **@nitra/cursor**: **k8s** (Deployment + **HealthCheckPolicy** у **`hc.yaml`**, overlay **ua**
|
|
7
|
+
Правило **abie** для споживачів **@nitra/cursor**: **k8s** (Deployment + **HealthCheckPolicy** у **`hc.yaml`**, overlay **ua** — **nodeSelector**, **HTTPRoute** (будь-який непорожній **`target.name`**, для спільних сервісів **`auth-run-hl`** / **`file-link-hl`** — **`namespace: dev`** у base та patch **`…/backendRefs/…/namespace`** у **ua**)), гілки **dev**, **ua** у **clean-merged-branch**, а також заборона тримати артефакти **Firebase Hosting** у **підкаталогах першого рівня** (безпосередні діти кореня репозиторію; у самому корені ці імена не вимагаються до видалення).
|
|
8
8
|
|
|
9
9
|
**`npx @nitra/cursor check abie`** виконується лише якщо в **`.n-cursor.json`** у **`rules`** є **`abie`** — інакше вихід **0** без зауважень.
|
|
10
10
|
|
|
@@ -34,15 +34,15 @@ spec:
|
|
|
34
34
|
name: СЕРВІС-hl
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
## k8s: overlay **HTTPRoute** (**ua**
|
|
37
|
+
## k8s: overlay **HTTPRoute** (**ua**)
|
|
38
38
|
|
|
39
|
-
За наявності **Deployment** під **k8s** і наявності **Vite** (**`vite.config.js`**, **`vite.config.mjs`** або **`vite.config.ts`** у каталозі пакета) у **`ua/kustomization.yaml`**
|
|
39
|
+
За наявності **Deployment** під **k8s** і наявності **Vite** (**`vite.config.js`**, **`vite.config.mjs`** або **`vite.config.ts`** у каталозі пакета) у **`ua/kustomization.yaml`** цього пакета потрібні **inline JSON6902** у **`patches`**: **target** **`kind: HTTPRoute`**, **непорожній `name`** (як у маніфесті маршруту). Мають бути зміни **`/spec/hostnames`** (домени abie — у скрипті) та **`/spec/parentRefs/0/namespace`** (**`ua`**, також дозволені префікси **`ua-*`**, наприклад **`ua-b2b`**). Як обирати **`op`** (**add** / **replace** тощо) у patch — **k8s.mdc** (розділ про JSON patch у kustomization).
|
|
40
40
|
|
|
41
41
|
### HTTPRoute: спільні сервіси **`auth-run-hl`**, **`file-link-hl`**
|
|
42
42
|
|
|
43
43
|
У **HTTPRoute** у шляху з **`…/k8s/base/…`** у **`spec.hostnames`** дозволені лише **`aiml.live`**, **`*.aiml.live`** та інші піддомени **aiml.live** (перевірка в **`check-abie.mjs`**).
|
|
44
44
|
|
|
45
|
-
Ці **Service** (headless **`-hl`**) живуть у **базовому** неймспейсі **`dev`**. У маніфесті **HTTPRoute** під **`k8s`** (шар без **`ua/`**
|
|
45
|
+
Ці **Service** (headless **`-hl`**) живуть у **базовому** неймспейсі **`dev`**. У маніфесті **HTTPRoute** під **`k8s`** (шар без **`ua/`** — наприклад **`…/k8s/base/hr.yaml`**) для кожного **`backendRefs`** до такого сервісу явно вкажи **`namespace: dev`** і порт **8080**:
|
|
46
46
|
|
|
47
47
|
```yaml title="…/k8s/base/hr.yaml (фрагмент)"
|
|
48
48
|
spec:
|
|
@@ -60,7 +60,7 @@ spec:
|
|
|
60
60
|
port: 8080
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
У **`ua/kustomization.yaml`**
|
|
63
|
+
У **`ua/kustomization.yaml`** додай до того самого **inline** patch на **`HTTPRoute`** (той самий **`target.name`**) операції **JSON6902** з **`path`**: **`/spec/rules/<i>/backendRefs/<j>/namespace`**, де **`<i>`** / **`<j>`** — індекси відповідно до порядку **`spec.rules`** та **`backendRefs`** у base-файлі; **`value`**: **`ua`** (також дозволені **`ua-*`**). Якщо кілька таких **`backendRefs`**, потрібна окрема операція для кожного.
|
|
64
64
|
|
|
65
65
|
```yaml title="…/ua/kustomization.yaml (фрагмент)"
|
|
66
66
|
- target:
|
|
@@ -82,219 +82,9 @@ spec:
|
|
|
82
82
|
value: ua
|
|
83
83
|
```
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
- target:
|
|
87
|
-
kind: HTTPRoute
|
|
88
|
-
name: my-httproute
|
|
89
|
-
patch: |-
|
|
90
|
-
- op: replace
|
|
91
|
-
path: /spec/hostnames
|
|
92
|
-
value:
|
|
93
|
-
- "napitkivmeste.tech" # зокрема выбирайонлайн.рф, *.napitkivmeste.tech, *.выбирайонлайн.рф
|
|
94
|
-
- op: replace
|
|
95
|
-
path: /spec/parentRefs/0/namespace
|
|
96
|
-
value: ru
|
|
97
|
-
- op: replace
|
|
98
|
-
path: /spec/rules/0/backendRefs/0/namespace
|
|
99
|
-
value: ru
|
|
100
|
-
- op: replace
|
|
101
|
-
path: /spec/rules/0/backendRefs/1/namespace
|
|
102
|
-
value: ru
|
|
103
|
-
```
|
|
85
|
+
## k8s: overlay **ua** і nodeSelector
|
|
104
86
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
```yaml title="…/ru/kustomization.yaml (фрагмент, після patch на ConfigMap з HASURA_GRAPHQL_JWT_SECRET)"
|
|
108
|
-
- target:
|
|
109
|
-
kind: HTTPRoute
|
|
110
|
-
name: my-httproute
|
|
111
|
-
patch: |-
|
|
112
|
-
- op: add
|
|
113
|
-
path: /metadata/annotations
|
|
114
|
-
value:
|
|
115
|
-
gwin.yandex.cloud/rules.http.upgradeTypes: "websocket"
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
## k8s: overlay **ru** і nginx-sidecar для WebSocket (Hasura)
|
|
119
|
-
|
|
120
|
-
YC ALB (gwin) має баг: якщо HTTPRoute-правило містить одночасно `URLRewrite` (ReplacePrefixMatch) і `upgrade_types: websocket` — ALB не обробляє WebSocket і повертає 404.
|
|
121
|
-
<https://center.yandex.cloud/support/tickets/TX549394>
|
|
122
|
-
|
|
123
|
-
Обхідний варіант: nginx-sidecar у поді, що сам виконує rewrite і передає WebSocket до Hasura.
|
|
124
|
-
|
|
125
|
-
**Умова:** в дереві `k8s` є Deployment з image `hasura/graphql-engine` (або `newName` на нього через `images:` у kustomization) **і** `ru/kustomization.yaml` містить `HASURA_GRAPHQL_JWT_SECRET` (patch на ConfigMap Hasura з JWT).
|
|
126
|
-
|
|
127
|
-
### Що потрібно зробити
|
|
128
|
-
|
|
129
|
-
**1. `ru/configmap-nginx.yaml`** — ConfigMap з nginx.conf:
|
|
130
|
-
|
|
131
|
-
```yaml title="…/k8s/ru/configmap-nginx.yaml"
|
|
132
|
-
# yaml-language-server: $schema=https://raw.githubusercontent.com/yannh/kubernetes-json-schema/master/v1.33.9-standalone-strict/configmap-v1.json
|
|
133
|
-
apiVersion: v1
|
|
134
|
-
kind: ConfigMap
|
|
135
|
-
metadata:
|
|
136
|
-
name: СЕРВІС-nginx
|
|
137
|
-
namespace: ru-NAMESPACE
|
|
138
|
-
data:
|
|
139
|
-
nginx.conf: |
|
|
140
|
-
user nginx;
|
|
141
|
-
worker_processes auto;
|
|
142
|
-
error_log /dev/null;
|
|
143
|
-
|
|
144
|
-
events {
|
|
145
|
-
worker_connections 1024;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
http {
|
|
149
|
-
access_log off;
|
|
150
|
-
|
|
151
|
-
map $http_upgrade $connection_upgrade {
|
|
152
|
-
default upgrade;
|
|
153
|
-
'' close;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
server {
|
|
157
|
-
listen 8081;
|
|
158
|
-
server_name _;
|
|
159
|
-
|
|
160
|
-
location /healthz {
|
|
161
|
-
add_header Content-Type text/plain;
|
|
162
|
-
return 200 "healthy";
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
# WebSocket: ALB не робить rewrite (URLRewrite + upgrade = bug YC ALB)
|
|
166
|
-
# nginx переписує /PREFIX/* → /* і передає до Hasura
|
|
167
|
-
location /PREFIX/ {
|
|
168
|
-
rewrite ^/PREFIX/(.*)$ /$1 break;
|
|
169
|
-
proxy_pass http://127.0.0.1:8080;
|
|
170
|
-
proxy_http_version 1.1;
|
|
171
|
-
proxy_set_header Upgrade $http_upgrade;
|
|
172
|
-
proxy_set_header Connection $connection_upgrade;
|
|
173
|
-
proxy_set_header Host $host;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
# HTTP: ALB вже зробив prefix_rewrite → /, nginx просто передає
|
|
177
|
-
location / {
|
|
178
|
-
proxy_pass http://127.0.0.1:8080;
|
|
179
|
-
proxy_http_version 1.1;
|
|
180
|
-
proxy_set_header Upgrade $http_upgrade;
|
|
181
|
-
proxy_set_header Connection $connection_upgrade;
|
|
182
|
-
proxy_set_header Host $host;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
**2. `ru/kustomization.yaml`** — додати до `resources` та чотири patch-блоки:
|
|
189
|
-
|
|
190
|
-
```yaml title="…/k8s/ru/kustomization.yaml (фрагмент)"
|
|
191
|
-
resources:
|
|
192
|
-
- ../base
|
|
193
|
-
- configmap-nginx.yaml # ← додати
|
|
194
|
-
|
|
195
|
-
patches:
|
|
196
|
-
# Headless Service: замінити ports на два іменованих (hasura:8080 + proxy:8081)
|
|
197
|
-
- target:
|
|
198
|
-
kind: Service
|
|
199
|
-
name: СЕРВІС-hl
|
|
200
|
-
patch: |-
|
|
201
|
-
- op: replace
|
|
202
|
-
path: /spec/type
|
|
203
|
-
value: NodePort
|
|
204
|
-
- op: remove
|
|
205
|
-
path: /spec/clusterIP
|
|
206
|
-
- op: replace
|
|
207
|
-
path: /spec/ports
|
|
208
|
-
value:
|
|
209
|
-
- name: hasura
|
|
210
|
-
protocol: TCP
|
|
211
|
-
port: 8080
|
|
212
|
-
- name: proxy
|
|
213
|
-
protocol: TCP
|
|
214
|
-
port: 8081
|
|
215
|
-
|
|
216
|
-
# Deployment: додати nginx-sidecar контейнер та volume
|
|
217
|
-
- target:
|
|
218
|
-
kind: Deployment
|
|
219
|
-
name: СЕРВІС
|
|
220
|
-
patch: |-
|
|
221
|
-
- op: add
|
|
222
|
-
path: /spec/template/spec/containers/-
|
|
223
|
-
value:
|
|
224
|
-
name: СЕРВІС-p
|
|
225
|
-
image: nginx:alpine-slim
|
|
226
|
-
ports:
|
|
227
|
-
- containerPort: 8081
|
|
228
|
-
protocol: TCP
|
|
229
|
-
volumeMounts:
|
|
230
|
-
- name: nginx-conf
|
|
231
|
-
mountPath: /etc/nginx/nginx.conf
|
|
232
|
-
subPath: nginx.conf
|
|
233
|
-
resources: {}
|
|
234
|
-
- op: add
|
|
235
|
-
path: /spec/template/spec/volumes
|
|
236
|
-
value:
|
|
237
|
-
- name: nginx-conf
|
|
238
|
-
configMap:
|
|
239
|
-
name: СЕРВІС-nginx
|
|
240
|
-
|
|
241
|
-
# HTTPRoute: прибрати URLRewrite-фільтри з PathPrefix-правила,
|
|
242
|
-
# направити трафік на nginx:8081, видалити мертве WebSocket-правило
|
|
243
|
-
- target:
|
|
244
|
-
kind: HTTPRoute
|
|
245
|
-
name: СЕРВІС
|
|
246
|
-
patch: |-
|
|
247
|
-
- op: remove
|
|
248
|
-
path: /spec/rules/INDEX_PATHPREFIX/filters
|
|
249
|
-
- op: replace
|
|
250
|
-
path: /spec/rules/INDEX_PATHPREFIX/backendRefs/0/port
|
|
251
|
-
value: 8081
|
|
252
|
-
- op: remove
|
|
253
|
-
path: /spec/rules/INDEX_WEBSOCKET
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
> `INDEX_PATHPREFIX` і `INDEX_WEBSOCKET` — індекси правил у `base/hr.yaml`. Після видалення filters ALB більше не додає `prefix_rewrite`, тому nginx-sidecar отримує оригінальний шлях і сам виконує rewrite.
|
|
257
|
-
|
|
258
|
-
**Примітка щодо Service:** якщо в base у `-hl` Service два порти задаються вперше, `spec.ports[*].name` є обов'язковим — без нього `kubectl apply` поверне помилку `Required value`.
|
|
259
|
-
|
|
260
|
-
## k8s: overlay **ru** і **Service** (у т. ч. headless → NodePort)
|
|
261
|
-
|
|
262
|
-
Для кожного **Service** в YAML під **`…/k8s/…`**, де шлях файлу **не** містить **`k8s/ua/`** чи **`k8s/ru/`** (маніфести base / спільного шару; у т. ч. **headless** з **`spec.clusterIP: None`** і **`-hl`**), якщо ще не **`spec.type: NodePort`** / **`LoadBalancer`** / **`ExternalName`**, у **`k8s/ru/kustomization.yaml`** того ж пакета (overlay **ru**) додай **inline** **JSON6902** у **`patches`**: **`target.kind: Service`**, **`target.name`** як у маніфеста, **`path: /spec/type`**, **`value: NodePort`**. Якщо в base було **`spec.clusterIP: None`**, у тому ж **patch** додай **`op: remove`** для **`/spec/clusterIP`**. Якщо в base **явно** задано **`spec.clusterIPs`** (зокрема **`['None']`**), додай **`op: remove`** і для **`/spec/clusterIPs`** — інакше **API** може відхилити **NodePort** (*`spec.clusterIPs[0]: Invalid value: "None"`*). **Не** додавай **`remove`** на **`/spec/clusterIPs`**, якщо ключа **немає** в base: **`kubectl kustomize`** тоді падає (*Unable to remove nonexistent key*). Якщо в base лише **`clusterIP: None`**, а помилка лишається після **`kubectl apply -k`** (злиття з уже існуючим **Service** у кластері), тимчасово **видали** **`Service`** у **`ru`** і застосуй знову, або додай у base поле **`clusterIPs`**, щоб **`remove`** у patch був валідний для **kustomize**. Деталі — **`check-abie.mjs`**.
|
|
263
|
-
|
|
264
|
-
```yaml title="…/ru/kustomization.yaml (фрагмент, headless → NodePort, без clusterIPs у base)"
|
|
265
|
-
patches:
|
|
266
|
-
- target:
|
|
267
|
-
kind: Service
|
|
268
|
-
name: user-site-hl
|
|
269
|
-
patch: |-
|
|
270
|
-
- op: replace
|
|
271
|
-
path: /spec/type
|
|
272
|
-
value: NodePort
|
|
273
|
-
- op: remove
|
|
274
|
-
path: /spec/clusterIP
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
Якщо в base у цього **Service** уже є **`spec.clusterIPs`**, той самий **patch** розшир **remove** на **`/spec/clusterIPs`** (див. **`check-abie.mjs`**).
|
|
278
|
-
|
|
279
|
-
## k8s: overlay **ru** і HealthCheckPolicy
|
|
280
|
-
|
|
281
|
-
Якщо в дереві **k8s** є **HealthCheckPolicy**, у **`ru/kustomization.yaml`** має бути patch **`$patch: delete`** для політики (узгоджено з **k8s.mdc**; перевірка в **`check-k8s.mjs`**, **`ruKustomizationHasHealthCheckDeletePatch`**). Підстав реальне ім’я замість **`СЕРВІС`**:
|
|
282
|
-
|
|
283
|
-
```yaml title="…/ru/kustomization.yaml (фрагмент)"
|
|
284
|
-
patches:
|
|
285
|
-
- target:
|
|
286
|
-
kind: HealthCheckPolicy
|
|
287
|
-
name: СЕРВІС
|
|
288
|
-
patch: |-
|
|
289
|
-
kind: HealthCheckPolicy
|
|
290
|
-
metadata:
|
|
291
|
-
name: СЕРВІС
|
|
292
|
-
$patch: delete
|
|
293
|
-
```
|
|
294
|
-
|
|
295
|
-
## k8s: overlay **ua** / **ru** і nodeSelector
|
|
296
|
-
|
|
297
|
-
У **`…/ua/kustomization.yaml`** та **`…/ru/kustomization.yaml`** того пакета, у дереві **`k8s`** якого є **Deployment**, потрібен patch на **`kind: Deployment`**: **ua** — **`spec.template.spec.nodeSelector`** з **`preem: false`**; **ru** — **`spec.template.spec.nodeSelector`** з **`yandex.cloud/preemptible: false`**. Форму **JSON6902** (шлях **`/spec/template/spec/nodeSelector`**, **`op`**) див. **k8s.mdc**.
|
|
87
|
+
У **`…/ua/kustomization.yaml`** того пакета, у дереві **`k8s`** якого є **Deployment**, потрібен patch на **`kind: Deployment`**: **`spec.template.spec.nodeSelector`** з **`preem: false`**. Форму **JSON6902** (шлях **`/spec/template/spec/nodeSelector`**, **`op`**) див. **k8s.mdc**.
|
|
298
88
|
|
|
299
89
|
```yaml title="…/ua/kustomization.yaml (фрагмент)"
|
|
300
90
|
patches:
|
|
@@ -308,21 +98,9 @@ patches:
|
|
|
308
98
|
preem: 'false'
|
|
309
99
|
```
|
|
310
100
|
|
|
311
|
-
```yaml title="…/ru/kustomization.yaml (фрагмент)"
|
|
312
|
-
patches:
|
|
313
|
-
- target:
|
|
314
|
-
kind: Deployment
|
|
315
|
-
name: my-app
|
|
316
|
-
patch: |-
|
|
317
|
-
- op: replace
|
|
318
|
-
path: /spec/template/spec/nodeSelector
|
|
319
|
-
value:
|
|
320
|
-
yandex.cloud/preemptible: "false"
|
|
321
|
-
```
|
|
322
|
-
|
|
323
101
|
### Базовий Deployment (`…/base/`)
|
|
324
102
|
|
|
325
|
-
Якщо **Deployment** у YAML під **`k8s`** лежить у шляху з сегментом **`base`**, у **`spec.template.spec.nodeSelector`** має бути **`preem`** зі значенням **істинно** (**`true`** або рядок **`'true'`**); overlay **ua**
|
|
103
|
+
Якщо **Deployment** у YAML під **`k8s`** лежить у шляху з сегментом **`base`**, у **`spec.template.spec.nodeSelector`** має бути **`preem`** зі значенням **істинно** (**`true`** або рядок **`'true'`**); overlay **ua** підміняє селектор.
|
|
326
104
|
|
|
327
105
|
```yaml title="…/base/deploy.yaml (фрагмент)"
|
|
328
106
|
spec:
|
|
@@ -332,19 +110,18 @@ spec:
|
|
|
332
110
|
preem: 'true' # буде замінено через kustomize
|
|
333
111
|
```
|
|
334
112
|
|
|
335
|
-
## Внутрішньокластерні URL у env-файлах (dev / ua
|
|
113
|
+
## Внутрішньокластерні URL у env-файлах (dev / ua)
|
|
336
114
|
|
|
337
115
|
Правило стосується **будь-якого** внутрішньокластерного URL у env-файлах abie-проєкту, а не лише `HASURA_GRAPHQL_ENDPOINT`. Це може бути URL до Hasura, KVCMS, `auth-run-hl`, `file-link-hl` чи будь-якого іншого Service у кластері — у всіх випадках DNS-суфікс і namespace-префікс мають відповідати **середовищу** з імені env-файлу.
|
|
338
116
|
|
|
339
|
-
abie-проєкти живуть у
|
|
117
|
+
abie-проєкти живуть у **двох GKE-кластерах** (dev / ua), тож DNS-суфікс і namespace у URL відрізняються між `*.env`-файлами:
|
|
340
118
|
|
|
341
119
|
| env-файл (basename) | namespace-префікс у URL | DNS-суфікс кластера | примітка |
|
|
342
120
|
| --- | --- | --- | --- |
|
|
343
121
|
| `dev.env`, `.dev.env` | `dev-…` | `abie-dev.internal` | GKE-кластер dev |
|
|
344
122
|
| `ua.env`, `.ua.env` | `ua-…` | `abie-ua.internal` | GKE-кластер ua |
|
|
345
|
-
| `ru.env`, `.ru.env` | `ru-…` | `cluster.local` | YC-кластер ru, стандартний k8s DNS |
|
|
346
123
|
|
|
347
|
-
Канонічна форма URL — `http://<service>.<namespace>.svc.<cluster-dns-suffix>:<port>`.
|
|
124
|
+
Канонічна форма URL — `http://<service>.<namespace>.svc.<cluster-dns-suffix>:<port>`. Суфікс — `<cluster>.internal`.
|
|
348
125
|
|
|
349
126
|
Приклади для одного env-файлу з двома сервісами (Hasura + KVCMS):
|
|
350
127
|
|
|
@@ -358,19 +135,14 @@ HASURA_GRAPHQL_ENDPOINT=http://apruv-h-hl.ua-apruv.svc.abie-ua.internal:8080
|
|
|
358
135
|
KVCMS_URL=http://kvcms-hl.ua-apruv.svc.abie-ua.internal:8080
|
|
359
136
|
```
|
|
360
137
|
|
|
361
|
-
|
|
362
|
-
HASURA_GRAPHQL_ENDPOINT=http://apruv-h-hl.ru-apruv.svc.cluster.local:8080
|
|
363
|
-
KVCMS_URL=http://kvcms-hl.ru-apruv.svc.cluster.local:8080
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
`<namespace>` (наприклад `dev-apruv` / `ua-apruv` / `ru-apruv`) — `metadata.name` цільового namespace після kustomize-overlay для відповідного середовища; `<service>` — `metadata.name` headless Service (`-hl`) того сервісу, до якого йде URL.
|
|
138
|
+
`<namespace>` (наприклад `dev-apruv` / `ua-apruv`) — `metadata.name` цільового namespace після kustomize-overlay для відповідного середовища; `<service>` — `metadata.name` headless Service (`-hl`) того сервісу, до якого йде URL.
|
|
367
139
|
|
|
368
|
-
**Перевірка `check-abie.mjs`** сканує всі `*.env` файли, basename яких збігається з `dev.env` / `ua.env`
|
|
140
|
+
**Перевірка `check-abie.mjs`** сканує всі `*.env` файли, basename яких збігається з `dev.env` / `ua.env` (з провідною крапкою чи без), знаходить **усі** internal URL (`http://<svc>.<ns>.svc.<dns>` — як для Hasura-ендпоінта, так і для KVCMS чи будь-якого іншого) і вимагає, щоб для кожного:
|
|
369
141
|
|
|
370
|
-
- DNS-суфікс відповідав env: `abie-dev.internal` / `abie-ua.internal
|
|
371
|
-
- namespace починався з `dev-` / `ua-`
|
|
142
|
+
- DNS-суфікс відповідав env: `abie-dev.internal` / `abie-ua.internal`;
|
|
143
|
+
- namespace починався з `dev-` / `ua-` відповідно.
|
|
372
144
|
|
|
373
|
-
Загальне правило про **внутрішній** URL (не публічний домен) для `HASURA_GRAPHQL_ENDPOINT` лишається у **`hasura.mdc`** (для nitra і abie) — `check-hasura.mjs` приймає
|
|
145
|
+
Загальне правило про **внутрішній** URL (не публічний домен) для `HASURA_GRAPHQL_ENDPOINT` лишається у **`hasura.mdc`** (для nitra і abie) — `check-hasura.mjs` приймає кластерний DNS-формат `<cluster>.internal`.
|
|
374
146
|
|
|
375
147
|
## Firebase Hosting
|
|
376
148
|
|
|
@@ -378,11 +150,11 @@ KVCMS_URL=http://kvcms-hl.ru-apruv.svc.cluster.local:8080
|
|
|
378
150
|
|
|
379
151
|
## Git branches
|
|
380
152
|
|
|
381
|
-
У **`.github/workflows/clean-merged-branch.yml`** у кроці **`phpdocker-io/github-actions-delete-abandoned-branches`** значення **`with.ignore_branches`** має містити **dev
|
|
153
|
+
У **`.github/workflows/clean-merged-branch.yml`** у кроці **`phpdocker-io/github-actions-delete-abandoned-branches`** значення **`with.ignore_branches`** має містити **dev** та **ua** (разом з іншими гілками, якщо потрібно):
|
|
382
154
|
|
|
383
155
|
```yaml title=".github/workflows/clean-merged-branch.yml (фрагмент)"
|
|
384
156
|
with:
|
|
385
|
-
ignore_branches: main,dev,ua
|
|
157
|
+
ignore_branches: main,dev,ua
|
|
386
158
|
```
|
|
387
159
|
|
|
388
160
|
## Перевірка
|
|
@@ -398,6 +170,6 @@ with:
|
|
|
398
170
|
- **`http_route_base/`** → `abie.http_route_base` — у HTTPRoute під `…/k8s/.../base/...` усі `spec.hostnames` мають бути в домені `aiml.live` (включно з `*.aiml.live` та піддоменами). **Цільові файли:** `…/k8s/.../base/.../hr.yaml`.
|
|
399
171
|
- **`health_check_policy/`** → `abie.health_check_policy` — структура HealthCheckPolicy: `apiVersion: networking.gke.io/v1`, `metadata.name`, `spec.default.config.type: HTTP`, `httpHealthCheck.requestPath` починається з `/`, `port: 8080`, `targetRef.kind: Service`, `targetRef.name` має суфікс `-hl`. **Цільові файли:** `…/k8s/.../hc.yaml`.
|
|
400
172
|
- **`base_deployment_preem/`** → `abie.base_deployment_preem` — Deployment у base/ має `spec.template.spec.nodeSelector.preem` зі значенням `true` (boolean або рядок). **Цільові файли:** ресурсні YAML під `…/k8s/.../base/...`.
|
|
401
|
-
- **`clean_merged_ignore_branches/`** → `abie.clean_merged_ignore_branches` — у workflow `.github/workflows/clean-merged-branch.yml` крок з `uses: phpdocker-io/github-actions-delete-abandoned-branches` має `with.ignore_branches`, що містить токени `dev,ua
|
|
173
|
+
- **`clean_merged_ignore_branches/`** → `abie.clean_merged_ignore_branches` — у workflow `.github/workflows/clean-merged-branch.yml` крок з `uses: phpdocker-io/github-actions-delete-abandoned-branches` має `with.ignore_branches`, що містить токени `dev,ua` (case-insensitive). **Цільові файли:** `.github/workflows/clean-merged-branch.yml`.
|
|
402
174
|
|
|
403
|
-
Cross-file логіка (парність HCP↔Deployment у каталозі, обчислений `<deployment.name>-hl` для `targetRef.name`, валідація
|
|
175
|
+
Cross-file логіка (парність HCP↔Deployment у каталозі, обчислений `<deployment.name>-hl` для `targetRef.name`, валідація ua-overlay JSON6902 patches на HTTPRoute, env→cluster DNS, аналіз cross-namespace backendRefs у пакетах) лишається у **`check-abie.mjs`** — Rego не читає файлову систему й не робить cross-document резолюцію.
|
package/mdc/hasura.mdc
CHANGED
package/mdc/k8s.mdc
CHANGED
|
@@ -310,7 +310,7 @@ data:
|
|
|
310
310
|
|
|
311
311
|
### Overlays (не-dev)
|
|
312
312
|
|
|
313
|
-
- У каталозі кожного іншого середовища (наприклад **`
|
|
313
|
+
- У каталозі кожного іншого середовища (наприклад **`ua/`**, **`prod/`**) має бути **мінімум файлів**: типово лише **`kustomization.yaml`** (посилання на `base`, `patches`, `replacements`, `components` тощо) і ресурси чи додаткові YAML, **необхідні лише для цього overlay**.
|
|
314
314
|
- Відмінності від dev вносяться **оверрайдами** (patches, `images`, `replicas`, `configMapGenerator` тощо), а не копіюванням повного дерева з `base`.
|
|
315
315
|
|
|
316
316
|
### Namespace
|
|
@@ -387,7 +387,7 @@ images:
|
|
|
387
387
|
|
|
388
388
|
Інші назви каталогу (`scale/`, `hpa-component/`, `pdb-component/`) — fail.
|
|
389
389
|
|
|
390
|
-
**Overlays** (`ua/`,
|
|
390
|
+
**Overlays** (`ua/`, прод-overlays) підключають `components: [- ../components]` і додають JSON6902-патчі для прод-значень: `/spec/minReplicas`, `/spec/maxReplicas` (HPA), `/spec/minAvailable` (PDB). Dev-середовище (`base`) HPA/PDB не отримує — як і потрібно.
|
|
391
391
|
|
|
392
392
|
**`<pkg>/k8s/components/kustomization.yaml`** має `kind: Component` (не `kind: Kustomization`) — це **джерело** канонічних HPA/PDB для всіх overlays, а не overlay сам по собі. Прод-перезаписи (`/spec/minReplicas`, `/spec/maxReplicas`, `/spec/minAvailable`) живуть у `<env>/kustomization.yaml`, що підключає Component через `components:`. У самому Component patches не потрібні — він env-неутральний; **`check k8s`** не вимагає прод-патчів від `components/kustomization.yaml`.
|
|
393
393
|
|
package/package.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
# `npm/scripts/check-abie.mjs` (abie.mdc): кожен `Deployment` у файлах під
|
|
3
3
|
# `…/k8s/.../base/…` має `spec.template.spec.nodeSelector.preem` зі
|
|
4
4
|
# значенням, що вважається істинним (boolean `true` або рядок `"true"`
|
|
5
|
-
# без урахування регістру).
|
|
6
|
-
# JSON6902
|
|
5
|
+
# без урахування регістру). Overlay ua далі підміняє селектор
|
|
6
|
+
# JSON6902-патчем на `preem: false`.
|
|
7
7
|
#
|
|
8
8
|
# Запуск (локально, лише для одного base-YAML з Deployment):
|
|
9
9
|
# conftest test path/to/k8s/base/deployment.yaml \
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# з `npm/scripts/check-abie.mjs` (abie.mdc): у workflow
|
|
3
3
|
# `.github/workflows/clean-merged-branch.yml` крок з
|
|
4
4
|
# `uses: phpdocker-io/github-actions-delete-abandoned-branches` має у
|
|
5
|
-
# `with.ignore_branches` містити усі обовʼязкові токени `dev,ua
|
|
5
|
+
# `with.ignore_branches` містити усі обовʼязкові токени `dev,ua`
|
|
6
6
|
# (case-insensitive, кома-розділені).
|
|
7
7
|
#
|
|
8
8
|
# Запуск (локально):
|
|
@@ -23,7 +23,7 @@ package abie.clean_merged_ignore_branches
|
|
|
23
23
|
import rego.v1
|
|
24
24
|
|
|
25
25
|
# Обовʼязкові гілки в `ignore_branches` (узгоджено з `ABIE_REQUIRED_IGNORE_BRANCHES`).
|
|
26
|
-
required_branches := {"dev", "ua"
|
|
26
|
+
required_branches := {"dev", "ua"}
|
|
27
27
|
|
|
28
28
|
# Префікс `uses:` для GitHub Action, у якого читаємо `with.ignore_branches`.
|
|
29
29
|
target_action_marker := "phpdocker-io/github-actions-delete-abandoned-branches"
|
|
@@ -24,23 +24,23 @@ test_deny_ignore_branches_missing if {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
test_deny_missing_required_token if {
|
|
27
|
-
count(clean_merged_ignore_branches.deny) > 0 with input as mk_workflow({"ignore_branches": "dev
|
|
27
|
+
count(clean_merged_ignore_branches.deny) > 0 with input as mk_workflow({"ignore_branches": "dev"})
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
test_deny_completely_wrong_tokens if {
|
|
31
31
|
count(clean_merged_ignore_branches.deny) > 0 with input as mk_workflow({"ignore_branches": "main,develop"})
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
count(clean_merged_ignore_branches.deny) == 0 with input as mk_workflow({"ignore_branches": "dev,ua
|
|
34
|
+
test_allow_required_tokens if {
|
|
35
|
+
count(clean_merged_ignore_branches.deny) == 0 with input as mk_workflow({"ignore_branches": "dev,ua"})
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
# Регістронезалежне порівняння і пропуск пробілів.
|
|
39
39
|
test_allow_uppercase_with_spaces if {
|
|
40
|
-
count(clean_merged_ignore_branches.deny) == 0 with input as mk_workflow({"ignore_branches": " DEV , UA
|
|
40
|
+
count(clean_merged_ignore_branches.deny) == 0 with input as mk_workflow({"ignore_branches": " DEV , UA "})
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
extra_branches_workflow := mk_workflow({"ignore_branches": "dev,ua,
|
|
43
|
+
extra_branches_workflow := mk_workflow({"ignore_branches": "dev,ua,main,release/*"})
|
|
44
44
|
|
|
45
45
|
# Додаткові гілки після обов'язкових — дозволено.
|
|
46
46
|
test_allow_extra_branches if {
|