8.6 Verziókezelés és dependency management
Áttekintő
Minden projektben vannak könyvtárak, amiket nem te írtál – de amiket a kódod használ. Ezeket dependency-knek (függőségeknek) hívjuk. A dependency management az a folyamat, amellyel nyilvántartod, melyik verziót használod, hogyan frissítesz, és hogyan biztosítod, hogy minden csapattag és a production szerver pontosan ugyanazt az állapotot lássa.
Ez az alfejezet nem szintaxisról szól. Arról szól, hogy mit rontanak el a juniorok újra meg újra – és hogyan kerüld el.
Miért számít ez az állásinterjún?
„Hogyan kezeled a package frissítéseket?" – elhangzik. Ha nem tudod a lock fájl és a manifest különbségét, nem nézel ki magabiztosnak.
Miért számít production-ban?
Egy frissítetlen dependency sebezhetőség. Egy rosszul frissített dependency production leállás. Mindkettőt láttam.
Részletes leírás
A manifest fájl szerepe
Minden csomagkezelő rendszernek van egy manifest fájlja, ami leírja, hogy a projektednek mire van szüksége:
- JavaScript (Node.js):
package.json - Python:
requirements.txtvagypyproject.toml - PHP:
composer.json - Go:
go.mod - Ruby:
Gemfile
Ez a fájl azt mondja meg: „Ehhez a projekthez szükségem van az X csomagra, nagyjából ebben a verzióban."
// package.json (JavaScript)
{
"dependencies": {
"express": "^4.18.0",
"axios": "~1.4.0"
}
}
# requirements.txt (Python)
requests>=2.28.0,<3.0.0
flask==2.3.2
// composer.json (PHP)
{
"require": {
"guzzlehttp/guzzle": "^7.5",
"laravel/framework": "^10.0"
}
}
A manifest nem rögzíti pontosan melyik verziót – csak megad egy tartományt. Ez szándékos.
Szemantikus verziózás (SemVer)
A legtöbb package MAJOR.MINOR.PATCH formátumban verziózott. Ez nem véletlen, ez egy megállapodás:
| Változás típusa | Mit jelent? |
|---|---|
PATCH (pl. 1.0.0 → 1.0.1) | Hibajavítás, visszafele kompatibilis |
MINOR (pl. 1.0.0 → 1.1.0) | Új funkció, visszafele kompatibilis |
MAJOR (pl. 1.0.0 → 2.0.0) | Breaking change – valami elromlott |
Ez a megállapodás nem kötelező – a packagekészítők megsérthetik. De ha tartják, akkor tudod, hogy:
^4.18.0→ elfogad minden4.x.x-et, aholx >= 18(MINOR és PATCH frissítések OK)~1.4.0→ csak1.4.x-et fogad el (csak PATCH frissítések OK)==2.3.2→ pontosan ezt a verziót kéri (semmi mást)
Amit juniorok félreértenek: A ^ nem azt jelenti, hogy „mindig a legújabb". Azt jelenti, hogy „elfogadok kompatibilis frissítéseket ezen belül". Ha MAJOR verziót frissít a package, nem veszi automatikusan fel.
A lock fájl – a legfontosabb fájl, amit sokan ignorálnak
A manifest megmondja, mit szeretnél. A lock fájl megmondja, mit kaptál.
- JavaScript:
package-lock.jsonvagyyarn.lock - Python:
poetry.lock(ha Poetry-t használsz) - PHP:
composer.lock
A lock fájl tartalmazza az összes dependency pontos verzióját, beleértve a közvetett függőségeket is (a dependency-id dependency-jeit is).
Miért kritikus ez?
Fejlesztő A telepíti: express 4.18.2
Fejlesztő B telepíti: express 4.18.3 (frissebb lett a package)
Production deploy: express 4.18.4
Mindhárom különböző verziót futtat. "Nálam működik" probléma indul.
Ha committolod a lock fájlt, mindenki pontosan ugyanazt telepíti.
Arany szabály: A lock fájl a verziókövetőbe kerül. Mindig. Kivételek nincsenek.
# Telepítés lock fájl alapján (nem frissít semmit)
npm ci # JavaScript
composer install # PHP
# Telepítés manifest alapján (frissíthet)
npm install # JavaScript
composer update # PHP
Hogyan frissíts dependency-t biztonságosan?
Frissítés nem egyenlő npm update && commit. Ez az egyik leggyakoribb hiba, amit juniorok csinálnak.
Biztonságos frissítési folyamat:
- Ellenőrizd a változásokat – nézd meg a changelog-ot vagy release notes-t
- Frissíts egyszerre egyet – ne frissíts 20 package-t egyszerre
- Futtasd a teszteket – ha nincs teszt, kézzel tesztelj
- Ellenőrizd a lock fájlt – a diff legyen értelmező
- Deploy staging-re először – ne közvetlenül production-ra
# Csak egy package frissítése (npm)
npm update express
# Elavult package-ek listázása
npm outdated
pip list --outdated
composer outdated
Mikor NE frissíts?
- Közvetlenül deploy előtt
- Ha nincs tesztlefedettség az érintett területen
- Ha nem érted a breaking change-eket
- Ha a csapat nincs értesítve
Security audit – ne hagyd ki
A dependency-k biztonsági sebezhetőségeket hordozhatnak. Ez nem elméleti – rendszeresen derülnek ki kritikus sérülékenységek széles körben használt package-ekben.
# Biztonsági audit futtatása
npm audit # JavaScript
pip-audit # Python (pip install pip-audit szükséges)
composer audit # PHP
# Automatikus javítás (csak alacsony kockázatú esetben)
npm audit fix
Mit mutat az audit?
- Melyik dependency-ben van ismert sebezhetőség
- Milyen súlyosságú (low / medium / high / critical)
- Van-e elérhető fix
Mit csinálj, ha critical sebezhetőséget találsz?
- Nézd meg, tényleg érinti-e a te felhasználási módod
- Ha igen: frissítsd azonnal
- Ha a fix nem elérhető: keress alternatívát, vagy jelezd a csapatnak
- Dokumentáld a döntést
devDependencies vs dependencies
Egy utolsó, de fontos különbség:
// package.json
{
"dependencies": {
"express": "^4.18.0" // Kell production-ban is
},
"devDependencies": {
"jest": "^29.0.0", // Csak fejlesztéshez kell
"eslint": "^8.0.0" // Csak fejlesztéshez kell
}
}
Production deploy-nál nem kell a test framework. Ha összekevered, a production image feleslegesen nagy lesz, és esetleg sérülékenyebb.
Életszerű példák
1. példa: A „nálam működik" szindróma
Bence és Lilla ugyanazon a projekten dolgoznak. Bence júniusban klónozta a repót, Lilla szeptemberben. Lilla meghív egy login funkciót – az elszáll.
Miért? Bence-nél az axios 1.4.0-s verzió fut (amit a lock fájlból telepített). Lilla-nál nincs lock fájl commitolva, npm install-al telepített, és az axios 1.5.0-ra frissített – amiben volt egy breaking change az interceptoroknál.
Fix: A lock fájl mindig kerüljön a verziókövetőbe. Mindenki npm ci-t használjon, nem npm install-t meglévő lock fájl esetén.
2. példa: A pánikszerű frissítés
Péter junior fejlesztő kap egy Slack üzenetet: „Kritikus sebezhetőség a log4j-ben, azonnal frissíts!" Péter npm update-et futtat, majd pushol – és letör a production.
Miért? Az npm update frissített más package-eket is, amelyek között volt egy MINOR frissítés, ami az ő API-használatát elrontotta. Tesztek nem futottak, stagingre nem ment ki.
Fix: Mindig pontosan egy package-t frissíts. Futtasd a teszteket. Nézd meg a diff-et.
3. példa: A copy-paste requirements.txt
Júlia lát egy tutorial-t, kimásolja a requirements.txt-et, nincs benne pontos verzió:
# Így NE
requests
flask
sqlalchemy
Fél évvel később valaki klónozza a projektet és telepíti – a flask közben 2.x-ről 3.x-re frissült, breaking change-ekkel. A projekt nem indul.
Fix: Mindig rögzítsd a verziót. Legalább felső határt adj meg: flask>=2.0,<3.0. Vagy használj pip freeze > requirements.txt-t a pontos verzió rögzítéséhez.
4. példa: Dependency audit CI-ban
Gábor beállítja, hogy minden PR-nél lefusson npm audit. Egy hétre rá egy csapattag hozzáad egy új package-et, ami egy ismert sebezhetőségű indirect dependency-t húz be. A CI megáll, a PR nem mergelhet.
Gábor megkeresi az alternatívát, jelenti a csapatnak, és document-álja a döntést. Az audit így teszi automatikussá azt, ami egyébként kézzel elmaradna.
Tesztfeladatok
1. feladat – SemVer értelmezés
Mit jelent a következő verzió jelölés? Melyik verziót fogadja el, melyiket nem?
"lodash": "^4.17.11"
Válassz ki minden igaz állítást:
- [ ] A. Elfogadja a 4.17.12-t (PATCH frissítés)
- [ ] B. Elfogadja a 4.18.0-t (MINOR frissítés)
- [ ] C. Elfogadja az 5.0.0-t (MAJOR frissítés)
- [ ] D. Elfogadja a 4.17.10-t (régebbi PATCH)
- [ ] E. Csak a pontosan 4.17.11-et fogadja el
Megoldás
A és B igaz. A ^ azt jelenti: elfogad MINOR és PATCH frissítéseket, de a MAJOR verziót nem. A 4.17.10 régebbi verziót általában nem fogad el (a minimum 4.17.11).
2. feladat – Lock fájl döntés
Az alábbi állítások közül melyik igaz?
- [ ] A. A lock fájlt
.gitignore-ba kell tenni, mert nagy és generált - [ ] B. A lock fájlt committolni kell, mert biztosítja a reprodukálható telepítést
- [ ] C. A lock fájl csak library-khoz kell, applikációkhoz nem
- [ ] D. A lock fájl nélkül is ugyanazt a verziót telepíti mindenki
Megoldás
B igaz. A lock fájl committolása biztosítja, hogy mindenki (fejlesztők, CI, production) ugyanazokat a verziókat telepíti. Az A egy visszatérő tévhit – sokan ignorálják tévesen.
3. feladat – npm install vs npm ci
Mikor melyiket használd?
| Szituáció | npm install | npm ci |
|---|---|---|
| Új package hozzáadása a projekthez | ||
| CI/CD pipelineben telepítés | ||
| Csapattársnál: meglévő projektet klónozta | ||
| Saját gépen: package.json-t módosítottad |
Megoldás
| Szituáció | npm install | npm ci |
|---|---|---|
| Új package hozzáadása a projekthez | ✅ | ❌ |
| CI/CD pipelineben telepítés | ❌ | ✅ |
| Csapattársnál: meglévő projektet klónozta | ❌ | ✅ |
| Saját gépen: package.json-t módosítottad | ✅ | ❌ |
npm ci mindig a lock fájlból telepít, gyorsabb és megbízható. npm install frissítheti a lock fájlt.
4. feladat – MAJOR változás felismerése
Az axios library changelog-jában látod ezt:
v1.0.0 (breaking change):
- The default export has been removed. Use named import instead.
Before: import axios from 'axios'
After: import { axios } from 'axios'
A saját kódodban ez van:
import axios from 'axios';
axios.get('/api/users');
Mi fog történni, ha frissítesz 0.x-ről 1.0.0-ra?
- [ ] A. Semmi, visszafele kompatibilis
- [ ] B. Runtime error: axios is not a function
- [ ] C. Warningot dob, de működik
- [ ] D. Csak TypeScript projekteknél okoz problémát
Megoldás
B. Ez MAJOR verziómódosítás, breaking change van. A default export megszűnt, a kódod runtime errort dob. Frissítés előtt a changelog olvasása kötelező, és módosítani kell az importot.
5. feladat – devDependencies szortírozás
Kategorizáld az alábbi package-eket: dependencies vagy devDependencies?
| Package | Mire való | Kategória |
|---|---|---|
express | HTTP szerver framework | |
jest | Tesztelési framework | |
dotenv | .env fájl betöltése | |
eslint | Kódellenőrző | |
pg | PostgreSQL driver | |
nodemon | Fejlesztési auto-restart |
Megoldás
| Package | Kategória |
|---|---|
express | dependencies – kell production-ban |
jest | devDependencies – csak fejlesztésben kell |
dotenv | dependencies – általában kell production-ban |
eslint | devDependencies – csak fejlesztésben kell |
pg | dependencies – kell production-ban |
nodemon | devDependencies – csak fejlesztésben kell |
6. feladat – Audit eredmény értelmezése
npm audit azt mutatja:
found 3 vulnerabilities (1 moderate, 2 high)
Az egyik high severity sérülékenység a lodash package-ben van, az eval-t használó funkcióban. A te kódod csak _.map() és _.filter() függvényeket hív.
Mi a helyes következő lépés?
- [ ] A. Azonnal futtatod az
npm audit fix-et - [ ] B. Megvizsgálod, hogy az érintett funkciót tényleg használod-e, és döntesz
- [ ] C. Ignorálod, mert 1 moderate és 2 high nem kritikus
- [ ] D. Törlöd és újratelepíted a node_modules-t
Megoldás
B. A sebezhetőség csak az eval-alapú funkciókat érinti, amit nem használsz. Megvizsgálod, dokumentálod a döntést, majd döntesz a frissítésről. Az npm audit fix automatikusan módosíthat más dolgokat is, amit ellenőrizni kell.
7. feladat – Szituációs döntés
Péntek délután 4:30-kor felfedezed, hogy a projektetek egyik package-jében van egy moderate severity sebezhetőség. Nincs éles bejelentkezési felület (csak belső tool), staging nincs tesztelve, és holnap a csapat fele szabadságon van.
Mi a legmegfelelőbb lépés?
- [ ] A. Azonnal frissítesz, pusholsz, deploy-olsz production-ba
- [ ] B. Megvizsgálod a sebezhetőséget, jelzed a csapatnak, hétfőn kezelsz
- [ ] C. Ignorálod, úgysem talál rá senki
- [ ] D. Törlöd az egész dependency-t azonnali hatállyal
Megoldás
B. Moderate severity belső toolnál nem jelent azonnali veszélyt. A pánikszerű péntek esti deploy rosszabb kockázatot jelent, mint a hétfői kezelt frissítés. Jelzés a csapatnak kötelező.
8. feladat – Lock fájl diff értelmezése
Code review során látod, hogy egy PR a package-lock.json-ban 47 fájlt módosított, de a package.json-ban csak egy sor változott (hozzáadtak egy új package-et). Ez gyanús?
- [ ] A. Igen, valaki biztosan rongált valamit
- [ ] B. Nem, ez normális – egy új package sok indirect dependency-t húz be
- [ ] C. Igen, a lock fájlt kézzel szerkesztette valaki
- [ ] D. Mindegy, a lock fájl nem fontos a review-ban
Megoldás
B. Egy új package rengeteg indirect dependency-t (tranzitív függőséget) húzhat be. A 47 módosítás teljesen normális lehet. A lock fájl diff-et érdemes átnézni, de nem gyanús önmagában. D rossz válasz: a lock fájl igenis fontos review-ban.