Ogni workflow GitHub Actions che hai scritto è un file YAML. Tutto — i trigger, i job, gli step, le variabili d'ambiente, la matrix strategy — è espresso in YAML. Il che significa che capire YAML in profondità non è solo accademico: è la differenza tra una CI che funziona in modo affidabile e una CI che si rompe misteriosamente alle 16:00 di venerdì quando stai cercando di rilasciare una release.
GitHub Actions ha un'eccellente documentazione sulla sintassi dei workflow, ma si concentra sulle funzionalità di Actions piuttosto che sui meccanismi YAML sottostanti. Questo articolo copre entrambi — la struttura del workflow e i pattern YAML specifici (e le insidie) che determinano il successo o il fallimento delle configurazioni CI.
Struttura del workflow: le chiavi di primo livello
Un file workflow GitHub Actions si trova in .github/workflows/ e ha tre chiavi obbligatorie di primo livello.
La panoramica ufficiale dei workflow
spiega dove si trova il file nel repository e come GitHub lo scopre:
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 teston come booleano YAML: In YAML 1.1, la parola nuda on
viene interpretata come booleano true. Il parser di GitHub gestisce correttamente questo, ma se mai vedi il tuo
file workflow segnalato da un linter YAML generico, è per questo motivo. La forma sicura è quotarlo:
"on": — anche se GitHub Actions stesso non richiede le virgolette.Trigger: la chiave on:
La chiave on: controlla quando viene eseguito il workflow. La
lista completa degli eventi trigger
copre tutto, dalle revisioni delle pull request ai repository dispatch. Ecco i pattern più comuni:
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]Comandi run: multiriga e blocchi scalari YAML
La chiave run: è dove il blocco scalare letterale YAML (|) si dimostra indispensabile —
vedi il riferimento yaml-multiline.info per
ogni variante di blocchi e scalari ripiegati. Senza di esso, dovresti concatenare comandi con &&
su una singola riga, che è illeggibile:
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| per gli script shell multiriga, mai >.
Lo scalare ripiegato converte i newline in spazi, il che significa che i tuoi comandi shell vengono uniti in una lunga stringa.
Questo causa errori criptici. Il blocco scalare letterale | preserva i newline esattamente, quindi ogni riga
viene eseguita come un comando shell separato.Variabili d'ambiente e segreti
Le variabili d'ambiente in GitHub Actions usano YAML in combinazione con la sintassi di contesto ed espressione di Actions. Ecco come si incastrano insieme:
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.shLa sintassi delle espressioni ${{ }} è il linguaggio template di GitHub Actions sovrapposto a YAML.
Viene valutato prima del parsing YAML in alcuni contesti, il che può interagire inaspettatamente con le proprie regole di quotazione di YAML.
In caso di dubbio, racchiudi i valori che iniziano con ${{ tra virgolette doppie.
Matrix strategy: build su più configurazioni
La matrix strategy è una delle funzionalità più potenti di GitHub Actions — ed è espressa interamente in YAML. Esegue il job una volta per ogni combinazione di valori della matrix:
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 testQuesta singola definizione di job produce fino a 9 esecuzioni parallele (3 OS × 3 versioni Node, meno 1 esclusa).
I valori della matrix YAML sono semplici array — l'unica cosa a cui prestare attenzione è che i numeri di versione come 18
dovrebbero essere quotati come "18" per tenerli come stringhe. Senza virgolette, YAML li analizza come interi
e alcune Actions potrebbero lamentarsi.
Step condizionali con if:
La chiave if: ti permette di saltare step in base a condizioni. Usa il linguaggio delle espressioni di GitHub,
non i valori YAML normali:
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 productionWorkflow riutilizzabili
Per eliminare la duplicazione tra repository (non solo all'interno di un file), GitHub Actions supporta
i workflow riutilizzabili.
Il workflow chiamato usa on: workflow_call: e il chiamante usa
uses: a livello di job — non a livello di step:
# .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 }}# .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 }}Gli errori YAML più comuni in GitHub Actions
- Indentazione errata negli step. Gli step devono essere indentati sotto
steps:con spazi coerenti. Un singolo spazio in più o in meno sposta uno step fuori dal suo job. - Numeri di versione non quotati.
node-version: 20passa un intero; alcune actions si aspettano una stringa. Usanode-version: "20"per sicurezza. - Uso di
>invece di|per gli script shell. Gli scalari ripiegati collassano i newline. Il tuo script multiriga diventa una lunga stringa e fallisce. - Virgolette mancanti sui pattern glob. Pattern come
release/**contengono*che YAML potrebbe interpretare come alias. Cita sempre i pattern glob. - Segreti usati nelle condizioni if:. GitHub maschera i segreti nei log ma non permette loro di essere usati nelle espressioni
if:. Usa invece una variabile d'ambiente. - Dimenticare
fail-fast: falsenei job matrix. Per impostazione predefinita, se un job matrix fallisce, tutti gli altri vengono annullati. Di solito non è quello che vuoi durante il debug.
Conclusione
I workflow GitHub Actions sono fondamentalmente file YAML — capire i blocchi scalari letterali di YAML, le regole di quotazione e la coercizione dei tipi si traduce direttamente nella scrittura di una CI più affidabile. I fallimenti più comuni derivano da errori di indentazione, valori non quotati che vengono coerciti al tipo sbagliato e dall'uso dell'operatore sbagliato per le stringhe multiriga negli script shell. Fai quelle tre cose bene e la maggior parte del debug dei workflow diventa semplice. Usa il YAML Validator per individuare gli errori di sintassi prima del push, e il YAML Formatter per applicare un'indentazione coerente nei tuoi file workflow.