CI/CD per le app Databricks con GitHub Actions

Questa pagina spiega come automatizzare la distribuzione di un'app Databricks da GitHub tramite GitHub Actions e Bundle di automazione dichiarativa. Tratta la federazione delle identità dei carichi di lavoro, il file YAML del flusso di lavoro e un controllo dello stato di integrità che conferma che l'app esegue il codice più recente dopo ogni distribuzione.

Per indicazioni GitHub Actions generiche per Azure Databricks processi e pipeline, vedere GitHub Actions. Per configurare la federazione delle identità dei carichi di lavoro, consulta Abilitare la federazione delle identità dei carichi di lavoro per GitHub Actions.

Requirements

Passaggio 1. Configurare la federazione delle identità del carico di lavoro

La federazione dell'identità del carico di lavoro consente all'GitHub Actions runner di eseguire l'autenticazione con Azure Databricks usando un token OIDC di breve durata anziché archiviare le credenziali nel repository.

Segui i passaggi descritti in Enable workload identity federation for GitHub Actions per creare un criterio di federazione per GitHub Actions sulla tua entità servizio. Prendi nota dell'ID dell'applicazione dell'entità servizio (UUID) e dell'URL dell'area di lavoro. Sono necessarie entrambe le variabili nel flusso di lavoro.

Concedi quindi all'entità servizio CAN MANAGE le autorizzazioni per l'app oppure l'autorizzazione dell'area di lavoro per creare app, se l'app non esiste ancora. Vedere Configurare le autorizzazioni per un'app Databricks.

Passaggio 2. Configurare il repository GitHub

Nel repository GitHub creare un ambiente di distribuzione per archiviare le variabili di connessione dell'area di lavoro. L'uso di un ambiente consente anche di richiedere l'approvazione manuale prima dell'esecuzione delle distribuzioni.

  1. In Impostazioni>Ambienti, crea un ambiente denominato prod (o qualsiasi nome a cui fa riferimento il flusso di lavoro).
  2. Per Variabili di ambiente, aggiungere quanto segue:
Variabile Value
DATABRICKS_HOST URL dell'area di lavoro, ad esempio https://my-workspace.cloud.databricks.com
DATABRICKS_CLIENT_ID L'ID dell'applicazione dell'entità servizio del passaggio 1

Nessuno dei due valori è una credenziale. Il criterio di federazione del service principal controlla chi può autenticarsi come tale, quindi il solo ID client non concede l'accesso. Non è necessario un segreto del client.

Passaggio 3. Configurare il bundle per le distribuzioni in produzione

In databricks.yml, dichiara un'area di lavoro host esplicita e root_path sul target prod. In questo modo il bundle viene distribuito nella stessa posizione in ogni esecuzione. La validazione in modalità di produzione richiede entrambi i campi, a meno che run_as non sia impostato su un'entità servizio. Vedere Modalità di distribuzione dei bundle di automazione dichiarativa.

targets:
  prod:
    mode: production
    workspace:
      host: https://my-workspace.cloud.databricks.com
      root_path: /Workspace/Users/<service-principal-or-owner>/.bundle/${bundle.name}/${bundle.target}
    resources:
      apps:
        my_app:
          name: my-app
          source_code_path: ./app

Sostituisci <service-principal-or-owner> con l'utente del workspace proprietario degli artefatti del bundle, in genere l'ID dell'applicazione dell'entità di servizio.

Sostituire ./app con il percorso del codice sorgente dell'app rispetto a databricks.yml. Il source_code_path campo è obbligatorio quando il codice dell'app si trova nello stesso repository del bundle. Se il codice dell'app si trova in un repository separato, usare git_source invece . Vedi app.

Passaggio 4. Aggiungi il flusso di lavoro di deploy

Aggiungere .github/workflows/deploy.yml al repository:

name: Deploy to Databricks Apps

on:
  workflow_dispatch:
  # Uncomment to deploy on every push to main once the workflow is validated.
  # push:
  #   branches: [main]

permissions:
  id-token: write # required for OIDC federation
  contents: read

jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    environment: prod
    env:
      DATABRICKS_AUTH_TYPE: github-oidc
      DATABRICKS_HOST: ${{ vars.DATABRICKS_HOST }}
      DATABRICKS_CLIENT_ID: ${{ vars.DATABRICKS_CLIENT_ID }}
    steps:
      - uses: actions/checkout@v4

      - name: Install Databricks CLI
        uses: databricks/setup-cli@main

      - name: Validate bundle
        run: databricks bundle validate --target prod

      - name: Deploy bundle
        run: databricks bundle deploy --target prod

      - name: Start or restart app
        run: databricks bundle run my_app --target prod

Sostituisci my_app nell'ultimo passaggio con la chiave di risorsa che il/la tuo/tua databricks.yml usa in resources.apps.

Il runner deve disporre dell'autorizzazione id-token: write per richiedere un token OIDC. L'azione databricks/setup-cli legge DATABRICKS_AUTH_TYPE=github-oidc e gestisce automaticamente l'autenticazione.

Avvertimento

databricks bundle deploy carica il codice sorgente e aggiorna le risorse, ma non riavvia il processo dell'app. Se si salta il passaggio finale databricks bundle run, il deploy va a buon fine nella CI mentre l'app continua a eseguire il codice precedente. Eseguire sempre il pacchetto di risorse dopo la distribuzione.

Passaggio 5. Attendere che l'app sia funzionante

Databricks consiglia di aggiungere una fase di polling dello stato dopo la distribuzione. databricks bundle run esce non appena segnala l'avvio dell'app, ma l'app potrebbe non essere ancora in esecuzione. Può comunque non riuscire durante l'avvio a causa di problemi come dipendenze mancanti, una variabile di ambiente mancante o un conflitto di porte. L'aggiunta di un passaggio di polling garantisce che anche un avvio non riuscito comporti il fallimento del flusso di lavoro:

- name: Wait for app to be running
  env:
    APP_NAME: my-app
  run: |
    for i in $(seq 1 20); do
      STATE=$(databricks apps get "$APP_NAME" --output json | jq -r '.app_status.state')
      echo "Attempt $i/20: state=$STATE"
      if [ "$STATE" = "RUNNING" ]; then
        exit 0
      fi
      sleep 15
    done
    echo "App did not reach RUNNING state within 5 minutes" >&2
    exit 1

Imposta APP_NAME sul valore dichiarato da databricks.yml in resources.apps.<key>.name, non sulla chiave della risorsa del bundle.

Gestione di un'app esistente

I nomi delle app sono univoci nell'area di lavoro. Il bundle deploy passaggio ha esito negativo quando An app with the same name already exists un altro bundle (o un'app creata manualmente) possiede già un'app di tale nome. Associare il bundle all'app esistente invece di ricrearlo.

Eseguire questa operazione una volta in locale per collegare il bundle all'app esistente:

databricks bundle deployment bind my_app <existing-app-name> --target prod --auto-approve

Eseguire di nuovo il flusso di lavoro. Le distribuzioni successive riutilizzano l'associazione.

Se l'app esistente ha una configurazione lato server (ad esempio budget_policy_id) che non è presente in databricks.yml, copiarla nel file di bundle prima di eseguire di nuovo la distribuzione. Le mancate corrispondenze vengono visualizzate come errore di "risultato incoerente" di Terraform durante il passaggio di distribuzione del bundle.

Scegliere un trigger

Iniziare con workflow_dispatch in modo che la prima distribuzione sia manuale. Una volta eseguite alcune esecuzioni, aggiungere push: branches: [main] per eseguire la distribuzione in ogni unione.

Per un ulteriore livello di sicurezza, configurare l'ambiente prod con i revisori obbligatori in Impostazioni>Ambienti>prod>regole di protezione della distribuzione. Ogni esecuzione del flusso di lavoro attende un approvatore prima che inizi il processo di distribuzione.

Passaggi successivi