Mundarija (35)
- Bu darsda
- 1. Nega bu kerak?
- 2. Testlarni tashkil qilish
- 2.1 Darajalar va muhit
- 2.2 Izolyatsiya — parallellikning sharti
- 3. Parallellik va tezlik
- 3.1 Kanon o'lchovi
- 3.2 Nega chiziqli emas
- 4. Beqaror testlar: sabab bilan tuzatish
- 4.1 To'rt hodisa
- 4.2 Chegarani oshirish — qachon to'g'ri
- 4.3 Mutlaq va nisbiy chegara
- 4.4 Beqarorlikni topish
- 5. Lokal check va pre-push hook
- 5.1 npm run check
- 5.2 Pre-push hook
- 6. Minimal CI
- 6.1 Fayl
- 6.2 Fayl bo'ylab
- 6.3 Halol: bu fayl nimani bilmaydi
- 6.4 npm audit: haqiqiy natija
- 7. Ko'p uchraydigan xatolar
- 8. Mashqlar
- 1-mashq (oson): bo'shliqlarni to'ldiring
- 2-mashq (o'rta): beqaror testlarni ajratish
- 3-mashq (qiyin): fayllarni ishchilarga taqsimlash
- 9. Loyiha qadami: yakuniy tekshiruv va commit
- 9.1 Bu darsdagi o'zgarishlar
- 9.2 Yakuniy tekshiruv
- 9.3 Commit
- 10. 31-qism yakuni: nima qurildi
- Keyingi qism
- 11. Real ishda
- Xulosa
- Manbalar
Test arxitekturasi va CI: parallel testlar, beqaror testlar, lokal check va minimal pipeline
Qisqacha: Testlar ko'paygan sari ikki savol muhim bo'ladi: ular tezmi va ularga ishonsa bo'ladimi. Kanon 340 ta testni Vitest'da parallel yurgizadi: sukut (16 ishchi) bilan 116 s, 4 ishchi bilan 151 s. 31-qism boshidagi birinchi to'liq tekshiruvda testlar qizil edi — lekin kod to'g'ri edi: to'rtta beqaror (flaky) test yuk ostida yiqilgan. Har birining sababi topildi va tuzatildi — tasodif emas. Tekshiruv bir buyruqda:
npm run check(tip, lint, test, build). Xuddi shu qadamlar CI faylida —.github/workflows/ci.yml. Bu dars 31-qismni yakunlaydi:vazifalar-apiv4.0.0 commit qilinadi.
Bu darsda
- Backend testlarini darajalar va muhit bo'yicha tashkil qilasiz.
- Vitest parallelligi qanday ishlashini va uning narxini kanon o'lchovida ko'rasiz.
- Beqaror testning sababini topib, uni tasodif emas, sabab bilan tuzatasiz.
- Lokal
checkva pre-push hook bilan xatoni push'dan oldin ushlaysiz. - Minimal CI faylini o'qiysiz va u nimani tekshirmasligini bilasiz.
- 31-qismni yakunlaysiz:
vazifalar-apiv4.0.0 commit'i va nima qurilganining xaritasi.
Oldin bilishingiz kerak: GitHub Actions: birinchi CI workflow, Git hooklar: Husky va lint-staged, Test strategiyasi va flaky testlar, Testcontainers, Yuklama va stress testlari.
1. Nega bu kerak?
31-qism boshlanganda kanon 30-qism oxiridagi loyihani o'zgartirmasdan, yangi konteynerlarda to'liq tekshirdi. × belgili qatorlarga va oxiridagi Tests qatoriga qarang. Natija:
--- npm run test
↓ |asosiy| test/konteyner.test.ts (1 test | 1 skipped)
× omborYarat(prisma): SAQLASH=prisma — fail-fast va ishlaydi 20735ms
× deep link → /start → ulandi; /vazifalar; tugma → bajarildi; begona id — topilmadi; /yangi dialog (Redis) muddat bilan 1119ms
FAIL |asosiy| test/migratsiya.test.ts [ test/migratsiya.test.ts ]
⎯⎯⎯⎯⎯⎯⎯ Failed Tests 2 ⎯⎯⎯⎯⎯⎯⎯
FAIL |asosiy| test/prisma-ombor.test.ts > omborYarat(prisma): SAQLASH=prisma — fail-fast va ishlaydi
FAIL |asosiy| test/telegram-bot.test.ts > deep link → /start → ulandi; /vazifalar; tugma → bajarildi; begona id — topilmadi; /yangi dialog (Redis) muddat bilan
Test Files 3 failed | 52 passed | 1 skipped (56)
Tests 2 failed | 296 passed | 1 skipped (299)
exit 1 (99095 ms)Kod o'zgarmagan, 30-qismda xuddi shu testlar yashil edi. Keyingi kunlardagi yugurishda (tuzatishlardan oldin) yana ikkita test yiqildi — lekin boshqa juftlik:
maxWorkers=sukut #1: 172823 ms | Tests 2 failed | 298 passed | 1 skipped (301) | yiqilgan: test/auth.test.ts > POST /v1/auth/kirish > timing: noma'lum email ham argon2 bajaradi — ;test/prisma-ombor.test.ts > omborYarat(prisma): SAQLASH=prisma — fail-fast va ishlaydi;Bir yugurishda Telegram testi yiqiladi, boshqasida auth testi, kod esa o'sha. Bu — beqaror test.
Beqaror test xatodan ham yomonroq. Xato bir marta tuzatiladi. Beqaror test esa jamoaga "qizil — bu shunchaki tasodif, qayta yurgizamiz" deb o'rgatadi. Bir oydan keyin haqiqiy xato ham "tasodif" deb o'tkazib yuboriladi. Test to'plamining qiymati — unga ishonch.
O'xshatish: tez-tez yolg'on signal beradigan yong'in signalizatsiyasi. Uch marta bekorga chalinsa, to'rtinchisida hech kim binodan chiqmaydi.
2. Testlarni tashkil qilish
2.1 Darajalar va muhit
Backend test strategiyasi darsida testlarni darajalarga bo'ldik: unit, integration, shartnoma, e2e. 31-qism oxirida vazifalar-api da 68 ta test fayli bor. Ular muhitga ko'ra ham bo'linadi — nima kerak bo'lsa, o'shanda ishlaydi:
flowchart TB
A["npm run check"] --> T["tip + lint + build"]
A --> V["Vitest: 68 fayl"]
V --> U["bazasiz: unit, HTTP, shartnoma"]
V --> D["Postgres + Redis + MinIO + Mailpit"]
K["TESTCONTAINERS=1"] --> C["konteyner.test: o'z Postgres'i"]
E["npm run e2e"] --> P["Playwright: haqiqiy brauzer"]Diagrammaning chap tarmog'i — har kuni ishlaydigan npm run check. Uning ichida bazasiz testlar doim ishlaydi. Baza, Redis, MinIO yoki Mailpit kerak bo'lgan testlar — faqat ular mavjud bo'lsa. O'ng tomondagi ikkitasi alohida buyruq bilan: Testcontainers (Docker kerak, ~10 s qo'shimcha) va e2e (brauzer kerak).
Muhit yo'q bo'lsa, test yiqilmaydi, o'tkazib yuboriladi (SKIP) va sababini aytadi. Biz loyihani Docker'siz, hech qanday bazasiz to'liq yurgizib ko'rdik (Vitest 5.0.5, 4 ishchi):
↓ |asosiy| test/navbat.test.ts (1 test | 1 skipped)
↓ |asosiy| test/pg-ombor.test.ts (1 test | 1 skipped)
↓ |asosiy| test/saqlash.test.ts (1 test | 1 skipped)
↓ |redis-kanal| test/jonli.test.ts (1 test | 1 skipped)
Test Files 44 passed | 24 skipped (68)
Tests 139 passed | 38 skipped (177)Chiqishning faqat bir qismi ko'rsatilgan. To'plam yashil — lekin 68 fayldan 24 tasi umuman ishlamadi. Muhim saboq: yashil natija "hamma narsa tekshirildi" degani emas. Har doim SKIP soniga qarang. Kanonning to'liq tekshiruvida (hamma xizmat bilan) faqat bitta fayl SKIP — konteyner.test, u alohida yuradi.
2.2 Izolyatsiya — parallellikning sharti
Testlar parallel ishlashi uchun ular bir-biriga tegmasligi kerak. Kanon buni uch joyda hal qilgan:
| Umumiy resurs | Muammo | Kanon yechimi |
|---|---|---|
| Auth bazasi | bir fayl TRUNCATE qilsa, boshqasining ma'lumoti yo'qoladi |
har fayl shablon bazadan o'z nusxasini oladi (CREATE DATABASE … TEMPLATE, ~0.3 s) |
| Redis navbatlari | ikki test bir navbatdan ish oladi | navbat prefiksi testga xos: t45-<pid> |
| Redis Pub/Sub kanali | SSE testlari bir-birining hodisasini oladi | alohida Vitest loyihasi redis-kanal, ketma-ket |
Uchinchisi vitest.config.ts da:
const KANAL_TESTLARI = ["test/jonli.test.ts", "test/outbox.test.ts"];
export default defineConfig({
test: {
env: { LOG_LEVEL: "silent" },
testTimeout: 20_000,
hookTimeout: 30_000,
projects: [
{ extends: true, test: { name: "asosiy",
include: ["test/**/*.test.ts", "src/**/*.spec.ts"],
exclude: KANAL_TESTLARI } },
{ extends: true, test: { name: "redis-kanal",
include: KANAL_TESTLARI, fileParallelism: false } },
],
},
});(Kanon faylidan; izohlar olib tashlangan, qatorlar bo'lingan.) Chiqishdagi |asosiy| va |redis-kanal| — shu loyihalar nomi. Ikkalasi bir yugurishda ishlaydi, lekin ikkinchisining fayllari bir-birini kutadi. testTimeout: 20_000 — Vitest sukuti 5 s; bazali testlar yuklangan mashinada 5–7 s olgani uchun oshirilgan.
3. Parallellik va tezlik
3.1 Kanon o'lchovi
Vitest test fayllarini alohida ishchi jarayonlarda (worker) parallel yurgizadi; fayl ichidagi testlar ketma-ket. Ishchilar soni — --maxWorkers. Vitest 5 hujjatiga ko'ra (2026-11), vitest run da sukut — mashinadagi mavjud parallellikning hammasi (os.availableParallelism()), kuzatuv (watch) rejimida — yarmi. Kanon mashinasida 16 mantiqiy yadro — demak sukut 16 ishchi (kanon chiqishi sonni yozmaydi, bu hujjat bo'yicha hisob). Kanon bir xil 340 testni uch xil parallellikda yurgizdi (test bazalari har yugurishdan oldin noldan quriladi; yorliqlar qisqartirilgan):
maxWorkers=sukut (yakuniy tekshiruv, npm run test): 116484 ms | Tests 339 passed | 1 skipped (340)
maxWorkers=8 #1: 122670 ms | Tests 339 passed | 1 skipped (340) | yiqilgan:
maxWorkers=4 #1: 150596 ms | Tests 339 passed | 1 skipped (340) | yiqilgan:Grafikda — vaqt sukut parallellikka nisbatan:
- sukut (16 ishchi)100 %
- 8 ishchi105 %
- 4 ishchi129 %
Manba: IlmHamroh kanon o'lchovi, 2026-11-03: Vitest 5.0.5, Node 24.21.0, 340 test, Postgres 18.6 va Redis Docker'da; 116.5 / 122.7 / 150.6 s; har biri bitta yugurish, bitta mashina
3.2 Nega chiziqli emas
Ishchilar 16 dan 4 ga — to'rt baravar kamaydi. Vaqt esa atigi 29 % oshdi. 16 dan 8 ga — farq 5 %, shovqin chegarasida.
Sabab — testlar CPU'ni emas, asosan umumiy resurslarni kutadi: bitta Postgres, bitta Redis, Prisma klientini ko'tarish, argon2 hash. 16 ta ishchi bir Postgres'ga navbat bo'ladi. Bu Yuklama va stress testlari darsidagi to'yinish: ishchilar qo'shilgani bilan o'tkazuvchanlik o'smaydi, faqat kutish o'sadi. Yana bir sabab: yugurishning katta qismi modullarni yuklashga ketadi. Bizning lokal yugurishlarimizda Vitest buni o'zi ko'rsatdi: Duration 54.07s (import 85%, tests 12%, transform 3%) — vaqtning 85 % i import.
Ikki amaliy xulosa:
- Lokal — sukut yaxshi. Bitta faylni tekshirish uchun esa butun to'plam emas:
npx vitest run test/shartnoma.test.ts. - CI — GitHub'ning oddiy runner'ida 2–4 vCPU. 16 ishchi u yerda bo'lmaydi, beqaror testlar esa aynan yuklangan mashinada chiqdi. Kanon CI faylida
--maxWorkers=2.
Tekshirib ko'ring: Testlar 4 ishchida 151 s, 16 ishchida 116 s. Jamoa "8 yadroli CI runner'ga pul to'lab, CI'ni 2 baravar tezlashtiramiz" deydi. O'lchov bu rejani qo'llab-quvvatlaydimi?
Javob
Yo'q. 4 dan 16 ishchiga — atigi 23 % tezlashuv (151 → 116 s), 8 ishchi esa 16 talikdan bor-yo'g'i 5 % sekin. Tor joy — yadrolar emas, umumiy Postgres va modullarni yuklash. Pul to'lashdan oldin profil kerak: qaysi fayllar eng uzoq yuradi, import vaqtini qisqartirib bo'ladimi, sekin fayllarni bo'lib bo'ladimi. Bu — Backend unumdorligini oshirish darsidagi "avval o'lcha" qoidasi, faqat testlar uchun.
4. Beqaror testlar: sabab bilan tuzatish
4.1 To'rt hodisa
Test strategiyasi va flaky testlar darsida beqarorlikning to'rt sababini ko'rgansiz: vaqt, tartib, "darhol va tugagach", kutish chegarasi. Kanon topgan to'rt hodisaning hammasi shularga tushadi:
| Test | Belgisi | Sabab | Tuzatish |
|---|---|---|---|
telegram-bot |
dialog holati Redis'da yo'q | javob holatdan oldin keladi | kutib() — shart bilan kutish |
prisma-ombor fail-fast |
20 735 ms, timeout | yolg'iz 10.7 s, yuk ostida 20 s dan oshdi | o'z chegarasi 60 s |
migratsiya (afterAll) |
hook 30 s timeout | DROP DATABASE checkpoint kutadi |
hook chegarasi 60 s |
auth timing |
479 va 506 ms farqi > 20 ms | mutlaq chegara yuk ostida | nisbiy: max(20 ms, 15 %) |
Birinchisini Asinxron komponentlarni testlash darsida ko'rdik. Qolgan uchtasi — kutish chegarasi turi. Lekin ularni tuzatishda bitta xavf bor.
4.2 Chegarani oshirish — qachon to'g'ri
"Timeout'ni oshirish" — beqaror testning eng mashhur va eng xavfli "davosi". Haqiqiy osilish (cheksiz kutayotgan Promise) ham timeout bilan ko'rinadi — chegarani 10 baravar oshirsangiz, uni shunchaki kechroq ko'rasiz.
Kanondagi uchta tuzatish boshqacha: har birida chegara o'lchovdan kelib chiqqan. Prisma testi:
// yolg'iz 10.7 s (Prisma klienti ikki marta ko'tariladi),
// parallel yuk ostida 20 s dan oshdi — o'z chegarasi 60 s
test("omborYarat(prisma): SAQLASH=prisma — fail-fast va ishlaydi",
{ timeout: 60_000 }, async () => {Kanon izohidagi o'lchovga ko'ra yolg'iz 10.7 s — test haqiqatan sekin (Prisma klientini ikki marta ko'taradi). Global chegara (20 s) o'zgarmadi: faqat shu bitta test uchun, o'lchangan vaqtning ~6 baravari. Boshqa 339 test haqiqiy osilishni hamon 20 s da ushlaydi.
4.3 Mutlaq va nisbiy chegara
To'rtinchisi qiziqroq. Login oqimi testlaridan biri vaqt hujumini (timing attack) tekshiradi. Noma'lum email uchun ham server argon2 hash'ni hisoblashi kerak. Aks holda javob vaqtidan "bunday foydalanuvchi bormi" ni bilib olish mumkin. Test ikkala holatni 9 martadan o'lchaydi va medianalarni solishtiradi:
-assert.ok(Math.abs(bor - yoq) < 20, xabar);
+assert.ok(
+ Math.abs(bor - yoq) < Math.max(20, 0.15 * Math.max(bor, yoq)),
+ xabar);(Kanon diff'idan, telefon uchun bo'lingan; xabar o'rnida kodda `bor … ms, yo'q … ms` satri turadi.) Kanon izohiga ko'ra bo'sh mashinada har kirish ~50 ms, farq bir necha ms — 20 ms chegara yetarli. Yuklangan mashinada har kirish ~500 ms ga cho'zildi (izohdagi o'lchov: 479 va 506 ms) va shovqin ham shunga yarasha o'sdi: 27 ms farq — "hujum" emas, shovqin. Nisbiy chegara (15 %) shovqin bilan birga kattalashadi.
Muhimi — test o'z vazifasini yo'qotmadi. Haqiqiy zaiflikda farq juda katta: argon2'siz noma'lum email ~2 ms, argon2 bilan ~50 ms va undan ko'p. Testdagi ikkinchi tekshiruv ham qoldi: yoq > 15 ms — noma'lum email ham hash qilinishi shart. Nisbiy chegara shovqinni o'tkazadi, zaiflikni esa baribir ushlaydi.
Diqqat: "Kanon tekshiruvidagi har qizil = beqaror test" ham noto'g'ri xulosa. Kanon parallellik o'lchovida bir nechta yugurish 22–33 tadan yiqildi. Sabab — orqa fonda to'xtamagan eski jarayonlar test bazalarini shu paytda qayta qurayotgan edi ("relation does not exist"). Bu test xatosi emas, o'lchov xatosi. Bunday yugurishlar natijalardan olib tashlangan va sababi yozib qo'yilgan. Qizil natijada birinchi savol: "sharoit to'g'rimidi?"
4.4 Beqarorlikni topish
Beqaror testni bitta yugurish ko'rsatmaydi. Hisoblab ko'ramiz: test har yugurishda 2 % ehtimol bilan yiqilsa, uni ko'rish uchun necha marta yurgizish kerak?
// Bitta test har yugurishda p ehtimol bilan yiqiladi
function korishEhtimoli(p, marta) {
return 1 - (1 - p) ** marta;
}
function kerakliMarta(p, ishonch = 0.95) {
return Math.ceil(Math.log(1 - ishonch) / Math.log(1 - p));
}
for (const p of [0.2, 0.02, 0.005]) {
console.log(`p = ${p * 100} %: 1 yugurishda ` +
`${(korishEhtimoli(p, 1) * 100).toFixed(1)} %, ` +
`95 % ishonch uchun ${kerakliMarta(p)} yugurish`);
}
// To'plamda 4 ta shunday test (har biri 2 %) bo'lsa:
const qizil = 1 - (1 - 0.02) ** 4;
console.log(`to'plam qizil: ${(qizil * 100).toFixed(1)} %`);Konsolda:
p = 20 %: 1 yugurishda 20.0 %, 95 % ishonch uchun 14 yugurish
p = 2 %: 1 yugurishda 2.0 %, 95 % ishonch uchun 149 yugurish
p = 0.5 %: 1 yugurishda 0.5 %, 95 % ishonch uchun 598 yugurish
to'plam qizil: 7.8 %Ikki xulosa. Birinchisi: kam uchraydigan beqarorlikni takrorlab topish qimmat — 2 % li test uchun ~150 yugurish. Shuning uchun sabab qidiriladi, statistika emas: "nima vaqtga, tartibga yoki umumiy holatga bog'liq?". Ikkinchisi: har biri "kam uchraydigan" to'rtta test birga har 13 yugurishdan birini qizil qiladi. Jamoa uchun bu — "CI tez-tez yolg'on qizil".
Amaliy vositalar:
| Vosita | Nima qiladi |
|---|---|
| Ko'p marta yurgizish | yuk ostida (parallel) — beqarorlik aynan shu yerda chiqadi |
--sequence.shuffle |
testlarni tasodifiy tartibda — yashirin bog'liqlikni topadi |
--sequence.seed=N |
o'sha tasodifiy tartibni takrorlaydi |
--retry=N |
yiqilganini qayta yurgizadi — topish uchun, tuzatish uchun emas |
| Karantin | sababi topilguncha alohida ro'yxatda, lekin kuzatuvda |
Kanon package.json ga skript qo'shdi: "test:aralash": "vitest run --sequence.shuffle". Aralash tartib urug' (seed) bilan bo'ladi va Vitest uni chiqishda yozadi. Biz kichik to'plamda sinadik:
RUN v5.0.5 C:/Users/…/vazifalar-api
Running tests with seed "31"
✓ |asosiy| test/config.test.ts > config: REDIS_URL (ixtiyoriy, faqat redis://), KESH_TTL (sukut 60, bo'sh — xato) 16ms
✓ |asosiy| test/asinxron.test.ts > retry backoff haqiqiy setTimeout bilan — soxta soat oldinga suriladi (test 0 ms kutadi); Retry-After 5 s hurmat qilinadi 11ms
✓ |asosiy| test/asinxron.test.ts > bayroqlar keshi: 30 s ichida bazaga qayta bormaydi, 30 s dan keyin — boradi; tozala() — darhol 2ms(Buyruq: npx vitest run --sequence.shuffle --sequence.seed=31 … uchta fayl bilan; chiqish qisqartirilgan, yo'l qisqartirilgan.) asinxron.test.ts dagi retry testi fayldagi tartibda uchinchi, bu yerda — birinchi. Aralash tartibda biror test yiqilsa, chiqishdagi urug'ni --sequence.seed ga berib, xuddi o'sha tartibni qayta hosil qilasiz.
5. Lokal check va pre-push hook
5.1 npm run check
Kanonning yagona tekshiruv buyrug'i:
"check": "npm run tip && npm run lint && npm test && npm run build"To'rt qadam, && bilan: birinchisi yiqilsa, qolganlari ishlamaydi. Nega build ham? TESTLAR.md dagi qoida: Vitest kodni o'z transpilyatori (oxc) bilan o'giradi, nest build esa tsc bilan. Ular dekorator metama'lumotini va aylanma importlarni har xil qayta ishlaydi — Vitest'da o'tgan kod build'da yiqilishi mumkin. Prodakshnga build boradi, demak build ham tekshiriladi.
Kanonning yakuniy tekshiruvidagi vaqtlar (bitta yugurish): tip 7.4 s, lint 16.9 s, test 116.5 s, build 30.1 s. Testlar — vaqtning ~70 %.
5.2 Pre-push hook
Git hooklar darsida Husky bilan pre-commit hook qo'ygansiz. Butun check har commit'da — juda sekin (~3 daqiqa). Uning to'g'ri joyi — pre-push: commit'lar erkin, lekin serverga yuborishdan oldin to'liq tekshiruv. Kanonda hook yo'q; mana uning eng oddiy ko'rinishi va natijasi. Biz bo'sh repoda sinadik: check ataylab yiqiladigan qilib yozilgan (Git 2.54, Node 24.21.0):
#!/bin/sh
# .git/hooks/pre-push
echo "pre-push: npm run check"
npm run check --silent || {
echo "check yiqildi - push bekor qilindi"
exit 1
}pre-push: npm run check
test: 1 yiqildi
check yiqildi - push bekor qilindi
error: failed to push some refs to '../r.git'Hook nol bo'lmagan kod bilan chiqdi — Git push'ni bekor qildi va kod serverga ketmadi. Husky bilan xuddi shu buyruqlar .husky/pre-push fayliga yoziladi va repo orqali butun jamoaga tarqaladi.
Hook — yordamchi, qo'riqchi emas. git push --no-verify uni chetlab o'tadi, yangi klonlangan repoda esa (Husky'siz) u umuman yo'q. Majburiy tekshiruv joyi — CI.
6. Minimal CI
6.1 Fayl
GitHub Actions darsida birinchi workflow yozgansiz: checkout, Node, npm ci, npm run check. Backend uchun bir narsa yetishmaydi — xizmatlar: Postgres va Redis. GitHub Actions ularni services bilan konteyner sifatida ko'taradi.
Kanon fayli (izohlar qisqartirilgan, uzun options va run qatorlari YAML ichida bo'lingan — qiymatlari aynan; «Test bazalari» qadamida takrorlanuvchi manzil PG o'zgaruvchisiga olingan — buyruqlar bir xil, biz bash da solishtirib tekshirdik):
# .github/workflows/ci.yml — minimal CI: lokal `npm run check` bilan
# bir xil qadamlar, haqiqiy Postgres (pgvector) va Redis bilan.
# Push'da emas — qo'lda (workflow_dispatch); PR uchun `pull_request`
# ni yoqish mumkin. Sirlar yo'q: testlar tashqi API'ga bormaydi.
name: check
on:
workflow_dispatch:
# pull_request:
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
jobs:
check:
runs-on: ubuntu-24.04
timeout-minutes: 20
services:
postgres:
image: pgvector/pgvector:pg18
env:
POSTGRES_HOST_AUTH_METHOD: trust
ports: ["5432:5432"]
options: >-
--health-cmd "pg_isready -U postgres"
--health-interval 5s --health-timeout 5s
--health-retries 20
redis:
image: redis:8
ports: ["6379:6379"]
options: >-
--health-cmd "redis-cli ping"
--health-interval 5s --health-timeout 5s
--health-retries 20
env:
TEST_DATABASE_URL: postgres://postgres@127.0.0.1:5432/vazifalar_test
TEST_PRISMA_DATABASE_URL: postgres://postgres@127.0.0.1:5432/vazifalar_test_prisma
TEST_AUTH_DATABASE_URL: postgres://postgres@127.0.0.1:5432/vazifalar_test_auth
TEST_NAMUNA_DATABASE_URL: postgres://postgres@127.0.0.1:5432/vazifalar
TEST_REDIS_URL: redis://127.0.0.1:6379
steps:
- uses: actions/checkout@v7
- uses: actions/setup-node@v7
with:
node-version: 24
cache: npm
- run: npm ci
# test bazalari — Prisma migratsiyalari; namuna — seed bilan
- name: Test bazalari
run: |
PG=postgres://postgres@127.0.0.1:5432
for b in vazifalar_test vazifalar_test_prisma \
vazifalar_test_auth vazifalar; do
psql -h 127.0.0.1 -U postgres -c "CREATE DATABASE $b"
DATABASE_URL=$PG/$b npx prisma migrate deploy
done
DATABASE_URL=$PG/vazifalar npm run db:seed
# parallellik cheklangan: DB'ga tayangan testlar yuklangan
# mashinada beqaror bo'ldi (2 vCPU runner)
- run: npm run tip
- run: npm run lint
- run: npx vitest run --maxWorkers=2
- run: npm run build
- name: Migratsiyalar ↔ schema.prisma (drift bo'lmasin)
run: >-
DATABASE_URL=$TEST_DATABASE_URL
npx prisma migrate diff --from-config-datasource
--to-schema prisma/schema.prisma --exit-code
- name: Bog'liqliklar auditi
run: npm audit --omit=dev --audit-level=highenv dagi to'rtta ulanish satri 70 belgidan uzun — ular bo'linmadi, chunki URL'ni bo'lib bo'lmaydi. Oxiridan bitta qadamda kanon to'liq manzil yozgan; biz uning o'rniga job env idagi aynan o'sha qiymatli $TEST_DATABASE_URL ni qo'ydik. Action versiyalari — GitHub Actions darsidagidek @v7. O'z loyihangizda shu action'larning eng so'nggi asosiy versiyasini qo'ying.
6.2 Fayl bo'ylab
| Qism | Nima qiladi |
|---|---|
on: workflow_dispatch |
faqat qo'lda ishga tushadi (Actions sahifasidagi tugma yoki gh workflow run) |
concurrency |
bir tarmoqda yangi yugurish boshlansa, eskisi bekor bo'ladi |
services + options |
Postgres va Redis konteynerlari; --health-* — ular tayyor bo'lguncha qadamlar kutadi |
env |
testlar shu manzillardan bazani topadi — lokaldagi bilan bir xil o'zgaruvchilar |
| Test bazalari | to'rtta baza, migratsiyalar, namuna ma'lumoti (seed) |
| tip, lint, vitest, build | npm run check ning o'zi, faqat --maxWorkers=2 bilan |
| drift | schema.prisma va migratsiyalar farq qilsa — --exit-code qadamni yiqitadi |
| audit | prod bog'liqliklarida high darajali zaiflik bo'lsa — yiqiladi |
Postgres image — pgvector/pgvector:pg18, oddiy postgres:18 emas: Vektor bazalar va pgvector darsidagi migratsiya CREATE EXTENSION vector qiladi, oddiy image'da bu kengaytma yo'q.
Push'da emas, qo'lda — nega? GitHub Actions'ning bepul daqiqalari cheklangan, kursda tekshiruv lokal npm run check bilan qilinadi. PR'larda avtomatik ishlashi uchun # pull_request: izohini oching. CI narxi va byudjet — 34-qismda.
6.3 Halol: bu fayl nimani bilmaydi
Kanon bu faylni ishga tushirmagan — u faqat fayl. Shuning uchun uning ba'zi joylari tekshirilmagan:
- Seed va migratsiyadan qurilgan baza — sinalmagan. Kanon test bazalarini o'z skripti bilan
sql/fayllaridan quradi; CI'da esa Prisma migratsiyalari ishlatiladi. Ular bir xil sxema berishi tekshirilgan (farq 0 qator), lekin CI'dagi butun yo'l — yo'q. - MinIO va Mailpit yo'q — fayl, email, navbat testlari CI'da SKIP bo'ladi. «Darajalar va muhit» bo'limidagi saboq: yashil CI ≠ hammasi tekshirildi.
- Testcontainers va e2e — CI'da yo'q. Kanon ularni alohida yurgizadi; e2e (Playwright) bu qismda umuman yurgizilmadi — mashinada brauzerlar o'rnatilmagan, 31-qism frontendni o'zgartirmaydi.
- Audit qadami bugun qizil bo'lardi. Buni keyingi bo'limda ko'ramiz.
6.4 npm audit: haqiqiy natija
Kanon prod bog'liqliklarini tekshirdi (npm audit --omit=dev). Har bo'limda uch qatorga qarang: paket va versiya diapazoni, Severity (jiddiylik) va fix available ostidagi ogohlantirish:
# npm audit report
minimatch <11.0.1
Severity: moderate
minimatch has potential denial of service via globparts amplification - https://github.com/advisories/GHSA-g3hv-75wg-m249
fix available via `npm audit fix --force`
Will install archiver@4.0.2, which is a breaking change
node_modules/minimatch
readdir-glob *
Depends on vulnerable versions of minimatch
node_modules/readdir-glob
archiver >=5.0.0
Depends on vulnerable versions of readdir-glob
node_modules/archiver
multer 2.0.0 - 2.4.0
Severity: high
multer vulnerable to Denial of Service via a pending asynchronous fileFilter after request teardown - https://github.com/advisories/GHSA-q7qp-rjg7-q26m
fix available via `npm audit fix --force`
Will install @nestjs/platform-express@12.3.2, which is outside the stated dependency range
node_modules/multer
@nestjs/platform-express 10.4.18 - 10.4.22 || 11.1.2 - 12.2.0
Depends on vulnerable versions of multer
node_modules/@nestjs/platform-express
5 vulnerabilities (3 moderate, 2 high)
To address all issues (including breaking changes), run:
npm audit fix --forceBesh zaiflik, ikkitasi high. CI'dagi --audit-level=high bilan audit qadami yiqiladi. Ikkalasi ham 31-qism qo'shgan paket emas — 30-qismdan qolgan tranzitiv bog'liqliklar:
multer—@nestjs/platform-expressichida. Zaiflik fayl yuklashdagifileFilterda. Kanon fayllarnibusboybilan qabul qiladi, Nest'ningFileInterceptori ishlatilmaydi (Fayl yuklash darsi qarori). Ya'ni zaif kod yo'li loyihada chaqirilmaydi — lekin paket o'rnatilgan.minimatch—archiver→readdir-globzanjirida, eksport arxivi uchun.
npm audit fix --force ikkalasini "tuzatadi", lekin chiqishni o'qing: archiver ni 8.0.0 dan 4.0.2 ga tushiradi ("breaking change"), @nestjs/platform-express ni esa loyihadagi boshqa @nestjs/* paketlari (12.2.0) diapazonidan tashqariga chiqaradi. Semver darsidagi qoida: major o'zgarish — buzuvchi. Kanon --force qilmadi.
To'g'ri yo'llar: tuzatilgan patch versiya chiqishini kutish (masalan, butun @nestjs/* oilasini birga yangilash), package.json dagi overrides bilan tranzitiv paketni qotirish (sinalmagan) yoki vaqtincha istisno — sababi va muddati yozib qo'yilgan holda. Qaysi yo'l bo'lmasin, audit natijasini o'qish kerak: "high" har doim ham "bizda ekspluatatsiya qilinadi" degani emas, lekin buni har safar isbotlash kerak.
Tekshirib ko'ring: Hamkasbingiz CI qizil bo'lmasin deb audit qadamini o'chirib qo'ymoqchi. Yaxshiroq yechim bormi?
Javob
Bor. Qadamni o'chirish — signalni o'chirish: ertaga haqiqatan xavfli zaiflik ham ko'rinmaydi. Yaxshiroq: zaiflikni tahlil qilib (zaif yo'l loyihada chaqiriladimi), qarorni hujjatga yozish (docs/ da, sana va muddat bilan) va shu bitta maslahatni (advisory) istisno qilish yoki tuzatilgan versiyaga o'tish. Audit qadami esa boshqa zaifliklar uchun ishlayveradi.
7. Ko'p uchraydigan xatolar
| Xato | Oqibati | To'g'risi |
|---|---|---|
| Beqaror testni "qayta yurgizamiz" deb qoldirish | ishonch yo'qoladi, haqiqiy xato ham o'tib ketadi | sabab — vaqt, tartib, holat; tuzatish yoki karantin |
| Hamma timeout'ni oshirish | haqiqiy osilish kech ko'rinadi | o'lchangan, faqat sekin test uchun chegara |
| Mutlaq vaqt chegarasi yuklangan muhitda | CI'da yolg'on qizil | nisbiy chegara yoki taqqoslash |
| Parallel testlar umumiy bazada | bir-birini buzadi | har fayl — o'z bazasi, prefiksi |
| Yashil natijada SKIP soniga qaramaslik | yarim to'plam ishlamagan | SKIP sonini kuzatish |
CI'da build siz |
Vitest o'tadi, tsc yiqiladi |
check ning hamma qadami |
| Audit qizil — qadamni o'chirish | signal yo'qoladi | tahlil, hujjatlangan istisno |
npm audit fix --force ni o'qimasdan |
major versiya o'zgaradi | chiqishni o'qish, alohida PR |
8. Mashqlar
Mashqlar kurs/mashqlar/31/34-ci/ da. 2- va 3-mashq yechimlari Node 24.21.0 da tekshirilgan (biz ishga tushirdik).
1-mashq (oson): bo'shliqlarni to'ldiring
- Vitest ishchilar sonini belgilovchi bayroq —
--max - Testlarni tasodifiy tartibda yurgizish —
--sequence. - Kanon CI faylidagi Postgres image —
pgvector/pgvector:pg checkskriptidagi to'rtinchi qadam —npm run- Push'dan oldin ishlaydigan Git hook —
Yechim
- Workers —
--maxWorkers=2(CI faylida). - shuffle — urug'ni
--sequence.seedtakrorlaydi. - 18 —
CREATE EXTENSION vectoruchun pgvector image. - build — Vitest (oxc) va
tscfarqi uchun. - pre-push —
--no-verifybilan chetlab o'tiladi, shuning uchun CI ham kerak.
2-mashq (o'rta): beqaror testlarni ajratish
Bir xil kod bilan to'plam besh marta yurgizildi. Har test uchun natijalar massivi berilgan (true — o'tdi). ajrat(natijalar) funksiyasini yozing: testlarni uch guruhga bo'lsin — barqaror (hammasi o'tdi), buzilgan (hammasi yiqildi), beqaror (aralash, o'tish foizi bilan). Ishora: every, filter (filter), Object.entries.
Yechim
function ajrat(natijalar) {
const g = { barqaror: [], buzilgan: [], beqaror: [] };
for (const [nom, r] of Object.entries(natijalar)) {
if (r.every(Boolean)) g.barqaror.push(nom);
else if (r.every((x) => !x)) g.buzilgan.push(nom);
else {
const otdi = r.filter(Boolean).length;
const foiz = Math.round((otdi / r.length) * 100);
g.beqaror.push(`${nom} (${foiz} % o'tdi)`);
}
}
return g;
}
console.log(ajrat({
"asinxron: retry": [true, true, true, true, true],
"telegram: dialog": [true, false, true, true, false],
"auth: timing": [true, true, true, false, true],
"shartnoma: snapshot": [false, false, false, false, false],
}));Konsolda:
{
barqaror: [ 'asinxron: retry' ],
buzilgan: [ 'shartnoma: snapshot' ],
beqaror: [ "telegram: dialog (60 % o'tdi)", "auth: timing (80 % o'tdi)" ]
}Ma'lumot namuna uchun o'ylab topilgan. buzilgan guruhi beqaror emas — u har safar yiqiladi va oddiy xato kabi tuzatiladi (ehtimol surat eskirgan). Beqarorlar esa sabab qidirishni talab qiladi. beqaror qatoridagi satrlar qo'shtirnoqda — ichida apostrof bor.
3-mashq (qiyin): fayllarni ishchilarga taqsimlash
CI'da testlarni bir nechta mashinaga (shard) bo'lish mumkin. Har fayl yugurish vaqti ma'lum bo'lsin. Eng yaxshi oddiy usul: fayllarni eng uzunidan boshlab olib, har birini hozir eng bo'sh ishchiga berish. taqsimla(fayllar, n) funksiyasini yozing. U har ishchining fayllari va jami vaqtini qaytarsin. Oxirida eng band ishchining vaqtini chiqaring — butun yugurish shuncha davom etadi. Namuna fayllar va 2, 3 ishchi bilan sinang. Ishora: toSorted (toSorted), reduce.
Yechim
function taqsimla(fayllar, n) {
const ishchilar = Array.from({ length: n },
() => ({ fayllar: [], s: 0 }));
for (const f of fayllar.toSorted((a, b) => b.s - a.s)) {
const bosh = ishchilar.reduce((a, b) => (b.s < a.s ? b : a));
bosh.fayllar.push(f.nom);
bosh.s += f.s;
}
return ishchilar;
}
const fayllar = [
{ nom: "navbat", s: 14 }, { nom: "auth", s: 12 },
{ nom: "prisma-ombor", s: 11 }, { nom: "telegram-bot", s: 6 },
{ nom: "shartnoma", s: 5 }, { nom: "api", s: 4 },
{ nom: "asinxron", s: 1 },
];
for (const n of [2, 3]) {
const r = taqsimla(fayllar, n);
for (const [i, x] of r.entries()) {
console.log(`${n} ishchi, #${i + 1}: ${x.s} s —`,
x.fayllar.join(", "));
}
console.log(` yugurish: ${Math.max(...r.map((x) => x.s))} s`);
}Konsolda:
2 ishchi, #1: 26 s — navbat, telegram-bot, shartnoma, asinxron
2 ishchi, #2: 27 s — auth, prisma-ombor, api
yugurish: 27 s
3 ishchi, #1: 18 s — navbat, api
3 ishchi, #2: 18 s — auth, shartnoma, asinxron
3 ishchi, #3: 17 s — prisma-ombor, telegram-bot
yugurish: 18 sVaqtlar namuna uchun o'ylab topilgan. Jami 53 s: ideal holatda 2 ishchi 26.5 s, 3 ishchi 17.7 s ga tushardi — taqsimot idealga juda yaqin (27 va 18 s). Lekin ishchilar soni qancha bo'lmasin, yugurish 14 soniyalik navbat dan qisqa bo'lmaydi: eng uzun fayl — pastki chegara. Kanon o'lchovidagi "ishchilar ko'p — tezlik oz" ning yana bir sababi shu.
9. Loyiha qadami: yakuniy tekshiruv va commit
9.1 Bu darsdagi o'zgarishlar
Loyihaning yakuniy bosqichida qolgan beshta o'zgarish:
test/konteyner.test.ts— Testcontainers testi 31-qism sxemasiga moslandi:
- const k = await new PostgreSqlContainer("postgres:18")
+ const k = await new PostgreSqlContainer("pgvector/pgvector:pg18")- });
+ }, 180_000);- assert.deepEqual(s, { trg: 5, mv: 1, rls: 13 });
+ assert.deepEqual(s, { trg: 8, mv: 1, rls: 16 });Birinchisi — pgvector kengaytmasi uchun. Ikkinchisi — beforeAll (konteyner ko'tarish + migratsiyalar) chegarasi 30 s dan 180 s ga: kanon izohiga ko'ra yuklangan mashinada migratsiyalar 30 s hook chegarasidan oshib ketgan. Bu ham «Chegarani oshirish — qachon to'g'ri» bo'limidagi holat: chegara faqat shu bitta qimmat hook uchun. Uchinchisi — sxemadagi yangi obyektlar: +3 trigger (vazifa hodisalari, audit jurnalini o'zgartirishni taqiqlovchi ikkita) va +3 RLS jadvali (vazifa hodisalari, embeddinglar, AI sarfi). Testcontainers testi sxemaning "shaklini" sanab tekshiradi — yangi jadval qo'shib, RLS'ni unutsangiz, shu yerda yiqiladi.
package.json— versiya va yangi skript:
- "version": "4.0.0-alfa.4",
+ "version": "4.0.0","test:aralash": "vitest run --sequence.shuffle".github/workflows/ci.yml— «Minimal CI» bo'limidagi fayl.TESTLAR.md— "31-qism (prodakshn va AI) testlari" bo'limi: har yangi test fayli bir qatorda (statistika,saqlash,ai,ai-qidiruv,ai-nazorat,mcp,prodakshn,kuzatuv,chidamlilik,cheklov-redis,asinxron,shartnoma),test:aralashva CI haqida eslatma.README.md— "Prodakshn va AI (31-qism, v4)" bo'limi: AI xususiyatlari, MCP server, ma'lumotlar (hodisalar, saqlash muddati, audit), kuzatuv (/health/*,/metrics).
Oldingi uch darsdagi test/asinxron.test.ts va test/shartnoma.test.ts (surati bilan) ham shu commit'ga kiradi.
9.2 Yakuniy tekshiruv
npm run check
TESTCONTAINERS=1 npx vitest run test/konteyner.test.tsKanon yakuniy tekshiruvi (Docker'dagi PostgreSQL 18.6 + pgvector, Redis, MinIO, Mailpit; haqiqiy vazifalar_api, vazifalar_auth, vazifalar_ishchi rollari):
--- npm run tip
exit 0 (7411 ms)
--- npm run lint
exit 0 (16927 ms)
--- npm run build
exit 0 (30148 ms)
--- npm run test
↓ |asosiy| test/konteyner.test.ts (1 test | 1 skipped)
Test Files 67 passed | 1 skipped (68)
Tests 339 passed | 1 skipped (340)
exit 0 (116484 ms)
--- Testcontainers (TESTCONTAINERS=1): [Testcontainers vaqtlari] konteyner 2064 ms, migratsiya 3638 ms, snapshot 385 ms, restore (oxirgi) 192 ms Tests 10 passed (10) ; tc qoldiqlari: 0
--- prisma migrate deploy (yangi baza): 26 migrations found in prisma/migrations The following migration(s) have been applied: All migrations have been successfully applied.
--- schema.prisma ↔ migratsiyalar (migrate diff): []
--- migratsiyalar va sql/ sxemasi farqi (pg_dump, _prisma_migrations'siz): 0 qator(Kanon faylidan; uchta yugurishning sarlavha qatorlari olib tashlangan, yorliqlar qisqartirilgan. tc qoldiqlari: 0 — testdan keyin o'chirilmay qolgan Testcontainers konteynerlari yo'q.) Nima bo'ldi? Har qadam exit 0 bilan tugadi, 340 testdan faqat alohida yuradigan bittasi SKIP, u ham o'z yugurishida 10/10. Migratsiyalar uch xil tekshiruvda bir xil sxema berdi.
| Tekshiruv | Natija |
|---|---|
| tip / lint / build | 0 / 0 / 0 |
| Vitest (68 fayl) | 339 o'tdi, 1 SKIP (konteyner — alohida 10/10) |
| Testcontainers | 10/10, migratsiya 3.6 s |
| Migratsiyalar | 26 ta, schema.prisma bilan farq yo'q, sql/ bilan farq 0 qator |
| Jonli (uch saqlash rejimi, haqiqiy rollar) | kutilgan status kodlari: 200, 201, 204, 401, 404, 409, 412 va boshqalar |
Docker'siz bo'lsangiz, «Darajalar va muhit» bo'limidagi natijani ko'rasiz: 44 fayl o'tadi, 24 tasi SKIP. Bu ham to'g'ri natija — faqat qaysi qismi tekshirilmaganini bilasiz.
9.3 Commit
git add -A
M="test: asinxron (soxta soat), OpenAPI snapshot va iste'molchi"
M+=" shartnomasi, Testcontainers pgvector; ci: workflow fayli"
M+=" (qo'lda); chore: v4.0.0"
git commit -m "$M"git status ga qarang: .env, dist/, coverage/ kirmasin. docs/openapi-snapshot.json esa kirsin — u shartnomaning bir qismi.
Ixtiyoriy: versiyaga teg qo'ying (Tag va relizlar) — git tag v4.0.0. 31-qism shu bilan tugaydi.
10. 31-qism yakuni: nima qurildi
31-qism boshida vazifalar-api NestJS 12 da ishlaydigan, 25–29-qismlarning hamma imkoniyatiga ega API edi. Endi u v4.0.0:
| Yo'nalish | Loyihada | Tajriba (loyihaga kirmadi) |
|---|---|---|
| Ma'lumotlar bazasi | oyma-oy bo'limli vazifa hodisalari, BRIN, statistika; maxfiylik hujjati (docs/MAXFIYLIK.md), saqlash muddati, hisobni o'chirish va anonimlashtirish |
SQLite, MySQL, replika va failover, PITR, sharding, TLS va shifrlash, CDC |
| AI | vazifani qadamlarga bo'lish (JSON va SSE), semantik va gibrid qidiruv (pgvector), RAG yordamchi, zaxira model, kvota va kesh, MCP server | xom LLM so'rovlari, AI SDK, nutq va rasm |
| Prodakshn naqshlari | audit jurnali (hash zanjiri), feature flag'lar, graceful drain, /health/startup, /metrics, retry / circuit breaker / bulkhead (umumiy breaker — ochiq xato, Resilience naqshlari), Redis cheklagichi |
soft delete extension, multi-tenancy, OTel eksport |
| Test | soxta soat testlari, OpenAPI surati va iste'molchi shartnomasi, beqaror testlar tuzatildi, CI fayli | yuklama o'lchovi, parallellik o'lchovi |
Raqamlarda (kanon tekshiruvlari, 31-qism boshi → oxiri):
| Boshida | Oxirida | |
|---|---|---|
| Vitest | 296 o'tdi, 2 yiqildi (beqaror) | 339 o'tdi, 0 yiqildi |
| Migratsiyalar | 20 | 26 |
| Prod bog'liqliklar | 41 | 43 (@modelcontextprotocol/sdk, prom-client) |
Ikki yangi paket: @modelcontextprotocol/sdk — MCP server uchun, prom-client — metrikalar uchun. AI qatlami, flag'lar, circuit breaker va cheklagich — o'z kodimiz, paketsiz; har tanlov o'lchov bilan asoslandi.
Bu qismdagi eng qimmatli material — kanon topgan haqiqiy xatolar. 30-qismdan beri ishlamagan eksport buyrug'i. Prisma bo'limli jadvalni "o'chirmoqchi" bo'lgan migratsiya farqi. pgvector filtrli qidiruvda 0 natija. temperature: 0 da ham har xil javob beruvchi LLM. Va bu darsdagi to'rtta beqaror test. Ularning hech biri kitobda yozilmagan edi — hammasi o'lchov va tekshiruv bilan topildi.
Keyingi qism
Kod tayyor, testlar ishonchli — lekin bitta odam yozgan. 32-qism — Professional Git va jamoada ishlash. U Bisect: xatoni kiritgan commitni topish bilan boshlanadi: 339 ta test borligida regressiyani qaysi commit kiritganini git bisect run npm test ikkiga bo'lib-bo'lib bir necha qadamda topadi. Keyin — reliz avtomatikasi va CHANGELOG, jamoa workflow'lari, commit imzolash, yaxshi PR va code review. Bu darsdagi CI fayli va check shu jamoaviy ishning poydevori bo'ladi.
11. Real ishda
- Qayerda uchraydi: har jamoada "CI qizil — kim buzdi?" savoli. Katta loyihalarda beqaror testlar alohida kuzatiladi (karantin, beqarorlik hisoboti), CI vaqti esa jamoa unumdorligining o'lchovi.
- Vositalar: GitHub Actions (
services,concurrency,matrix), Vitest--shard,--sequence.shuffle,--retry; Husky va lefthook; Dependabot va Renovate (bog'liqliklarni yangilash),npm auditva OSV-Scanner. - Intervyu savollari: "Beqaror testni qanday topasiz va tuzatasiz?", "Testlarni parallel ishlatganda nimaga e'tibor berasiz?", "CI pipeline'ingizda qanday qadamlar bor va nega shu tartibda?", "
npm auditqizil — nima qilasiz?"
Xulosa
- Testlar muhitga ko'ra tashkil qilinadi: bazasizlari doim, xizmat kerak bo'lganlari — mavjud bo'lsa; yashil natijada SKIP soniga qarang.
- Parallellik izolyatsiyani talab qiladi (har faylga o'z bazasi, prefiksi); kanonda 4 → 16 ishchi atigi 23 % tezlashtirdi — tor joy umumiy resurslar.
- Beqaror test sabab bilan tuzatiladi: kanonning to'rtta hodisasi — "javob ≠ holat", o'lchangan chegaralar, mutlaq → nisbiy chegara.
npm run check(tip, lint, test, build) — lokal; pre-push hook — yordamchi; majburiy tekshiruv — CI.- Kanon CI fayli ishga tushirilmagan: seed yo'li sinalmagan, MinIO/Mailpit testlari u yerda SKIP, audit qadami bugun 2 ta
highzaiflik bilan qizil —--forceqilinmaydi. - 31-qism yakuni:
vazifalar-apiv4.0.0 — 339 test, 26 migratsiya, AI va prodakshn naqshlari, o'lchov bilan asoslangan qarorlar.
Keyingi dars: Bisect: xatoni kiritgan commitni topish — 32-qism boshlanadi: regressiyani kiritgan commit'ni testlar yordamida avtomatik topamiz.
Manbalar
- Vitest hujjati — Improving Performance (parallellik,
maxWorkers): https://vitest.dev/guide/improving-performance (sinalmagan URL, 2026-11) - Vitest hujjati —
sequence.shuffle,sequence.seed: https://vitest.dev/config/sequence#sequence-shuffle - Vitest hujjati — Projects: https://vitest.dev/guide/projects (sinalmagan URL, 2026-11)
- GitHub Docs — Docker service containers: https://docs.github.com/en/actions/tutorials/use-containerized-services/use-docker-service-containers
- GitHub Docs — Control workflow concurrency: https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/control-workflow-concurrency
- Vitest hujjati —
maxWorkers(sukut — mavjud parallellik): https://vitest.dev/config/maxworkers - Git hujjati — githooks, pre-push: https://git-scm.com/docs/githooks#_pre_push (sinalmagan URL, 2026-11)
- npm hujjati —
npm audit: https://docs.npmjs.com/cli/v11/commands/npm-audit (sinalmagan URL, 2026-11) - npm hujjati —
overrides: https://docs.npmjs.com/cli/v11/configuring-npm/package-json#overrides (sinalmagan, 2026-11) - GitHub Advisory — multer GHSA-q7qp-rjg7-q26m: https://github.com/advisories/GHSA-q7qp-rjg7-q26m (sinalmagan URL, 2026-11)
- GitHub Advisory — minimatch GHSA-g3hv-75wg-m249: https://github.com/advisories/GHSA-g3hv-75wg-m249 (sinalmagan URL, 2026-11)
- Kanon (IlmHamroh, 2026-11-02 — 11-03): 31-qism boshidagi va yakuniy tekshiruvlar, parallellik o'lchovi, beqaror testlar tuzatishlari,
npm auditchiqishi,.github/workflows/ci.yml(ishga tushirilmagan). - Biz ishga tushirdik (2026-11-03, Vitest 5.0.5, Node 24.21.0, Git 2.54): bazasiz to'liq yugurish,
--sequence.shuffle, pre-push hook, CI faylini YAML vabashda solishtirish. Brauzer modellari va mashqlar — Node 24.21.0.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!