Pipeline CI/CD Microsoft Fabric avec GitHub
Partie 3 : Secrets, scripts Python et workflows GitHub Actions
Cette troisième partie 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 |



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).


À 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.
# 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.
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
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
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
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.
Poursuivre la lecture
Les différentes parties du tutoriel
Retrouvez les quatre parties de ce tutoriel sur la mise en place d’un pipeline CI/CD entre GitHub et Microsoft Fabric, depuis la préparation initiale jusqu’au test de bout en bout.