Tre modelli di distribuzione, tre livelli di visibilità

Una action non si installa: si referenzia. Il modello di distribuzione decide quindi soltanto chi riesce a risolvere quel riferimento quando il workflow parte.

Il caso più semplice è tenere la action nello stesso repository che la usa. La documentazione suggerisce di metterla sotto la directory .github, per esempio in .github/actions/action-a, e di richiamarla con un percorso relativo. Non ha un versioning proprio: evolve insieme al repository che la ospita.

Il secondo modello è il repository dedicato pubblico. È la scelta raccomandata quando la action ha vita autonoma, perché permette di versionarla indipendentemente dal codice applicativo. Chiunque su GitHub può referenziarla nella forma proprietario/repository seguita da un riferimento Git.

Il terzo modello copre la condivisione interna. Se la action sta in un repository privato, devi aprire Settings, poi Actions, poi General, e in fondo alla pagina agire sulla sezione Access, scegliendo di renderla accessibile dai repository dell’organizzazione oppure dai repository posseduti dall’utente. Al runner viene passato un token di installazione con ambito ristretto, in sola lettura sul repository della action, che scade dopo un’ora. Attenzione all’avvertimento della documentazione: rendendo un repository privato accessibile ad altri workflow, i collaboratori esterni di quegli altri repository ottengono un accesso indiretto ai contenuti, perché possono leggere i log delle esecuzioni.

Un punto che l’esame ama mettere alla prova: pubblicare su Marketplace non è ciò che rende una action utilizzabile. Una action in un repository pubblico è già consumabile da chiunque conosca il riferimento. Il Marketplace aggiunge scopribilità, una scheda, categorie e badge, non il permesso di eseguirla.

Pubblicare su GitHub Marketplace

I requisiti strutturali sono pochi ma rigidi. Il repository deve essere pubblico. Deve contenere un solo file di metadati, action.yml oppure action.yaml, nella root: eventuali metadati in sottocartelle non vengono elencati. Il campo name deve essere univoco, cioè non può coincidere con una action già presente sul Marketplace, con nomi di utenti o organizzazioni GitHub (a meno che sia il proprietario stesso a pubblicare), con categorie o con nomi di funzionalità riservate da GitHub.

Il flusso operativo passa dalla pagina del file di metadati: aprendola compare un banner con Draft a release, e nella bozza di release si spunta Publish this Action to the GitHub Marketplace. Prima però il proprietario del repository o un amministratore dell’organizzazione deve accettare il GitHub Marketplace Developer Agreement, e per completare la pubblicazione serve l’autenticazione a due fattori attiva. Si assegna poi una categoria primaria, con una secondaria facoltativa, che è ciò che governa la ricerca.

Per ritirare una action dal Marketplace non si cancella nulla: si modifica ogni release pubblicata togliendo quella stessa spunta e si aggiorna la release.

Sui badge, distingui bene due cose. Il badge di verified creator identifica organizzazioni partner e si richiede scrivendo a partnerships@github.com: certifica l’identità dell’autore, non la bontà del codice. Non esiste alcuna revisione di sicurezza implicita nella presenza sul Marketplace, e considerarlo un audit è esattamente l’errore che le domande scenario tendono a punire.

Tag mobili, release e immutable releases

La strategia raccomandata è il versionamento semantico con tag del tipo v1.1.3, tenendo però aggiornati anche il tag maggiore v1 e quello minore v1.1 in modo che puntino sempre al commit appropriato più recente. Il tag maggiore mobile è il vero contratto che offri ai consumatori: promette compatibilità all’indietro dentro la major.

Spostare un tag significa force-push, con git tag -f seguito da git push -f --tags, tipicamente automatizzato da un workflow che al momento della pubblicazione compila il bundle e riallinea i tag. Un dettaglio di igiene: le dipendenze compilate non vanno committate sul branch principale, ma solo sul commit che diventa release.

Qui entra il tema delle immutable releases. Quando una release immutabile viene pubblicata, il tag associato resta bloccato su uno specifico commit, non può essere modificato e non può essere cancellato finché la release esiste; anche gli asset sono protetti e viene generata automaticamente una release attestation che lega tag, commit SHA e asset. La conseguenza pratica è netta: non puoi più force-pushare un tag legato a una release. La strategia corretta diventa quindi mista, ed è la confusione tipica da evitare: le versioni puntuali come v1.2.3 sono release immutabili, mentre il tag mobile v1 va creato come semplice tag Git, senza release associata. Tag e release non sono la stessa cosa.

Che cosa fissa chi consuma la tua action

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      # tag maggiore mobile: riceve patch e minor
      - uses: my-org/setup-tooling@v2
      # commit SHA completo: riferimento che non si sposta
      - uses: my-org/setup-tooling@0a1b2c3d4e5f60718293a4b5c6d7e8f9a0b1c2d3 # v2.4.1
      # action nello stesso repository
      - uses: ./.github/actions/setup-tooling

La raccomandazione di sicurezza è fissare il full-length commit SHA, perché secondo la documentazione è attualmente l’unico modo di usare una action come riferimento davvero immutabile: un tag può essere spostato o cancellato se qualcuno compromette il repository che lo ospita. Il costo è la perdita degli aggiornamenti automatici, e va ricordato che Dependabot genera avvisi solo per le action che usano versionamento semantico: per questo si annota la versione leggibile in un commento accanto allo SHA. Repository e organizzazioni possono anche imporre lo SHA pinning tramite policy. Come autore, il tuo compito è rendere questa scelta indolore: release ordinate, tag maggiore affidabile e note che dichiarino le rotture in modo esplicito.