---
title: "Pipeline CI/CD Microsoft Fabric avec GitHub : secrets, scripts Python et workflows GitHub Actions"
url: https://kwanzeo.com/ressources/pipeline-ci-cd-fabric-github-secrets-scripts-workflows
date: 2026-05-07
updated: 2026-10-14
---

# Pipeline CI/CD Microsoft Fabric avec GitHub : secrets, scripts Python et workflows GitHub Actions

> Partie 3 du tutoriel CI/CD Fabric avec GitHub : secrets et environnements GitHub, scripts Python validate.py et deploy.py, workflows CI, CD DEV et CD PROD.

**En résumé :** cette troisième partie du tutoriel CI/CD Fabric avec GitHub configure les secrets et environnements GitHub, puis met en place les briques techniques du pipeline : un script de validation des notebooks, un script de déploiement vers Microsoft Fabric et trois workflows GitHub Actions (CI, CD DEV, CD PROD).

## Étape 4. Configurer les secrets et environnements GitHub

### Créer les secrets de dépôt

Les secrets GitHub sont des variables d’environnement chiffrées, stockées dans le dépôt et exposées aux workflows sans apparaître en clair dans le code. Ils sont indispensables pour authentifier GitHub Actions auprès d’Azure et de l’API Microsoft Fabric.

Dans le dépôt GitHub, ouvrez Settings, dépliez Security, puis Secrets and variables et cliquez sur Actions. Cliquez sur New repository secret pour créer les secrets ci-dessous, un par un.

| Nom du secret | Valeur |
| --- | --- |
| AZURE_CLIENT_ID | ID d’application du Service Principal |
| AZURE_CLIENT_SECRET | Valeur du secret client généré dans Azure |
| AZURE_SUBSCRIPTION_ID | ID de l’abonnement Azure |
| AZURE_TENANT_ID | ID de l’annuaire Microsoft Entra ID |
| FABRIC_WORKSPACE_DEV_ID | ID du workspace Fabric DEV |
| FABRIC_WORKSPACE_PROD_ID | ID du workspace Fabric PROD |

![Accès aux paramètres de secrets d'un dépôt GitHub.](ressources/pipeline-ci-cd-fabric-github-secrets-scripts-workflows/add-secret-in-github1.jpg)

![Écran d'ajout d'un secret dans GitHub Actions.](ressources/pipeline-ci-cd-fabric-github-secrets-scripts-workflows/add-secret-in-github2.jpg)

![Validation d'un secret de dépôt GitHub.](ressources/pipeline-ci-cd-fabric-github-secrets-scripts-workflows/add-secret-in-github3.jpg)

### Créer les environnements GitHub

Les environnements GitHub permettent de cibler chaque workflow CD vers une cible distincte. Ils sont référencés dans les fichiers YAML et doivent donc exister dans le dépôt.

- Dans Settings du dépôt, ouvrir Environments dans le menu de gauche.
- Cliquer sur New environment et créer un environnement nommé `development`.
- Refaire la même opération pour un environnement nommé `production`.
- Laisser les options par défaut (pas de protection particulière).

![Création d'un environnement GitHub.](ressources/pipeline-ci-cd-fabric-github-secrets-scripts-workflows/add-environement-in-github1.jpg)

![Liste des environnements development et production dans GitHub.](ressources/pipeline-ci-cd-fabric-github-secrets-scripts-workflows/all-environement-created-in-github.jpg)

**À savoir :** sur le plan GitHub Free avec dépôt privé, l’approbation manuelle d’environnement n’est pas disponible. La séparation DEV / PROD est alors assurée par la stratégie de branches (`main` vers DEV, `release/*` vers PROD) et la protection de branches.

## Étape 5. Créer les scripts Python

### requirements.txt

Listez à la racine les dépendances Python utilisées par les scripts et les workflows.

```text
 # HTTP et APIs
requests>=2.31.0

 # Authentification Azure
azure-identity>=1.15.0

 # Tests
pytest>=7.4.0

 # Qualité de code
flake8>=6.1.0
```

### scripts/validate.py

Ce script parcourt récursivement le dossier `fabric/notebooks` et vérifie que chaque fichier `.ipynb` est un JSON valide. Il est exécuté dans le pipeline CI lors des Pull Requests pour bloquer les notebooks corrompus avant fusion. Il ne valide pas le contenu Jupyter, uniquement la structure JSON.

### scripts/deploy.py

Le script `deploy.py` synchronise les notebooks locaux vers Microsoft Fabric via l’API REST. Il liste les items existants dans le workspace cible, puis effectue une création (POST) ou une mise à jour (PATCH) en fonction du `displayName` du notebook. L’authentification s’appuie sur un token Azure AD obtenu via `az account get-access-token`.

```python
import os
import requests
import argparse
import base64

API = "https://api.fabric.microsoft.com/v1"

def get_items(workspace_id, token):
    url = f"{API}/workspaces/{workspace_id}/items"
    headers = {"Authorization": f"Bearer {token}"}
    r = requests.get(url, headers=headers)
    return r.json().get("value", []) if r.status_code == 200 else []

def upsert_notebook(workspace_id, token, path, existing):
    name = os.path.basename(path)
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    }
    with open(path, "rb") as f:
        content = base64.b64encode(f.read()).decode("utf-8")
    payload = {
        "displayName": name,
        "type": "Notebook",
        "definition": {
            "format": "ipynb",
            "parts": [
                {
                    "path": "notebook.ipynb",
                    "payloadType": "InlineBase64",
                    "payload": content
                }
            ]
        }
    }
    found = next((x for x in existing if x["displayName"] == name), None)
    if found:
        url = f"{API}/workspaces/{workspace_id}/items/{found['id']}"
        r = requests.patch(url, headers=headers, json=payload)
        print("UPDATED" if r.ok else r.text)
    else:
        url = f"{API}/workspaces/{workspace_id}/items"
        r = requests.post(url, headers=headers, json=payload)
        print("CREATED" if r.ok else r.text)

def main(workspace_id, token, path):
    notebooks = os.path.join(path, "notebooks")
    existing = get_items(workspace_id, token)
    if not os.path.exists(notebooks):
        print(f"Folder not found: {notebooks}")
        return
    for f in os.listdir(notebooks):
        if f.endswith(".ipynb"):
            upsert_notebook(workspace_id, token, os.path.join(notebooks, f), existing)

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--workspace-id", required=True)
    parser.add_argument("--token", required=True)
    parser.add_argument("--artifacts-path", required=True)
    args = parser.parse_args()
    main(args.workspace_id, args.token, args.artifacts_path)
```

## Étape 6. Créer les workflows GitHub Actions

Les workflows sont des fichiers YAML dans `.github/workflows/`. Trois fichiers couvrent l’ensemble du cycle CI/CD.

| Workflow | Fichier | Déclencheur | Objectif |
| --- | --- | --- | --- |
| CI | .github/workflows/ci.yml | Pull Request vers main | Lint et validation des notebooks avant merge. |
| CD DEV | .github/workflows/cd-dev.yml | Push sur main | Déploiement automatique vers le workspace Fabric DEV. |
| CD PROD | .github/workflows/cd-prod.yml | Push sur release/* | Déploiement contrôlé vers le workspace Fabric PROD. |

### ci.yml

```yaml
name: CI
on:
  pull_request:
    branches: [ main ]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.10"
      - name: Install dependencies
        run: pip install -r requirements.txt
      - name: Lint
        run: flake8 scripts/
      - name: Validate notebooks
        run: python scripts/validate.py --path fabric/notebooks/
```

### cd-dev.yml

```yaml
name: CD DEV
on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: development
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.10"
      - run: pip install -r requirements.txt
      - uses: azure/login@v2
        with:
          creds: |
            {
              "clientId": "${{ secrets.AZURE_CLIENT_ID }}",
              "clientSecret": "${{ secrets.AZURE_CLIENT_SECRET }}",
              "subscriptionId": "${{ secrets.AZURE_SUBSCRIPTION_ID }}",
              "tenantId": "${{ secrets.AZURE_TENANT_ID }}"
            }
      - name: Get Fabric token
        id: token
        run: |
          T=$(az account get-access-token --resource https://api.fabric.microsoft.com --query accessToken -o tsv)
          echo "token=$T" >> $GITHUB_OUTPUT
      - name: Deploy DEV
        run: |
          python scripts/deploy.py \
            --workspace-id "${{ secrets.FABRIC_WORKSPACE_DEV_ID }}" \
            --token "${{ steps.token.outputs.token }}" \
            --artifacts-path fabric/
```

### cd-prod.yml

```yaml
name: CD PROD
on:
  push:
    branches:
      - "release/**"

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.10"
      - run: pip install -r requirements.txt
      - uses: azure/login@v2
        with:
          creds: |
            {
              "clientId": "${{ secrets.AZURE_CLIENT_ID }}",
              "clientSecret": "${{ secrets.AZURE_CLIENT_SECRET }}",
              "subscriptionId": "${{ secrets.AZURE_SUBSCRIPTION_ID }}",
              "tenantId": "${{ secrets.AZURE_TENANT_ID }}"
            }
      - name: Get Fabric token
        id: token
        run: |
          T=$(az account get-access-token --resource https://api.fabric.microsoft.com --query accessToken -o tsv)
          echo "token=$T" >> $GITHUB_OUTPUT
      - name: Deploy PROD
        run: |
          python scripts/deploy.py \
            --workspace-id "${{ secrets.FABRIC_WORKSPACE_PROD_ID }}" \
            --token "${{ steps.token.outputs.token }}" \
            --artifacts-path fabric
```

## Ce qu’il faut retenir avant de continuer

Vous disposez maintenant de tous les éléments fonctionnels du pipeline : secrets, environnements, scripts et workflows. La dernière partie traite la sécurisation des branches, le premier push, et le test de bout en bout du pipeline jusqu’au déploiement en production.

Pour industrialiser vos développements Microsoft Fabric, découvrez [notre accompagnement Microsoft Fabric](/technologies/microsoft-fabric) ou [contactez nos équipes](/contact).

### Quels secrets GitHub faut-il créer pour le pipeline ?

AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, AZURE_SUBSCRIPTION_ID, AZURE_TENANT_ID, ainsi que les identifiants des workspaces FABRIC_WORKSPACE_DEV_ID et FABRIC_WORKSPACE_PROD_ID.

### Comment séparer DEV et PROD sur un dépôt privé en plan GitHub Free ?

L'approbation manuelle d'environnement n'y est pas disponible. La séparation est assurée par la stratégie de branches (main vers DEV, release/* vers PROD) et par la protection des branches.
