Każdy przepływ pracy GitHub Actions, który napisałeś, jest plikiem YAML. Wszystko — wyzwalacze, zadania, kroki, zmienne środowiskowe, strategia matrix — jest wyrażone w YAML. Co oznacza, że głębokie zrozumienie YAML to nie akademicka ciekawostka: to różnica między CI działającym niezawodnie a CI psującym się tajemniczo o 16:00 w piątek, gdy próbujesz wypuścić release.

GitHub Actions ma doskonałą dokumentację składni przepływów pracy, ale skupia się na funkcjach Actions, a nie na mechanice YAML pod spodem. Ten artykuł obejmuje oba aspekty — strukturę przepływu pracy i wzorce (oraz pułapki) specyficzne dla YAML, które decydują o powodzeniu lub porażce konfiguracji CI.

Struktura przepływu pracy: Klucze najwyższego poziomu

Plik przepływu pracy GitHub Actions znajduje się w .github/workflows/ i ma trzy wymagane klucze najwyższego poziomu. Oficjalny przegląd przepływu pracy wyjaśnia, gdzie plik leży w Twoim repozytorium i jak GitHub go odkrywa:

yaml
name: CI Pipeline          # optional but shown in the Actions UI

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

jobs:                      # the actual work
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm test
Uważaj na on jako boolean YAML: W YAML 1.1 słowo on bez cudzysłowu jest interpretowane jako boolean true. Parser GitHub obsługuje to poprawnie, ale jeśli kiedykolwiek zobaczysz, że Twój plik przepływu pracy jest oznaczony przez ogólny linter YAML, to właśnie dlatego. Bezpieczna forma to cytowanie: "on": — choć GitHub Actions sam w sobie nie wymaga cudzysłowów.

Wyzwalacze: Klucz on:

Klucz on: kontroluje, kiedy uruchamia się Twój przepływ pracy. Pełna lista zdarzeń wyzwalających obejmuje wszystko od recenzji pull requestów po dispatche z repozytorium. Oto najczęstsze wzorce:

yaml
on:
  # Push to specific branches
  push:
    branches:
      - main
      - "release/**"       # glob pattern — quotes needed for /**
    paths-ignore:
      - "docs/**"
      - "*.md"

  # PRs targeting main
  pull_request:
    branches: [main]
    types: [opened, synchronize, reopened]

  # Scheduled (cron syntax)
  schedule:
    - cron: "0 2 * * 1"   # every Monday at 2am UTC

  # Manual trigger with input
  workflow_dispatch:
    inputs:
      environment:
        description: "Target environment"
        required: true
        default: staging
        type: choice
        options: [staging, production]

Wieloliniowe polecenia run: i skalary blokowe YAML

Klucz run: to miejsce, gdzie dosłowny skalar blokowy YAML (|) naprawdę się sprawdza — zajrzyj do yaml-multiline.info po opis każdego wariantu skalaru blokowego i złożonego. Bez niego musiałbyś łączyć polecenia przez && w jednej linii, co jest nieczytelne:

yaml
steps:
  # Single line — works but hard to read
  - name: Build
    run: npm ci && npm run lint && npm run test && npm run build

  # Multi-line with literal block scalar — much better
  - name: Build
    run: |
      npm ci
      npm run lint
      npm run test -- --coverage
      npm run build

  # Folded scalar (>) joins lines with spaces — NOT what you want for shell
  # This would run as a single command with spaces where the newlines are:
  - name: Wrong for shell
    run: >
      npm ci
      npm test
Zawsze używaj | dla wieloliniowych skryptów shell, nigdy >. Złożony skalar składa znaki nowej linii w spacje, co oznacza, że Twoje polecenia shell zostaną scalone w jeden długi łańcuch. To powoduje tajemnicze błędy. Dosłowny skalar blokowy | zachowuje znaki nowej linii dokładnie tak, jak są, więc każda linia jest wykonywana jako osobne polecenie shell.

Zmienne środowiskowe i sekrety

Zmienne środowiskowe w GitHub Actions używają YAML w połączeniu z składnią kontekstu i wyrażeń Actions. Oto jak się ze sobą łączą:

yaml
env:
  NODE_ENV: production         # workflow-level env var
  API_VERSION: "2.1"          # quoted to force string type

jobs:
  deploy:
    runs-on: ubuntu-latest
    env:
      DEPLOY_ENV: staging      # job-level env var (overrides workflow-level)

    steps:
      - name: Deploy to staging
        env:
          API_KEY: ${{ secrets.STAGING_API_KEY }}     # step-level, from secret
          DATABASE_URL: ${{ vars.STAGING_DB_URL }}    # step-level, from variable
        run: |
          echo "Deploying to $DEPLOY_ENV"
          ./scripts/deploy.sh

Składnia wyrażeń ${{ }} to własny język szablonów GitHub Actions nakładany na YAML. Jest oceniany przed parsowaniem YAML w niektórych kontekstach, co może nieoczekiwanie wchodzić w interakcję z własnymi zasadami cytowania YAML. W razie wątpliwości owijaj wartości zaczynające się od ${{ w podwójne cudzysłowy.

Strategia matrix: Buduj na wielu konfiguracjach

Strategia matrix to jedna z najpotężniejszych funkcji GitHub Actions — i jest wyrażona całkowicie w YAML. Uruchamia Twoje zadanie raz dla każdej kombinacji wartości matrix:

yaml
jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false         # don't cancel other matrix jobs on failure
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node: ["18", "20", "22"]
        exclude:
          - os: windows-latest
            node: "18"         # skip this combination

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
      - run: npm ci && npm test

Ta pojedyncza definicja zadania generuje do 9 równoległych uruchomień (3 systemy × 3 wersje Node, minus 1 wykluczone). Wartości matrix YAML to zwykłe tablice — jedyne na co trzeba uważać, to że numery wersji jak 18 powinny być cytowane jako "18", aby pozostały łańcuchami. Bez cudzysłowów YAML parsuje je jako liczby całkowite i niektóre Actions mogą się skarżyć.

Warunkowe kroki z if:

Klucz if: pozwala pomijać kroki na podstawie warunków. Używa języka wyrażeń GitHub, a nie zwykłych wartości YAML:

yaml
steps:
  - name: Run tests
    run: npm test

  - name: Upload coverage
    if: success() && github.ref == 'refs/heads/main'
    uses: codecov/codecov-action@v4

  - name: Notify on failure
    if: failure()
    uses: slackapi/slack-github-action@v1
    with:
      slack-message: "Build failed on ${{ github.ref }}"
      channel-id: "C12345ABC"
    env:
      SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}

  - name: Deploy (only on tag push)
    if: startsWith(github.ref, 'refs/tags/v')
    run: ./scripts/deploy.sh production

Wielokrotnie używane przepływy pracy

Do eliminowania duplikacji między repozytoriami (nie tylko w jednym pliku) GitHub Actions obsługuje wielokrotnie używane przepływy pracy. Wywoływany przepływ pracy używa on: workflow_call:, a wywołujący używa uses: na poziomie zadania — nie kroku:

yaml
# .github/workflows/reusable-test.yml (the reusable workflow)
on:
  workflow_call:
    inputs:
      node-version:
        required: false
        type: string
        default: "20"
    secrets:
      NPM_TOKEN:
        required: true

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node-version }}
      - run: npm ci && npm test
        env:
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
yaml
# .github/workflows/ci.yml (the caller)
on: [push, pull_request]

jobs:
  run-tests:
    uses: my-org/shared-workflows/.github/workflows/reusable-test.yml@main
    with:
      node-version: "22"
    secrets:
      NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

Najczęstsze błędy YAML w GitHub Actions

  • Złe wcięcie kroków. Kroki muszą być wcięte pod steps: ze spójnymi spacjami. Pojedyncza dodatkowa lub brakująca spacja przenosi krok poza jego zadanie.
  • Niecytowane numery wersji. node-version: 20 przekazuje liczbę całkowitą; niektóre actions oczekują łańcucha. Używaj node-version: "20" dla bezpieczeństwa.
  • Używanie > zamiast | dla skryptów shell. Złożone skalary zwijają znaki nowej linii. Twój wieloliniowy skrypt staje się jednym długim łańcuchem i zawodzi.
  • Brak cudzysłowów przy wzorcach glob. Wzorce takie jak release/** zawierają *, który YAML może zinterpretować jako alias. Zawsze cytuj wzorce glob.
  • Sekrety używane w warunkach if:. GitHub maskuje sekrety w logach, ale nie zezwala na ich użycie w wyrażeniach if:. Zamiast tego użyj zmiennej środowiskowej.
  • Zapominanie o fail-fast: false w zadaniach matrix. Domyślnie, jeśli jedno zadanie matrix zawiedzie, wszystkie pozostałe są anulowane. Zwykle nie jest to pożądane podczas debugowania.

Podsumowanie

Przepływy pracy GitHub Actions to w gruncie rzeczy pliki YAML — rozumienie dosłownych skalarów blokowych, zasad cytowania i konwersji typów YAML bezpośrednio przekłada się na pisanie bardziej niezawodnego CI. Najczęstsze awarie wynikają z błędów wcięć, niecytowanych wartości, które konwertują się do złego typu, i używania złego operatora łańcucha wieloliniowego w skryptach shell. Opanuj te trzy rzeczy, a większość debugowania przepływów pracy stanie się prosta. Używaj Walidatora YAML do wykrywania błędów składni przed pushem i Formatera YAML do wymuszania spójnych wcięć w plikach przepływów pracy.