---
title: "Deploy sigur: dry-run implicit, verificare de paritate și controlul a ce s-a publicat de fapt"
description: "O comandă de deploy reușită dovedește că a avut loc un transfer, nu ce s-a transferat. Facem deploy-urile sigure cu trei obiceiuri: orice script de deploy rulează în dry-run dacă nu primește --apply, o verificare zilnică de paritate compară fișierele de pe server cu git, iar după publicare comparăm sursa servită și corpul răspunsurilor cu ce voiam să livrăm."
date: 2026-10-11
lang: ro
canonical: https://goingstellar.ro/ro/metode/deploy-sigur-dry-run-paritate/
author: Going Stellar
publisher: GOING STELLAR S.R.L.
topic: Inginerie / Deploy
license: CC BY 4.0
alternate_en: https://goingstellar.ro/methods/safe-deploys-dry-run-parity-checks/
---

# Deploy sigur: dry-run implicit, verificare de paritate și controlul a ce s-a publicat de fapt

*O comandă de deploy reușită dovedește că a avut loc un transfer, nu ce s-a transferat. Facem deploy-urile sigure cu trei obiceiuri: orice script de deploy rulează în dry-run dacă nu primește --apply, o verificare zilnică de paritate compară fișierele de pe server cu git, iar după publicare comparăm sursa servită și corpul răspunsurilor cu ce voiam să livrăm.*

> Inginerie · Deploy · 2026-10-11 · https://goingstellar.ro/ro/metode/deploy-sigur-dry-run-paritate/

## Pe scurt

- Un deploy sau un push reușit dovedește că a avut loc un transfer, nu ce s-a transferat; compară sursa servită de server cu sursa locală după fiecare deploy.
- Scripturile de deploy trebuie să ruleze implicit în dry-run și să ceară un --apply explicit, mai ales când șterg fișiere de pe server.
- Un deploy publică tot ce e pe disc, deci nu face deploy cât timp altă persoană sau alt agent scrie în același arbore de surse.
- Un cod de status 200 dovedește că serverul a răspuns, nu ce a răspuns; o aplicație single-page întoarce 200 cu pagina de index pentru orice cale necunoscută.
- Să livrezi cod pe o platformă și ca platforma să știe că există o funcție programată nouă sunt două fapte diferite; reînregistrează aplicația după fiecare deploy în producție și pică zgomotos dacă înregistrarea e refuzată.

## Ce înseamnă un deploy sigur

Un deploy sigur este unul în care știi, înainte și după, exact ce s-a schimbat pe server. Practic înseamnă trei obiceiuri: orice script de deploy rulează **implicit în dry-run** și are nevoie de un `--apply` explicit ca să scrie; o **verificare de paritate** compară fișierele de pe server cu sursa din git și semnalează orice diferență; iar după publicare **verifici ce se servește de fapt**, citind conținutul, nu codurile de status.

O comandă de deploy reușită dovedește că a avut loc un transfer. Nu dovedește ce s-a transferat, dacă platforma a aflat de el sau dacă altceva de pe server s-a schimbat ca efect secundar. Fiecare regulă de mai jos vine dintr-un incident în care deploy-ul a raportat succes.

## Pasul 1: dry-run implicit

Dry-run este modul în care scriptul de deploy listează ce ar copia și ce ar șterge, fără să atingă serverul. Scriptul de deploy al site-ului nostru construiește întâi site-ul din surse, apoi cheamă `rsync` cu `--checksum --delete --dry-run`, dacă nu primește `--apply`. Construcția la început contează: fișierele publicate trebuie să vină din surse, nu din ce a rămas pe disc de la rularea trecută. Opțiunea `--delete` scoate de pe server fișierele care nu mai există local, și tocmai de aceea dry-run-ul e implicit: citești lista de ștergeri înainte să apeși.

Scriptul de deploy de pe server pentru uneltele interne urmează aceeași regulă: dry-run implicit, o copie de rezervă pentru fiecare fișier înlocuit și `git pull --ff-only`, ca serverul să nu facă niciodată singur merge sau să rescrie istoricul.

## Pasul 2: deploy doar dintr-un arbore cunoscut și liniștit

**Un deploy publică tot ce e pe disc, inclusiv munca neterminată a altcuiva.** Unul dintre scripturile noastre sincroniza tot arborele de lucru cu `rsync --delete`. Am făcut deploy de **șase** ori într-o sesiune și, fără să atingem vreun fișier al lui, am publicat munca în curs a altui agent AI care lucra în paralel pe același proiect. Migrarea lui de bază de date rulase deja în producție. Build-ul a trecut, verificarea de sănătate a răspuns, deci nimic nu a semnalat problema; proiectul nu era în git, așa că nu exista nici un `git status` care să ne avertizeze.

**Nu face deploy cât timp un flux paralel scrie în fișierele sursă.** Într-o dimineață, două versiuni ale add-on-urilor noastre pentru Google Workspace au fost publicate cu conținut greșit: una avea fișierul de panou al altui add-on, cealaltă o sondă de depanare vizibilă în panou. Agenți paraleli puneau și scoteau fișiere în același folder, iar câteva secunde fiecare fișier conținea altceva. `clasp push` a raportat succes, pentru că transferul chiar mersese.

Înainte de primul deploy într-un proiect comun listăm acum fișierele modificate azi și verificăm cine le-a scris, anunțăm cealaltă sesiune înainte de deploy, nu după, și verificăm coliziunile în numerotarea migrărilor. Scriptul de deploy refuză să pornească dacă aplicația are modificări necomise.

## Pasul 3: paritate între git și server

O verificare de paritate compară fiecare fișier publicat pe server cu același fișier din ramura principală și raportează orice fișier diferit. De la diferența dintre ce spune git și ce rulează au pornit cele mai multe probleme ale noastre de deviere: fișiere copiate de mână cu `scp` care nu s-au mai întors în git, sau reparații făcute direct pe server și pierdute la următorul deploy.

Unealta noastră de paritate află fișierele publicate din arborele git, rulează zilnic și trimite email doar când un fișier devine divergent. La prima rulare toate cele **21** de fișiere publicate erau identice, adică exact starea pe care voiam s-o păstrăm. Regula care decurge de aici e simplă: deploy-ul corect este scriptul condus de git, nu o copiere de mână.

## Pasul 4: verifică ce s-a publicat de fapt

**Compară sursa servită cu sursa locală, fișier cu fișier.** După incidentul cu add-on-urile, scriptul nostru de deploy pentru add-on-uri citește codul servit de platformă după push și după crearea versiunii, îl compară cu fișierele locale și se oprește înainte să mute deployment-urile dacă diferă ceva. La prima rulare, garda a găsit o a doua contaminare, pe alt add-on, pe care nici nu o căutam.

**Citește corpul răspunsului, nu codul de status.** Am raportat odată că o descriere de API și o pagină de documentație de pe unul dintre serverele noastre sunt publice, doar pe baza unui status 200. Ambele răspunsuri erau pagina de index a aplicației single-page, servită ca rezervă pentru orice cale necunoscută. Întrebat direct, serviciul răspundea 401. Un cod de status spune că serverul a răspuns, nu ce a răspuns.

**Verifică dacă platforma știe de codul nou.** O funcție programată pe o platformă de joburi în fundal a fost livrată după ultima înregistrare a aplicației la platforma respectivă. Codul era în pachetul publicat, trecea verificarea de tipuri și mergea când era chemat de mână, dar nu a rulat niciodată după program timp de **4** luni. Cele **64** de rulări manuale din log erau perfect compatibile cu o funcție de care planificatorul nu auzise. Reînregistrarea a produs primele rulări programate în **10** minute; acum un pas din pipeline-ul de deploy reînregistrează aplicația după fiecare deploy în producție și pică zgomotos dacă înregistrarea e refuzată.

## Capcanele de shell care au transformat un pas sigur într-o schimbare live

**O comandă de test poate modifica producția.** Un agent a testat ca root, cu binarul sistemului, o configurație temporară de server web. Rularea de test a recreat directoarele temporare ale serverului și le-a dat utilizatorului implicit fără privilegii, pentru că fișierul de test nu numea niciun utilizator. Procesele reale nu mai puteau scrie corpurile cererilor, așa că orice webhook mare primea 500, timp de circa cinci ore: 100.893 de webhook-uri de actualizare a comenzilor au eșuat, iar **84** de comenzi nu au mai ajuns. Logul aplicației nu arăta nimic, pentru că cererile nu ajungeau la aplicație; indiciul a fost un 500 cu corp de **186** de octeți, adică pagina de eroare a serverului web. Configurațiile de test rulează acum într-un container de unică folosință.

**Punctul și virgula nu moștenește eșecul lui `&&`.** O comandă pe un rând lega cu `&&` un `cd` într-un worktree nou, apoi rula un patch după un `;`. Crearea worktree-ului a eșuat, `cd`-ul nu s-a făcut, iar patch-ul a intrat în arborele live din care publică scriptul de deploy. Nu a rulat niciun deploy până să observăm și să refacem fișierele. Pașii care scriu stau acum într-un script cu `set -euo pipefail` și cu o gardă care verifică directorul curent înainte de prima scriere.

**`ssh` într-o buclă înghite lista.** Fără `-n`, `ssh` citește intrarea standard, deci prima iterație a înghițit restul fișierului. Un job a pregătit **trei** loturi și l-a trimis doar pe primul, fără nicio eroare. Folosește `ssh -n`, citește bucla de pe alt descriptor și numără la final: o buclă care procesează mai puțin decât a primit trebuie să iasă cu cod nenul. Testează buclele cu cel puțin **2** elemente.

**Codul nu trece niciodată printr-un nivel de citare de shell.** Un script trimis prin `ssh '...'` cu heredoc și-a pierdut tăcut toate ghilimelele simple; ni s-a întâmplat de **trei** ori, ultima dată cu SQL. Scrii fișierul local, îi verifici sintaxa, îl copiezi cu `scp`, apoi îl rulezi.

## Unde am greșit

I-am spus recenzentului că sonda de depanare nu ajunsese la utilizatori, pe baza lui `git log`. Nu avea cum să apară acolo: sonda nu fusese niciodată comisă. Absența din git nu dovedește absența din producție. Dovada este sursa servită de server.

Scriptul de deploy al propriului site se termină încă prin a afișa codurile de status pentru **20** de pagini. Pentru un site static, un 404 spune ceva, dar un 200 nu dovedește că acolo e conținutul nou, aceeași lecție ca la pagina de rezervă de mai sus. Descrierea cinstită: pasul acesta prinde paginile lipsă, nu pe cele vechi.

## Limitele metodei

Dry-run-ul, paritatea și compararea sursei servite îți spun ce s-a schimbat și dacă se potrivește cu git. Nu îți spun că sursa din git e corectă și nu acoperă efecte secundare din afara fișierelor publicate, cum ar fi o migrare care a rulat deja sau o comandă de test care a schimbat proprietarul unor directoare. Paritatea acoperă doar fișierele pe care le cunoaște; o configurație editată direct pe server îi rămâne invizibilă dacă nu e urmărită.

## Listă de verificare

**1. Întâi dry-run.** Construiești din surse, citești copierile și ștergerile, apoi dai `--apply`.

**2. Arbore liniștit.** Niciun flux paralel care scrie în surse; nicio modificare necomisă; fișierele modificate recent verificate.

**3. Paritate.** Fișierele de pe server coincid cu ramura principală; deploy prin scriptul condus de git, niciodată prin copiere de mână.

**4. Conținut servit.** Compari sursa servită cu cea locală; citești corpul răspunsurilor; confirmi că platforma a înregistrat funcțiile noi.

**5. Igienă de shell.** `set -euo pipefail`, gardă pe director înainte de scriere, `ssh -n` în bucle, numărarea elementelor procesate, niciun cod trecut prin citare de shell, nicio configurație de test pe gazde de producție.

## Întrebări și răspunsuri

### Ce înseamnă dry-run implicit pentru un script de deploy?

Înseamnă că scriptul, rulat fără opțiuni, doar listează ce ar copia și ce ar șterge pe server și nu schimbă nimic. Publicarea cere o opțiune explicită, de exemplu --apply. Contează cel mai mult când scriptul șterge fișiere pe server, cum face rsync cu --delete, pentru că citești lista de ștergeri înainte să dispară ceva. Construiește întâi din surse, ca lista să reflecte sursele, nu fișiere vechi.

### Ce este o verificare de paritate la deploy?

O verificare de paritate compară fiecare fișier publicat pe server cu același fișier din ramura principală a depozitului și raportează orice diferență. Prinde devierile venite din fișiere copiate de mână sau din reparații făcute direct pe server și necomise. Rulează programat și alertează doar când un fișier devine divergent, astfel încât prima rulare curată devine baza pe care o protejezi.

### Cum verific ce s-a publicat de fapt?

Citește ce servește efectiv serverul sau platforma după deploy și compară cu fișierele locale, fișier cu fișier, înainte să muți traficul sau deployment-urile. Citește corpul răspunsurilor, nu codurile de status. Un push reușit dovedește doar că transferul a mers; dacă alt proces edita folderul în acel moment, conținutul urcat poate să nu fie cel pe care l-ai vrut.

### De ce poate ascunde un răspuns 200 o pagină lipsă sau protejată?

Multe servere web trimit orice cale necunoscută către pagina de index a unei aplicații single-page, care întoarce 200. O rută poate părea astfel publică sau existentă, deși serviciul real ar răspunde cu 401 sau 404. Ca să judeci dacă o rută există sau e deschisă, citește corpul răspunsului și, unde se poate, interoghează serviciul direct, fără serverul web din față.

### Cum poate o comandă de shell să modifice din greșeală producția la un deploy?

Cauze frecvente: un punct și virgulă după un cd care a eșuat, așa că restul comenzilor rulează în directorul live; ssh într-o buclă care citește intrarea buclei și procesează doar primul element; ghilimele pierdute când codul trece prin ssh cu heredoc; testarea ca root a unei configurații de server web, care poate schimba proprietarul directoarelor temporare. Folosește set -euo pipefail, gărzi pe director, ssh -n și fișiere copiate.

## Cum se citează

**Citare:** Going Stellar (2026). *Deploy sigur: dry-run implicit, verificare de paritate și controlul a ce s-a publicat de fapt*. GOING STELLAR S.R.L.. https://goingstellar.ro/ro/metode/deploy-sigur-dry-run-paritate/

```bibtex
@misc{goingstellar2026safe,
  title  = {Deploy sigur: dry-run implicit, verificare de paritate și controlul a ce s-a publicat de fapt},
  author = {{Going Stellar}},
  year   = {2026},
  url    = {https://goingstellar.ro/ro/metode/deploy-sigur-dry-run-paritate/},
  note   = {2026-10-11}
}
```

Licență. Se poate cita liber, cu atribuire.

## Mai există și

- Pagina în HTML: https://goingstellar.ro/ro/metode/deploy-sigur-dry-run-paritate/
- Același articol în engleză: https://goingstellar.ro/methods/safe-deploys-dry-run-parity-checks/
