8.6 Verziókezelés

← 8. Production-ready projekt építés

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.txt vagy pyproject.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ípusaMit 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 minden 4.x.x-et, ahol x >= 18 (MINOR és PATCH frissítések OK)
  • ~1.4.0 → csak 1.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.json vagy yarn.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:

  1. Ellenőrizd a változásokat – nézd meg a changelog-ot vagy release notes-t
  2. Frissíts egyszerre egyet – ne frissíts 20 package-t egyszerre
  3. Futtasd a teszteket – ha nincs teszt, kézzel tesztelj
  4. Ellenőrizd a lock fájlt – a diff legyen értelmező
  5. 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?

  1. Nézd meg, tényleg érinti-e a te felhasználási módod
  2. Ha igen: frissítsd azonnal
  3. Ha a fix nem elérhető: keress alternatívát, vagy jelezd a csapatnak
  4. 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 installnpm 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 installnpm 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?

PackageMire valóKategória
expressHTTP szerver framework
jestTesztelési framework
dotenv.env fájl betöltése
eslintKódellenőrző
pgPostgreSQL driver
nodemonFejlesztési auto-restart
Megoldás
PackageKategória
expressdependencies – kell production-ban
jestdevDependencies – csak fejlesztésben kell
dotenvdependencies – általában kell production-ban
eslintdevDependencies – csak fejlesztésben kell
pgdependencies – kell production-ban
nodemondevDependencies – 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.

Scroll to Top