Poarta e o singură comandă

ForkTex Engineering · 5 septembrie 2026 · 3 min

Fiecare repository în care lucrăm răspunde la aceeași întrebare, în același fel: e gata această schimbare?

Răspunsul e make ci. Nu o listă de verificare, nu un fișier de workflow, nu o conversație. O comandă, pe care un dezvoltator o rulează pe laptop și CI o rulează neschimbată.

De ce o singură comandă

Alternativa e familiară. Logica de calitate se acumulează într-o configurare de CI. Un pas de lint aici, un prag de acoperire acolo, o matrice de build care a crescut un flag în plus în timpul unui incident. Fiecare adăugire e rezonabilă. Rezultatul e că singurul mod de a ști dacă o schimbare trece e s-o trimiți și să aștepți.

Asta are două costuri. Cel evident e latența: un du-te-vino de cinci minute ca să descoperi o eroare de formatare. Cel mai subtil e că verificările încetează să mai fie inspectabile. O regulă care trăiește într-un fișier de workflow e o regulă pe care majoritatea echipei n-a citit-o niciodată și n-o poate rula. Când eșuează, remedierea e ghicit pe baza unui log.

Deci inversăm asta. Fiecare verificare e o țintă numită într-un Makefile. CI instalează un toolchain și invocă poarta. Ea nu conține nicio logică de calitate proprie, și asta e proprietatea care merită protejată: dacă CI poate eșua dintr-un motiv pe care nu-l poți reproduce local, poarta are o gaură în ea.

Atomii

Țintele sunt deliberat plictisitoare și numite consistent între repository-uri:

AtomCe face
installDependințe din lockfile
format-checkFormatare, verificată, nu aplicată
lintAnaliză statică
typecheckTipuri, fără emisie
testSuita
codegen-checkRegenerează artefacte derivate și compară
auditVulnerabilități ale dependințelor
ciToate cele de mai sus, în ordine

Consistența între repository-uri e cea mai mare parte a valorii. Un inginer care se mută între proiecte n-are nevoie să învețe un vocabular nou ca să afle cum e construit ceva. Numele atomului e interfața; ce rulează efectiv ținta e implementarea, și poate diferi.

Două reguli țin numele oneste. Un atom care numește o țintă fără nicio rețetă e o afirmație fără nimic în spate, așa că fiecare atom declarat trebuie să ruleze efectiv. Și același nume de atom înseamnă același lucru peste tot. test nu înseamnă teste unitare într-un repo și o suită de fum în altul.

Nu există „trece local"

O schimbare e propusă ca fiind completă după ce poarta trece. Nu după testele pe care autorul și-a amintit să le ruleze.

Asta sună evident și e încălcată de rutină într-un mod anume: excluderea unei verificări ca să treacă ceva. O regulă de lint se declanșează pe o linie care e în regulă, așa că intră un ignore per fișier, iar schimbarea e lansată.

O verificare exclusă nu se mai întoarce. Nimeni nu revizitează o suprimare, pentru că nimic n-o scoate la iveală. Excluderea supraviețuiește motivului pentru care a fost făcută, iar următorul autor moștenește o poartă cu o gaură pe care n-o poate vedea și n-a acceptat-o.

Obiceiul care o înlocuiește e de obicei să repari lucrul spre care arăta regula. Când un linter obiectează la un tip prea larg, numește tipul. Regula avea dreptate; suprimarea a fost doar mai rapidă.

Există excluderi legitime. Ele poartă un motiv, iar motivul e scris exact acolo unde e excluderea, nu într-un mesaj de commit pe care nimeni nu-l va mai citi.

Testele rulează pe infrastructură reală

O alegere din interiorul porții merită apărată, pentru că e mai lentă și o facem oricum.

Testele de bază de date rulează pe o bază de date reală, pornită într-un container pentru suită. Nu un înlocuitor în memorie, nu o sesiune mock.

Un mock codifică ce credem noi că face driverul. Aproape fiecare bug care merită prins la acest strat trăiește exact acolo unde acea credință e greșită. o constrângere care se declanșează diferit decât te aștepți, o graniță de tranzacție care nu se imbricare cum sugerează documentația, un tip care face round-trip cu pierderi. Un test mock e de acord cu presupunerea care a produs bug-ul, ceea ce e cel mai puțin util lucru pe care l-ar putea face.

Costul e real: pornirea containerului face suita mai lentă la început. Cumpără teste care eșuează atunci când și producția ar eșua, ceea ce e singura proprietate pentru care o suită de teste chiar există.

Ce nu face poarta

Nu comite. Nu trimite. Nu decide că munca e terminată. Decide că munca e *propozabilă*.

Distincția asta contează când agenții scriu cod, ceea ce fac din ce în ce mai mult. Poarta e ce face o schimbare scrisă de o mașină verificabilă în aceiași termeni ca una umană: verificările au rulat, au trecut, iar persoana care citește diferența poate reproduce asta cu o singură comandă.