Trigger ed eventi: quando parte un workflow
La chiave on è il punto in cui un workflow smette di essere un file YAML e diventa automazione. Può contenere un singolo evento, una lista, oppure una mappa di eventi ciascuno con i propri filtri: quando ne dichiari più di uno, basta che se ne verifichi uno solo perché il run parta. La difficoltà, in GH-200, non è ricordare i nomi degli eventi ma sapere dove GitHub va a cercare il file del workflow, quali input un evento accetta davvero e quali run non partono affatto pur sembrando legittimi.
Il vincolo del branch predefinito
Per push e pull_request GitHub esegue la versione del workflow presente sul riferimento coinvolto: se modifichi il file su un branch di feature, il run su quel branch usa già la nuova versione. Tre eventi si comportano invece in modo diverso, ed è la prima cosa che l’esame verifica: schedule, workflow_dispatch e repository_dispatch attivano un run solo se il file del workflow esiste sul branch predefinito. Puoi aggiungere workflow_dispatch a un file su un branch secondario quanto vuoi: il pulsante Run workflow non comparirà finché quella definizione non viene unita nel default branch. Per schedule il vincolo è ancora più stretto, perché l’esecuzione avviene sull’ultimo commit del branch predefinito, non su un branch a tua scelta.
schedule usa la sintassi cron POSIX a cinque campi (minuto, ora, giorno del mese, mese, giorno della settimana) con gli operatori *, ,, - e /. La documentazione attuale ammette anche la dichiarazione di un timezone tramite stringa IANA: è una novità rispetto al comportamento storico, in cui l’unico riferimento era UTC, ed è esattamente il tipo di dettaglio che le domande recenti usano come distrattore. Ricorda comunque che l’orario non è una garanzia contrattuale: esiste una granularità minima sotto la quale non si scende e, nelle fasce di carico elevato della piattaforma, l’avvio slitta. Nei repository pubblici, inoltre, le pianificazioni vengono disattivate automaticamente dopo un lungo periodo di inattività del repository, e vanno riabilitate a mano.
repository_dispatch è il ponte verso l’esterno: un sistema di terze parti chiama la REST API indicando un event_type e, opzionalmente, un oggetto client_payload che il workflow legge dal contesto github.event. Anche qui vale la regola del branch predefinito, quindi non puoi usarlo per far partire un workflow che vive solo su un branch di sviluppo.
Input tipizzati: workflow_dispatch non è workflow_call
workflow_dispatch accetta input dichiarati con description, required, default e type. I tipi ammessi sono string, boolean, number, choice ed environment: l’interfaccia web li rende rispettivamente come campo di testo, casella di spunta, campo numerico, elenco a discesa costruito dalla lista options ed elenco degli environment configurati. Gli stessi input si passano da riga di comando con gh workflow run, usando l’opzione -f per le coppie chiave-valore e --ref per scegliere il branch su cui eseguire, oppure via REST API indicando ref e inputs nel corpo della richiesta.
Qui si annida la confusione più frequente dell’esame. workflow_call, l’evento che rende un workflow riutilizzabile, accetta soltanto boolean, number e string. Non esistono choice né environment in un reusable workflow: se ti serve un elenco chiuso di valori, lo dichiari come string e lo validi tu nel workflow chiamato. I segreti seguono un percorso separato dagli input, con secrets dichiarati singolarmente e marcati required, oppure propagati in blocco dal chiamante con secrets: inherit. La catena di workflow annidati ha inoltre un limite di profondità, quindi la composizione non è illimitata.
on:
workflow_dispatch:
inputs:
environment:
type: environment
required: true
dry_run:
type: boolean
default: true
workflow_call:
inputs:
target:
type: string
required: true
secrets:
deploy_key:
required: true
Filtri, concurrency e permessi
Gli eventi push e pull_request si restringono con branches, tags e paths, oppure con le rispettive forme negative branches-ignore, tags-ignore e paths-ignore. La regola da memorizzare è che le due forme non convivono per lo stesso evento: per includere ed escludere insieme si usa la forma positiva con i pattern di negazione preceduti da punto esclamativo, mantenendo almeno un pattern positivo, e l’ordine conta perché una negazione successiva a una corrispondenza positiva esclude il percorso. Attenzione: questi filtri non si applicano a schedule, workflow_dispatch e repository_dispatch, che non hanno un branch da filtrare.
Il concurrency serializza le esecuzioni. Definisci un group, che può essere una stringa o un’espressione costruita sui contesti github, inputs e vars, e decidi con cancel-in-progress se annullare il run già avviato nello stesso gruppo. I nomi di gruppo non distinguono maiuscole e minuscole. Per impostazione predefinita solo un run può restare in attesa per gruppo e il nuovo sostituisce il precedente; con la chiave queue puoi invece far accodare più run, che vengono poi eseguiti in ordine di arrivo. La combinazione fra accodamento multiplo e cancel-in-progress attivo non è ammessa. Il blocco si dichiara a livello di workflow oppure di singolo job.
Infine lo scope: assegna a permissions il minimo indispensabile, ricordando che dichiararlo azzera tutti gli ambiti non elencati.
Gli eventi generati dal GITHUB_TOKEN non innescano nuovi run
È la protezione anti-ricorsione più importante della piattaforma. Se un job usa il GITHUB_TOKEN per creare un commit, aprire una issue o modificare una pull request, l’evento risultante non genera un nuovo workflow run. Le eccezioni sono workflow_dispatch e repository_dispatch, che partono comunque. Caso particolare: quando una pull request viene creata o aggiornata da un workflow con il GITHUB_TOKEN, gli eventi pull_request con attività opened, synchronize o reopened producono run che richiedono approvazione manuale. Se vuoi davvero un incatenamento, devi autenticarti con un token diverso, tipicamente di una GitHub App. Le domande d’esame presentano spesso lo scenario “il primo workflow funziona ma il secondo non parte mai”: la risposta è quasi sempre questa, non un errore nei filtri.