Existe-t-il un moyen de cloner ou copier un pipeline CI/CD existant dans Azure DevOps

J’ai quelques pipelines CI que j’utilise dans Azure DevOps pour compiler des applications Xamarin et je souhaite en créer un nouveau qui fusionne les fonctionnalités des deux existants. Existe-t-il un moyen de copier ou cloner un pipeline existant afin que je puisse apporter des modifications au nouveau pipeline sans impacter les pipelines existants ?

J’ai vu que je peux exporter un pipeline vers un fichier JSON puis le réimporter. Toutes les valeurs d’identifiant dans le fichier JSON sont des GUID. Le processus d’importation créera-t-il de nouveaux GUID ou l’importation du fichier JSON écrasera-t-elle le pipeline existant ?

MISE À JOUR du 11 février 2020

Je ne suis pas sûr que ce soit un changement très récent, mais vous pouvez désormais à nouveau cloner facilement un pipeline existant. Depuis Pipelines, cliquez sur le pipeline que vous souhaitez cloner. Sur la page où l’historique des builds est affiché, l’option Cloner a été déplacée dans le menu des points de suspension sur cette page.

Bonjour,

Cloner ou copier un pipeline CI/CD dans Azure DevOps est une opération très utile pour éviter de recréer des configurations complexes depuis zéro. Que vous souhaitiez dupliquer un pipeline au sein du même projet ou le copier vers un autre projet ou organisation, plusieurs méthodes sont à votre disposition. Je vais vous présenter toutes les approches, de la plus simple à la plus avancée.

Vue d’ensemble des options disponibles

Méthode Complexité Fidélité Idéal pour
Clone via l’interface graphique Très facile Haute Même projet
Export/Import YAML Facile Complète Entre projets/organisations
Azure DevOps CLI Moyenne Complète Automatisation, scripts
API REST Azure DevOps Avancée Complète Intégration programmatique
Pipeline as Code (YAML) Bonne pratique Réutilisable Tous cas de figure

Méthode 1 : Cloner via l’interface graphique (le plus simple)

Pour les pipelines classiques (interface graphique)

Azure DevOps offre une fonctionnalité native de clonage pour les pipelines Classic :

  1. Naviguez vers Pipelines > Pipelines dans votre projet Azure DevOps
  2. Trouvez le pipeline que vous souhaitez cloner
  3. Cliquez sur les trois points (…) à droite du pipeline
  4. Sélectionnez “Clone” ou “Cloner”
  5. Le pipeline est dupliqué avec le nom Copie de [Nom du pipeline]
  6. Renommez et modifiez la copie selon vos besoins

Note : Cette option est disponible pour les pipelines Classic Build et Classic Release. Pour les pipelines YAML, l’approche est différente (voir méthode 2).

Pour les pipelines Release (CD)

  1. Allez dans Pipelines > Releases
  2. Sélectionnez votre pipeline de release
  3. Cliquez sur le menu “…” > “Clone”
  4. La copie est créée dans le même projet

Méthode 2 : Export/Import de pipeline Classic (entre projets)

Pour copier un pipeline vers un autre projet ou une autre organisation :

Export

  1. Dans le pipeline Classic, cliquez sur les trois points (…) > “Export” ou “Exporter”
  2. Un fichier JSON est téléchargé sur votre machine

Import

  1. Dans le projet de destination, allez dans Pipelines > Pipelines
  2. Cliquez sur “New pipeline” > “Import a pipeline” (ou “Importer un pipeline”)
  3. Sélectionnez le fichier JSON exporté
  4. Le pipeline est recréé — vous devrez reconfigurer les connections de service et les agents pools qui diffèrent entre projets

Méthode 3 : Duplication de pipeline YAML (recommandée)

Pour les pipelines YAML (la méthode moderne recommandée), la duplication se fait au niveau du fichier YAML lui-même.

Copier le fichier YAML

# Dans votre dépôt Git
cp azure-pipelines.yml azure-pipelines-nouveau.yml

Créer un nouveau pipeline pointant vers le nouveau fichier

  1. Allez dans Pipelines > New pipeline
  2. Sélectionnez votre dépôt
  3. Choisissez “Existing Azure Pipelines YAML file”
  4. Sélectionnez le fichier azure-pipelines-nouveau.yml
  5. Configurez les variables et triggers selon vos besoins

Utiliser les templates YAML pour éviter la duplication

La vraie bonne pratique est d’utiliser les templates YAML pour partager des configurations entre pipelines :

# templates/build-steps.yml (template réutilisable)
parameters:
- name: buildConfiguration
  type: string
  default: 'Release'
- name: dotnetVersion
  type: string
  default: '8.x'

steps:
- task: UseDotNet@2
  displayName: 'Installer .NET ${{ parameters.dotnetVersion }}'
  inputs:
    version: '${{ parameters.dotnetVersion }}'

- task: DotNetCoreCLI@2
  displayName: 'Build - ${{ parameters.buildConfiguration }}'
  inputs:
    command: 'build'
    arguments: '--configuration ${{ parameters.buildConfiguration }}'

- task: DotNetCoreCLI@2
  displayName: 'Tests unitaires'
  inputs:
    command: 'test'
    arguments: '--configuration ${{ parameters.buildConfiguration }} --collect:"XPlat Code Coverage"'
# azure-pipelines-app1.yml - Pipeline pour l'application 1
trigger:
  branches:
    include: [main, develop]
  paths:
    include: ['src/App1/**']

variables:
  buildConfiguration: 'Release'

pool:
  vmImage: 'ubuntu-latest'

stages:
- stage: Build
  jobs:
  - job: BuildJob
    steps:
    - template: templates/build-steps.yml
      parameters:
        buildConfiguration: $(buildConfiguration)
        dotnetVersion: '8.x'
# azure-pipelines-app2.yml - Pipeline pour l'application 2 (réutilise le même template)
trigger:
  paths:
    include: ['src/App2/**']

pool:
  vmImage: 'ubuntu-latest'

stages:
- stage: Build
  jobs:
  - job: BuildJob
    steps:
    - template: templates/build-steps.yml
      parameters:
        buildConfiguration: 'Debug'
        dotnetVersion: '6.x'

Méthode 4 : Azure DevOps CLI

L’Azure DevOps CLI (extension az devops) permet de gérer les pipelines par script.

Installation et configuration

# Installer l'extension Azure DevOps CLI
az extension add --name azure-devops

# Se connecter
az devops configure --defaults organization=https://dev.azure.com/MonOrganisation project=MonProjet
az devops login

Lister et exporter les définitions de pipeline

# Lister tous les pipelines du projet
az pipelines list --output table

# Obtenir la définition JSON d'un pipeline spécifique
az pipelines show --id 42 --output json > pipeline-backup.json

# Ou par nom
az pipelines show --name "MonPipeline" --output json > pipeline-backup.json

Créer un pipeline depuis une définition YAML

# Créer un nouveau pipeline YAML
az pipelines create \
  --name "MonPipeline-Copie" \
  --repository "MonRepo" \
  --branch "main" \
  --yml-path "azure-pipelines-copie.yml" \
  --repository-type tfsgit

# Créer dans un autre projet
az pipelines create \
  --name "MonPipeline-Copie" \
  --repository "MonRepo" \
  --branch "main" \
  --yml-path "azure-pipelines.yml" \
  --organization "https://dev.azure.com/AutreOrganisation" \
  --project "AutreProjet"

Script de copie automatisée

#!/bin/bash
# Script pour copier un pipeline entre projets

SOURCE_ORG="https://dev.azure.com/SourceOrganisation"
SOURCE_PROJECT="SourceProjet"
DEST_ORG="https://dev.azure.com/DestinationOrganisation"
DEST_PROJECT="DestinationProjet"
PIPELINE_NAME="MonPipeline"

echo "Récupération de la définition du pipeline source..."
az pipelines show \
  --name "$PIPELINE_NAME" \
  --organization "$SOURCE_ORG" \
  --project "$SOURCE_PROJECT" \
  --output json > /tmp/pipeline-definition.json

echo "Le pipeline a été exporté dans /tmp/pipeline-definition.json"
echo "Veuillez adapter les repository, service connections et variables, puis relancer."

Méthode 5 : API REST Azure DevOps

Pour une intégration programmatique complète :

# Script PowerShell pour cloner un pipeline via l'API REST

$organization = "MonOrganisation"
$sourceProject = "SourceProjet"
$destProject = "DestinationProjet"
$pipelineId = 42
$pat = "votre-personal-access-token"  # Créez un PAT dans Azure DevOps

$headers = @{
    Authorization = "Basic " + [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$pat"))
    "Content-Type" = "application/json"
}

# Récupérer la définition du pipeline source
$sourceUrl = "https://dev.azure.com/$organization/$sourceProject/_apis/build/definitions/$pipelineId`?api-version=7.1"
$pipelineDef = Invoke-RestMethod -Uri $sourceUrl -Headers $headers -Method Get

# Modifier pour le projet de destination
$pipelineDef.name = "$($pipelineDef.name) - Copie"
$pipelineDef.PSObject.Properties.Remove('id')
$pipelineDef.PSObject.Properties.Remove('revision')
$pipelineDef.PSObject.Properties.Remove('uri')
$pipelineDef.PSObject.Properties.Remove('url')

# Créer dans le projet de destination
$destUrl = "https://dev.azure.com/$organization/$destProject/_apis/build/definitions?api-version=7.1"
$body = $pipelineDef | ConvertTo-Json -Depth 20

$newPipeline = Invoke-RestMethod -Uri $destUrl -Headers $headers -Method Post -Body $body
Write-Output "Pipeline créé avec l'ID : $($newPipeline.id)"

Copier les variables de pipeline

N’oubliez pas que les variables de pipeline et les variables secrètes ne sont pas incluses dans l’export/clone automatique.

# Lister les variables d'un pipeline
az pipelines variable list --pipeline-id 42

# Ajouter une variable au pipeline copié
az pipelines variable create \
  --pipeline-id 99 \
  --name "MonVariable" \
  --value "MaValeur"

# Ajouter une variable secrète
az pipelines variable create \
  --pipeline-id 99 \
  --name "MonSecret" \
  --value "ValeurSecrète" \
  --secret true

Copier les environnements et approvals

Si votre pipeline utilise des Environments (pour les approvals et gates) :

# Lister les environnements
az devops invoke \
  --area distributedtask \
  --resource environments \
  --organization https://dev.azure.com/MonOrganisation \
  --project MonProjet \
  --api-version "7.1"

# Créer un environnement dans le projet de destination
az devops invoke \
  --area distributedtask \
  --resource environments \
  --organization https://dev.azure.com/MonOrganisation \
  --project DestinationProjet \
  --http-method POST \
  --in-file environment-definition.json \
  --api-version "7.1"

Bonnes pratiques pour la gestion des pipelines

Structurer vos pipelines pour faciliter la réutilisation

# Utiliser des variable groups partageables
variables:
- group: "Variables-Communes"        # Groupe de variables Azure DevOps
- group: "Variables-Environnement-Prod"
- name: buildConfiguration
  value: 'Release'

Utiliser des pipeline templates dans un dépôt centralisé

# Référencer un template depuis un autre dépôt
resources:
  repositories:
  - repository: templates
    type: git
    name: MonOrganisation/PipelineTemplates
    ref: refs/heads/main

stages:
- template: stages/build-and-test.yml@templates
  parameters:
    buildConfiguration: Release

En résumé, pour une copie rapide dans le même projet, utilisez la fonctionnalité Clone native de l’interface Azure DevOps. Pour copier entre projets ou automatiser la duplication, l’approche YAML avec templates est la plus robuste et maintenable à long terme.

Si vous pouvez préciser votre cas d’usage (pipeline Classic ou YAML, même projet ou migration vers un autre projet/organisation), je pourrai vous fournir une procédure encore plus détaillée adaptée à votre situation spécifique.