A csomagolás mostantól nyomot hagy: melyik környezetre mi készült, mi lett kirakva, és
mennyi a lemaradás - ez az, ami a "melyik verzió fut az e2e-n" kérdést kiveszi a fejből.
- deployment_packages tábla + modell (BaseAuditable): target, tartomány, darabszámok,
mappa/ZIP útvonal, deployed_at. A csomagolás és a tényleges kirakás két külön esemény.
- Targetenkénti előtöltés: a kezdő commit az adott környezetre utoljára kirakottként
megjelölt csomag to_commit-je. Rebase után nem létező hash esetén inkább üres marad,
mint hogy hamis tartományt mutasson.
- "Környezetek állapota" panel: napló szerinti állapot + commit-lemaradás
(git rev-list --count), és gombra a szerver deploy-version.json-jának lekérdezése.
Ha a kettő eltér, az elmaradt vagy félbemaradt feltöltés jele. Szándékosan gombra fut,
nem minden rendereléskor: így nem indul kimenő kérés magától.
- ZIP a kész mappából (a fájllista a zip létrejötte előtt készül, így nem csomagolja
magát), letöltés a naplóból. A DB-ből jövő útvonalat kiírás előtt a kimeneti mappához
kötjük, hogy egy módosított rekord se tehessen letölthetővé tetszőleges fájlt.
- _torles.sh: alapból dry run, --confirm kell a törléshez, app-gyökér ellenőrzéssel,
abszolút útvonal és .. kiszűrésével, LF sorvéggel és BOM nélkül. Lefuttatva ellenőrizve.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- PricelistExecutionJob + új PricelistRevertJob: $tries=1, $timeout, failed()
hook. A service catch ága csak PHP exceptiont fog el; worker timeout vagy
memórialimit esetén a fájl inprogress-ben ragadna, döntési gomb nélkül.
- heartbeat backstop a kill -9 esetére, ahol a failed() sem fut: minden chunk ír
a rekordba, így az updated_at a szívverés (isExecutionStuck). Ezzel garantált,
hogy minden kísérlet véges időn belül terminális állapotba jut - enélkül a
kényszerlezárás sem nyílna ki soha.
- kompenzáló visszaállítás R1-R4: árak törlése, termékek visszaállítása a
snapshotból, létrehozott termékek kivonása (soft delete, NEM fizikai törlés,
mert lehet rájuk hivatkozás), árlista + fájl lezárása
- konfliktuskezelés: a végrehajtás óta kézzel módosított terméket kihagyjuk és
jelentjük, nem írjuk felül vakon
- FIX phase5/3: a snapshot csak az írás ELŐTTI updated_at-et tárolta, amihez
képest a termék a végrehajtás után mindig eltér - a konfliktus-ellenőrzés így
minden sort kihagyott volna. Most a saját írásunk utáni updated_at is bekerül.
- kényszerlezárás: csak legalább egy terminális hibába futott visszaállítási
kísérlet után, flag + developer szerepkör mögött, kötelező indoklással
- döntéstámogató panel: mi történt már meg az importból, hogy a felhasználó ne
vakon válasszon a Folytatás és a Visszavonás között
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- PricelistFile::canBeApproved() / hasExecutionStarted(): a jóváhagyás feltételei
egy helyen, hogy a felületi gomb és a service ugyanazt ellenőrizze
- approve(): a státusz MÉG A DISPATCH ELŐTT billen át, különben a queue-latency
alatt a gomb látszana és egy második kattintás párhuzamos importot indítana
- reject(): új 'rejected' lépésstátusz - nem 'failed', mert azt az
updateStepStatus fail fájlstátuszra fordítaná, az elutasítás viszont closed
- a döntés (ki, mikor, milyen indokkal) a file_meta.approval-ba kerül, mert a
BaseAuditable a nevével ellentétben nem naplóz
- Edit gomb szűkítése hasExecutionStarted()-tel három helyen, köztük az
EditPricelistFile::afterSave()-ben, ami a teljes láncot újraindítja
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- új PricelistExecution Pennant flag (enabled + roles=[developer]) a jóváhagyás,
végrehajtás és visszavonás rollout-kapujaként
- új execution_failed fájlstátusz: a validálásig tartó szakasz fail státuszától
szándékosan elkülönítve, mert itt már történhettek termék- és árírások
- PricelistFileStatusEnum::color(): a badge-színek eddig két helyen, kimerítő
match-ben voltak duplikálva, amit az új case eltört volna
- pricelist_file_lines.applied_snapshot + executed_at a chunkolt, idempotens
végrehajtáshoz és a kompenzáló visszaállításhoz
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>