[ CASE_STUDY ][ CI_CD ][ GITHUB_ACTIONS ][ NEXTJS ][ DEVOPS ]

CI/CD dla Next.js — GitHub Actions od testów do produkcji (2026)

28 maja 202610 min czytania
Autor: DevStudio.itStudio Web & AI

Lint, build przez scripts/build.cjs, Prisma, preview na Vercel i rollback — kompletny pipeline dla Next.js 15 na Node 22, z uczciwym punktem wyjścia (brak workflow w repo).

READ_TIME: 10 MIN_COMPLEXITY: MED_
STAMP: VERIFIED_BY_DS_

TL;DR

Dla projektu Next.js na Node 22, Next 15.5.18 i buildzie przez scripts/build.cjs rekomendujemy jeden pipeline GitHub Actions: każdy PR = jakość (lint + build), merge do main = deploy na Vercel. W tym repozytorium nie ma jeszcze katalogu .github/workflows — artykuł opisuje docelowy stan, który warto dodać od razu, zamiast polegać na ręcznym „u mnie działa”. Sekrety (VERCEL_TOKEN, DATABASE_URL, klucze API) trzymaj wyłącznie w GitHub Secrets.

Dla kogo to jest

  • Zespołów 1–5 developerów na Next.js + Vercel
  • Projektów z Prisma (postinstall: prisma generate, migrate w skrypcie build)
  • Firm, które chcą audytowalnej historii wdrożeń i preview URL na każdy PR
  • Monorepo lub wielu aplikacji w jednym repo (sekcja paths:)

Fraza (SEO)

ci cd nextjs github actions, pipeline nextjs 2026, automatyczne wdrożenie vercel, github actions build nextjs, branch protection main, rollback vercel

Punkt wyjścia: uczciwy stan repozytorium

W wielu projektach produkcyjnych pipeline „istnieje w głowie zespołu”, a nie w repo. Tutaj:

  • package.json wymaga Node 22.x (engines.node),
  • Next.js 15.5.18, skrypty: buildnode scripts/build.cjs, linteslint, postinstallprisma generate,
  • Brak plików .github/workflows/*.yml — CI trzeba świadomie dodać.

To nie wada — to normalny etap. Wada pojawia się, gdy deploy z laptopa omija te same kroki co PR. Celem jest jeden artefakt: commit przeszedł lint i build w Actions → ten sam commit ląduje na Vercel.

Co robi scripts/build.cjs (i dlaczego CI musi to uwzględnić)

Zwykły next build w CI często nie wystarczy, gdy:

  1. Prisma — skrypt ładuje .env / .env.local (w Actions nie ma ich w repo), uruchamia prisma generate, a przy obecności DATABASE_URL także prisma migrate deploy, na końcu next build.
  2. Lokalnie developer ma bazę; w CI build może przejść bez migracji, jeśli nie ustawisz sekretu — ale sam generate jest potrzebny po npm ci (wspierany też przez postinstall).

Wniosek dla pipeline: job build musi wywołać npm run build (nie surowe next build), z odpowiednimi zmiennymi środowiskowymi w GitHub Secrets / Environments. Dla PR bez bazy często wystarczy DATABASE_URL do shadow DB lub pominięcie migracji — zależnie od polityki zespołu; ważne, żeby prod miał pełny zestaw sekretów w environment production.

Strategie DATABASE_URL w CI (Prisma)

Strategia Kiedy Plusy / minusy
Ten sam URL co staging Mały zespół, jedna baza testowa Szybkie; ryzyko kolizji migracji przy równoległych PR
Osobna baza per PR (Neon, Supabase branch) Większy zespół Izolacja; wyższy koszt / konfiguracja
Brak DATABASE_URL w PR Tylko statyczny front Build może pominąć migrate deploy (log w build.cjs); schema musi być aktualna z repo
Pełny URL tylko na main Kompromis PR: lint + tsc + build bez migracji; prod: pełny pipeline

W DevStudio-style buildzie przy braku DATABASE_URL skrypt wypisuje komunikat i pomija prisma migrate deploy, ale i tak uruchamia prisma generate — to jest zgodne z postinstall i zapobiega błędom „Client not generated”.

Rekomendowany podział: PR vs main

Krok Pull request Push na main
npm ci tak tak
npm run lint (ESLint) tak tak
npx tsc --noEmit tak (jeśli TypeScript w projekcie) tak
npm run build tak tak
Testy jednostkowe tak, gdy dodasz tak
Deploy Vercel preview tak (integracja Git lub Actions)
Deploy Vercel production tak
Lighthouse CI opcjonalnie opcjonalnie (np. cron)

Zasada: nic nie merge’uj do main, co nie przeszło tego samego build co produkcja.

Pełny przykład workflow (.github/workflows/ci.yml)

Poniższy plik jest gotowy do skopiowania i dostosowania. Używa Node 22, cache npm, lint, typecheck i build zgodnego z tym repo.

name: CI

on:
  pull_request:
    branches: [main]
  push:
    branches: [main]

concurrency:
  group: ci-${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

permissions:
  contents: read

jobs:
  quality:
    runs-on: ubuntu-latest
    timeout-minutes: 25
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node.js 22
        uses: actions/setup-node@v4
        with:
          node-version: '22'
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: ESLint
        run: npm run lint

      - name: TypeScript (no emit)
        run: npx tsc --noEmit

      - name: Build (Prisma + Next via scripts/build.cjs)
        run: npm run build
        env:
          # Wymagane do pełnego buildu — ustaw w GitHub Secrets / Environment
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
          NEXT_PUBLIC_SITE_URL: ${{ vars.NEXT_PUBLIC_SITE_URL || 'https://example.com' }}
          # Dodaj pozostałe NEXT_PUBLIC_* i klucze API jak w Vercel Production

  deploy-preview:
    if: github.event_name == 'pull_request'
    needs: quality
    runs-on: ubuntu-latest
    environment: preview
    steps:
      - uses: actions/checkout@v4
      - uses: amondnet/vercel-action@v25
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
          github-token: ${{ secrets.GITHUB_TOKEN }}
          scope: ${{ secrets.VERCEL_ORG_ID }}

  deploy-production:
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    needs: quality
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4
      - uses: amondnet/vercel-action@v25
        with:
          vercel-token: ${{ secrets.VERCEL_TOKEN }}
          vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
          vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
          vercel-args: '--prod'
          github-token: ${{ secrets.GITHUB_TOKEN }}
          scope: ${{ secrets.VERCEL_ORG_ID }}

Alternatywa prostsza: włącz Vercel Git Integration — wtedy Vercel sam buduje preview na PR, a job quality w Actions zostaje „bramką” przed merge. Wiele zespołów łączy oba: Actions = lint/tsc/build, Vercel = hosting + URL.

Sekrety i zmienne — gdzie co trzymać

Nazwa Gdzie Uwagi
VERCEL_TOKEN GitHub Secret Token z Vercel Account Settings
VERCEL_ORG_ID, VERCEL_PROJECT_ID GitHub Secret Z pliku .vercel/project.json po vercel link
DATABASE_URL Secret + Vercel Env Ta sama wartość co produkcja dla migrate deploy
OPENAI_API_KEY, Stripe itd. Secret / Vercel Nigdy w repo ani w logach Actions
NEXT_PUBLIC_* Variables (niesecret) lub Vercel Muszą być identyczne w PR build i prod, inaczej „u mnie działa” wraca

W ustawieniach repo: Settings → Secrets and variables → Actions. Dla produkcji użyj Environment production z włączonym Required reviewers (opcjonalnie, 1–2 osoby).

Branch protection na main

Minimum, które warto włączyć od pierwszego dnia:

  • Require pull request before merging
  • Require status check quality (nazwa joba z workflow)
  • Require branch to be up to date
  • Do not allow bypassing (nawet admin, jeśli zespół ma dyscyplinę)
  • Opcjonalnie: require signed commits

Dzięki temu nikt nie wrzuci builda, który nie przeszedł npm run lint i npm run build na Node 22.

Preview URL na każdy PR

Vercel Git Integration (zalecane na start):

  • automatyczny URL typu projekt-git-branch-xyz.vercel.app,
  • komentarz bota w PR z linkiem,
  • QA i klient sprawdzają zmianę przed merge.

GitHub Actions + vercel-action (jak w yaml powyżej):

  • pełna kontrola, ten sam token co deploy prod,
  • przydatne, gdy chcesz jeden pipeline w YAML zamiast panelu Vercel.

W obu przypadkach upewnij się, że zmienne NEXT_PUBLIC_* na preview nie są puste — inaczej build PR „przechodzi”, a UI na preview jest inny niż produkcja.

Synchronizacja env: w Vercel skopiuj zestaw zmiennych z Production do Preview (lub użyj Vercel CLI vercel env pull). W GitHub dodaj te same NEXT_PUBLIC_* jako Variables (widoczne w logach, nie sekret) — wtedy job quality buduje ten sam kod co preview. Sekrety (DATABASE_URL, STRIPE_SECRET_KEY) zostaw wyłącznie w Secrets.

Monorepo: nie buduj wszystkiego przy każdym PR

Gdy w jednym repo masz np. apps/web i packages/ui, dodaj osobne workflow z filtrem ścieżek:

on:
  pull_request:
    paths:
      - 'apps/web/**'
      - 'packages/ui/**'
      - 'package-lock.json'

Możesz też użyć paths-ignore dla dokumentacji (docs/**, content/blog/**), żeby nie uruchamiać 8-minutowego builda przy poprawce literówki w artykule — o ile blog nie jest częścią tego samego pakietu Next.js (w monolicie marketingowym często i tak budujesz całość).

Rollback na Vercel w ~60 sekund

Deploy prod na Vercel to nowy deployment; poprzednie buildy zostają.

Procedura awaryjna:

  1. Vercel Dashboard → Deployments
  2. Znajdź ostatni działający deployment (poprzedni commit)
  3. ⋯ → Promote to Production

Czas: często poniżej minuty. Pipeline nie zastępuje rollbacku — zapewnia, że promowany build był kiedyś zielony na PR. Unikaj deployu z laptopa „na szybko” obok CI — wtedy rollback w panelu może przywrócić inną wersję niż myślisz.

Przy własnym serwerze (Docker): tag obrazu = SHA commita; rollback = poprzedni tag w orchestratorze. Zasada ta sama: jeden artefakt z CI.

Bezpieczeństwo w CI/CD

  • permissions: contents: read domyślnie (jak w przykładzie) — minimalne uprawnienia tokena GITHUB_TOKEN
  • Osobny environment production z approval
  • Dependabot / npm audit w osobnym workflow tygodniowym
  • Nigdy nie echo sekretów ani pełnych .env w logach — Actions maskuje secrets.*, ale własne skrypty też muszą być czyste
  • Rotacja VERCEL_TOKEN i kluczy API co kwartał lub po odejściu członka zespołu

Najczęstsze błędy (i jak ich uniknąć)

Błąd Skutek Naprawa
Build PR bez NEXT_PUBLIC_* Inny bundle niż prod Variables w GitHub + Vercel Preview
next build zamiast npm run build Brak Prisma migrate/generate Zawsze skrypt z repo
Node 20 w Actions, 22 w engines Losowe błędy natywnych modułów node-version: '22'
Brak cache npm 8 min zamiast 3 cache: 'npm' w setup-node
Deploy z laptopa + CI Dwa źródła prawdy Tylko merge → main → deploy
Brak branch protection Złamanie prod w piątek wieczorem Wymagany check quality

FAQ

Czy GitHub Actions zastępuje Vercel?

Nie. Actions = kontrola jakości i opcjonalnie deploy CLI; Vercel = hosting, CDN, preview, rollback. Najczęściej: Actions na lint/build, Vercel na uruchomienie aplikacji.

Czy muszę uruchamiać prisma migrate deploy w CI?

W tym projekcie robi to scripts/build.cjs, gdy DATABASE_URL jest ustawione. Na PR możesz użyć osobnej bazy testowej lub pominąć migracje — ale wtedy upewnij się, że schema Prisma jest zgodna (generate i tak jest potrzebny). Na main/prod DATABASE_URL musi być kompletne.

Co jeśli nie mam testów?

Zacznij od lint + tsc + build. Testy dodaj, gdy masz krytyczne ścieżki (płatności, API umów). Pipeline i tak daje 80% wartości.

Monorepo z trzema aplikacjami?

Trzy workflow z paths: albo jeden workflow z macierzą strategy.matrix — nie jeden globalny build bez filtra.

Jak zsynchronizować wersję Node z Vercel?

W Vercel Project Settings ustaw Node.js 22.x, zgodnie z engines w package.json.

Troubleshooting: czerwony build w Actions

  • prisma generate failed — sprawdź wersję Node (22), czy npm ci doszedł do końca, czy schema w repo jest poprawna.
  • migrate deploy failed — URL bazy nieosiągalny z GitHub (firewall IP), zła migracja, konflikt z ręcznymi zmianami w DB.
  • next build OOM — zwiększ runner (rzadko) lub wyłącz zbędne analizy; sprawdź importy ciężkich bibliotek.
  • Lint fail na PR — uruchom lokalnie npm run lint na Node 22; nie merge’uj z --no-verify.
  • Preview działa, prod nie — porównaj Environment Variables w Vercel Production vs Preview; często brakuje jednego NEXT_PUBLIC_*.

Logi Actions pokazują dokładny krok — traktuj je jak jedyny audyt przed dotknięciem produkcji.

Plan wdrożenia w 1 dzień

  1. Dodać .github/workflows/ci.yml (fragment powyżej).
  2. Skonfigurować Secrets + Variables (DATABASE_URL, Vercel, NEXT_PUBLIC_*).
  3. Włączyć branch protection na main.
  4. Podłączyć repo do Vercel (jeśli jeszcze nie).
  5. Otworzyć testowy PR — sprawdzić zielony quality + preview URL.
  6. Zmergować — sprawdzić production deployment i zapisać procedurę rollbacku w README zespołu.

Podsumowanie

CI/CD dla Next.js 15 na Node 22 to nie magia — to powtarzalny zestaw: npm ci → lint → typecheck → npm run build (Prisma + Next) na każdym PR, deploy na Vercel po merge, sekrety poza repo, preview do akceptacji, rollback przez Promote w panelu. Brak workflow w repozytorium to sygnał, że warto to dodać teraz — zanim ręczny deploy kosztuje więcej niż jeden dzień naprawy produkcji.

Chcesz pipeline pod swój projekt?

O autorze

Budujemy szybkie strony WWW, aplikacje web/mobile, chatboty AI i hosting — z naciskiem na SEO i konwersję.

Przydatne linki

Od teorii do produkcji — Branchly, hosting, opieka i realizacje.

PODOBA CI SIĘ NASZA ARCHITEKTURA MYŚLENIA? ZBUDUJMY COŚ RAZEM.

[ ROZPOCZNIJ_KONFIGURACJĘ_PROJEKTU ]