Effectuer une migration depuis Travis vers Azure Pipelines

Azure DevOps Services

Ce guide vous aide à migrer de Travis vers Azure Pipelines. Il montre comment traduire une configuration Travis vers une configuration Azure Pipelines.

Différences clés

Travis et Azure Pipelines diffèrent de plusieurs façons, notamment :

  • Les builds Travis ont des phases, des travaux et des phases, tandis qu’Azure Pipelines a des étapes que vous organisez et exécutez dans n’importe quel ordre ou regroupement que vous choisissez.

  • Azure Pipelines vous permet de stocker des définitions de travaux et des étapes dans des fichiers YAML distincts dans le même référentiel ou un autre référentiel. Cette approche vous permet de partager des étapes entre plusieurs pipelines.

  • Azure Pipelines offre un support complet à des fins de génération et de test sur des images Linux, Windows et macOS gérées par Microsoft. Pour plus d’informations sur les agents hébergés, consultez Agents hébergés par Microsoft.

Prérequis

Langage

Travis utilise le mot clé language afin d’identifier l’environnement de build requis pour configurer pour votre build. Par exemple, pour sélectionner Node.js 16.x :

.travis.yml

language: node_js
node_js:
  - 22

Les agents hébergés par Microsoft incluent les kits SDK pour de nombreuses langues par défaut. Pour utiliser une version de langue spécifique, vous devrez peut-être utiliser une tâche de sélection de langue pour configurer l’environnement.

Par exemple, pour sélectionner Node.js 16.x :

azure-pipelines.yml

steps:
- task: UseNode@1
  inputs:
    version: '22.x'

Mappages de langage

Le language mot clé dans Travis CI fonctionne à la fois comme la version des outils de langage à utiliser et un signal implicite que de nombreuses étapes de génération sont effectuées. Dans Azure Pipelines, vous spécifiez les commandes que vous souhaitez exécuter.

Voici un guide de traduction du mot clé language vers les commandes exécutées automatiquement pour les langages les plus couramment utilisés :

Langage Commandes
c
cpp
./configure
make
make install
csharp nuget restore [solution.sln]
msbuild /p:Configuration=Release [solution.sln]
clojure lein deps
lein test
go go get -t -v ./...
make ougo test
java
groovy
Gradle :
gradle assemble
gradle check

Maven :
mvn install -DskipTests=true -Dmaven.javadoc.skip=true -B -V
mvn test -B

Ant :
ant test
node_js npm install ounpm ciouyarn
npm test
objective-c
swift
pod install oubundle exec pod install
xcodebuild -scheme [scheme] build test \| xcpretty
perl cpanm --quiet --installdeps --notest .

Build.PL :
perl ./Build.pl
./Build test

Makefile.PL :
perl Makefile.PL
make test

Makefile :
make test
php phpunit
python pip install -r requirements.txt
ruby bundle install --jobs=3 --retry=3
rake

Vous pouvez activer des langages moins courants, mais ils nécessitent une autre étape d’installation de dépendance ou une exécution à l’intérieur d’un conteneur Docker :

Langage Commandes
crystal docker run -v $(pwd):/src -w /src crystallang/crystal shards install
docker run -v $(pwd):/src -w /src crystallang/crystal crystal spec
d sudo wget http://master.dl.sourceforge.net/project/d-apt/files/d-apt.list -O /etc/apt/sources.list.d/d-apt.list
sudo apt-get update
sudo apt-get -y --allow-unauthenticated install --reinstall d-apt-keyring
sudo apt-get update
sudo apt-get install dmd-compiler dub
dub test --compiler=dmd
dart wget https://dl-ssl.google.com/linux/linux_signing_key.pub -O - \| sudo apt-key add -
wget https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list -O /etc/apt/sources.list.d/dart_stable.list
sudo apt-get update
sudo apt-get install dart
/usr/lib/dart/bin/pub get
/usr/lib/dart/bin/pub run test
erlang sudo apt-get install rebar
rebar get-deps
rebar compile
rebar skip_deps=true eunit
elixir sudo apt-get install elixir
mix local.rebar --force
mix local.hex --force
mix deps.get
mix test
haskell sudo apt-get install cabal-install
cabal install --only-dependencies --enable-tests
cabal configure --enable-tests
cabal build
cabal test
haxe sudo apt-get install haxe
yes \| haxelib install [hxml]
haxe [hxml]
julia sudo apt-get install julia
julia -e "using Pkg; Pkg.build(); end"
julia --check-bounds=yes -e "Pkg; Pkg.test(coverage=true); end"
nix docker run -v $(pwd):/src -w /src nixos/nix nix-build
perl6 sudo apt-get install rakudo
PERL6LIB=lib prove -v -r --exec=perl6 t/
rust curl -sSf https://sh.rustup.rs | sh -s -- -y
cargo build --verbose
cargo test --verbose
scala echo "deb https://repo.scala-sbt.org/scalasbt/debian /" | /etc/apt/sources.list.d/sbt.list
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823
sudo apt-get update
sudo apt-get install sbt
sbt ++2.11.6 test
smalltalk docker run -v $(pwd):/src -w /src hpiswa/smalltalkci smalltalkci

Sélections de langages multiples

Vous pouvez également configurer un environnement qui prend en charge la génération d’applications différentes dans plusieurs langages. Par exemple, pour garantir que l’environnement de build cible à la fois Node.JS 16.x et Ruby 3.2 ou mieux :

azure-pipelines.yml

steps:
- task: UseNode@1
  inputs:
    version: '8.x'
- task: UseRubyVersion@0
  inputs:
    versionSpec: '>= 3.2'

Phases

Dans Travis, les étapes sont définies dans un ensemble fixe de phases nommées telles que before_install ou before_script. Azure Pipelines ne comporte pas de phases nommées, et les étapes peuvent être regroupées, nommées et organisées selon le pipeline.

Par exemple :

.travis.yml

before_install:
    - npm install -g bower
install:
    - npm install
    - bower install
script:
    - npm run build
    - npm test

azure-pipelines.yml

steps:
- script: npm install -g bower
- script: npm install
- script: bower install
- script: npm run build
- script: npm test

Vous pouvez également regrouper les étapes et éventuellement les nommer :

azure-pipelines.yml

steps:
- script: |
    npm install -g bower
    npm install
    bower install
  displayName: 'Install dependencies'
- script: npm run build
- script: npm test

Travaux parallèles

Travis assure un parallélisme en vous permettant de définir un index, qui est un groupe de travaux exécutés en parallèle. Une build Travis peut comporter plusieurs index ; une fois que tous les travaux d’un index sont terminés, l’index suivant commence.

Avec Azure Pipelines, vous pouvez faire en sorte que chaque étape ou index dépende de n’importe quelle autre étape. De cette façon, vous spécifiez les étapes qui s’exécutent en série et celles qui peuvent s’exécuter en parallèle. Ainsi, vous pouvez effectuer une distribution ramifiée avec plusieurs étapes exécutées en parallèle après l’achèvement d’une étape, puis revenir à une distribution non ramifiée avec une étape unique qui s’exécute par la suite. Ce modèle vous permet de définir des flux de travail complexes, si nécessaire. Pour l’instant, voici un exemple simple :

Illustration d’une exécution parallèle simple

Par exemple, pour exécuter un script de build, puis, lorsque ce dernier est terminé, exécuter à la fois les tests unitaires et les tests d’intégration en parallèle, et, une fois tous les tests terminés, créer un package avec les artefacts, puis exécuter le déploiement en préproduction :

.travis.yml

jobs:
  include:
  - stage: build
    script: ./build.sh
  - stage: test
    script: ./test.sh unit_tests
  - script: ./test.sh integration_tests
  - stage: package
    script: ./package.sh
  - stage: deploy
    script: ./deploy.sh pre_prod

azure-pipelines.yml

jobs:
- job: build
  steps:
  - script: ./build.sh
- job: test1
  dependsOn: build
  steps:
  - script: ./test.sh unit_tests
- job: test2
  dependsOn: build
  steps:
  - script: ./test.sh integration_tests
- job: package
  dependsOn:
  - test1
  - test2
  script: ./package.sh
- job: deploy
  dependsOn: package
  steps:
  - script: ./deploy.sh pre_prod

Exécution parallèle avancée

Dans Azure Pipelines, vous disposez d’autres options et contrôlez l’orchestration de votre pipeline.

Par exemple, une équipe dispose d’un ensemble de tests unitaires rapides et d’un autre ensemble de tests d’intégration plus lents. L’équipe souhaite commencer à créer le fichier .ZIP à des fins de mise en production dès que l’unité est terminée, car cela garantit avec un degré de confiance élevé que la build fournit un bon package. Toutefois, avant de procéder au déploiement en préproduction, l’équipe veut s’assurer de la réussite de tous les tests :

Illustration d’une exécution parallèle avancée

Dans Azure Pipelines, elle peut le faire de cette façon :

azure-pipelines.yml

jobs:
- job: build
  steps:
  - script: ./build.sh
- job: test1
  dependsOn: build
  steps:
  - script: ./test.sh unit_tests
- job: test2
  dependsOn: build
  steps:
  - script: ./test.sh integration_tests
- job: package
  dependsOn: test1
  script: ./package.sh
- job: deploy
  dependsOn:
  - test1
  - test2
  - package
  steps:
  - script: ./deploy.sh pre_prod

Réutilisation d’une étape

Dans Travis, vous pouvez utiliser des matrices pour exécuter plusieurs exécutions dans une configuration unique. Dans Azure Pipelines, vous pouvez utiliser des matrices de la même façon, mais vous pouvez également implémenter la réutilisation de la configuration à l’aide de modèles.

Exemple : variable d’environnement dans une matrice

L’une des façons les plus courantes d’exécuter plusieurs builds avec une légère variation consiste à modifier l’exécution à l’aide de variables d’environnement. Par exemple, votre script de build peut rechercher la présence d’une variable d’environnement et modifier la façon dont il génère votre logiciel, ou la façon dont il teste le logiciel.

Utilisez une matrice pour exécuter une configuration de build plusieurs fois, une fois pour chaque valeur dans la variable d’environnement. Par exemple, exécutez un script donné trois fois, chaque fois avec un paramètre différent pour une variable d’environnement :

.travis.yml

os: osx
env:
  jobs:
  - MY_ENVIRONMENT_VARIABLE: 'one'
  - MY_ENVIRONMENT_VARIABLE: 'two'
  - MY_ENVIRONMENT_VARIABLE: 'three'
script: echo $MY_ENVIRONMENT_VARIABLE

azure-pipelines.yml

pool:
  vmImage: 'macOS-latest'
strategy:
  matrix:
    set_env_to_one:
      MY_ENVIRONMENT_VARIABLE: 'one'
    set_env_to_two:
      MY_ENVIRONMENT_VARIABLE: 'two'
    set_env_to_three:
      MY_ENVIRONMENT_VARIABLE: 'three'
steps:
- script: echo $(MY_ENVIRONMENT_VARIABLE)

Exemple : versions de langage dans une matrice

Un autre scénario courant consiste à effectuer une exécution sur plusieurs environnements de langage différents. Travis prend en charge une définition implicite grâce au mot clé language, tandis qu’Azure Pipelines attend une tâche explicite pour définir la configuration de cette version de langage.

Vous pouvez utiliser les options de matrice de variable d’environnement dans Azure Pipelines pour activer une matrice pour différentes versions de langage. Par exemple, vous pouvez définir une variable d’environnement dans chaque variable de matrice qui correspond à la version de langage que vous souhaitez utiliser, puis, lors de la première étape, vous pouvez utiliser cette variable d’environnement pour exécuter la tâche de configuration de langage :

.travis.yml

os: linux
jobs:
  include:
  - rvm: 2.3.7
  - rvm: 2.4.4
  - rvm: 2.5.1
script: ruby --version

azure-pipelines.yml

vmImage: 'ubuntu-latest'
strategy:
  matrix:
    ruby 2.3:
      ruby_version: '2.3.7'
    ruby 2.4:
      ruby_version: '2.4.4'
    ruby 2.5:
      ruby_version: '2.5.1'
steps:
- task: UseRubyVersion@0
  inputs:
    versionSpec: $(ruby_version)
- script: ruby --version

Exemple : systèmes d’exploitation dans une matrice

Il est également courant d’exécuter des builds dans plusieurs systèmes d’exploitation. Travis prend en charge cette définition grâce au mot clé os, tandis qu’Azure Pipelines vous permet de configurer le système d’exploitation en sélectionnant le pool à exécuter à l’aide du mot clé vmImage.

Par exemple, vous pouvez définir une variable d’environnement dans chaque variable de matrice qui correspond à l’image du système d’exploitation que vous souhaitez utiliser. Ensuite, vous définissez le pool d’ordinateurs sur la variable que vous définissez :

.travis.yml

jobs:
  include:
  - os: linux
  - os: windows
  - os: osx
script: echo Hello, world!

azure-pipelines.yml

strategy:
  matrix:
    linux:
      imageName: 'ubuntu-latest'
    mac:
      imageName: 'macOS-latest'
    windows:
      imageName: 'windows-latest'

pool:
  vmImage: $(imageName)

steps:
- script: echo Hello, world!

Gestion des réussites et des échecs

Travis vous permet de spécifier des étapes qui s’exécutent lorsque la compilation réussit, à l’aide de la after_success phase, ou lorsque la compilation échoue, à l’aide de la after_failure phase. En utilisant Azure Pipelines, vous pouvez définir des conditions de réussite et d’échec en fonction du résultat de n’importe quelle étape, ce qui permet des pipelines plus flexibles et puissants.

.travis.yml

build: ./build.sh
after_success: echo Success 
after_failure: echo Failed 

azure-pipelines.yml

steps:
- script: ./build.sh
- script: echo Success
  condition: succeeded()
- script: echo Failed
  condition: failed()

Gestion avancée des réussites et des échecs

Dans Azure Pipelines, vous pouvez programmer un ensemble flexible de dépendances et de conditions pour contrôler des flux entre plusieurs travaux.
Vous pouvez configurer des travaux à exécuter en fonction de la réussite ou de l’échec de travaux précédents ou en fonction de variables d’environnement. Vous pouvez même configurer des travaux pour qu’ils s’exécutent en permanence, quelle que soit la réussite des autres travaux.

Par exemple, si vous souhaitez exécuter un script en cas d’échec de la build, mais uniquement dans le cas d’une exécution en tant que build sur la branche primaire :

azure-pipelines.yml

jobs:
- job: build
  steps:
  - script: ./build.sh
- job: alert
  dependsOn: build
  condition: and(failed(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
  steps:
  - script: ./sound_the_alarms.sh

Variables prédéfinies

Travis et Azure Pipelines définissent plusieurs variables d’environnement pour vous aider à inspecter et à interagir avec l’environnement d’exécution du système CI.

Dans la plupart des cas, une variable Azure Pipelines correspond à la variable d’environnement dans Travis. Voici une liste des variables d’environnement couramment utilisées dans Travis et leur variable analogique dans Azure Pipelines :

Travis Azure Pipelines Description
CI=true ou TRAVIS=true TF_BUILD=True Indique que votre build est en cours d’exécution dans le système CI ; utile pour les scripts qui sont également destinés à s’exécuter localement pendant le développement.
TRAVIS_BRANCH Builds CI :
BUILD_SOURCEBRANCH

Builds de demande de tirage (pull request) :
SYSTEM_PULLREQUEST_TARGETBRANCH
Le nom de la branche pour laquelle la build est mise en file d'attente, ou le nom de la branche ciblée par la pull request.
TRAVIS_BUILD_DIR BUILD_SOURCESDIRECTORY Emplacement de votre source extraite et répertoire de travail par défaut.
TRAVIS_BUILD_NUMBER BUILD_BUILDID Identificateur numérique unique pour l’appel de build actuel.
TRAVIS_COMMIT Builds CI :
BUILD_SOURCEVERSION
ID de validation en cours de génération.
TRAVIS_COMMIT Builds de demande de tirage (pull request) :
git rev-parse HEAD^2
Pour les builds de validation de demande de tirage (pull request), Azure Pipelines définit BUILD_SOURCEVERSION selon la validation de fusion résultante de la demande de tirage en tant que valeur primaire ; cette commande identifie la validation de la demande de tirage elle-même.
TRAVIS_COMMIT_MESSAGE BUILD_SOURCEVERSIONMESSAGE Message de journal de la validation générée.
TRAVIS_EVENT_TYPE BUILD_REASON Raison pour laquelle la compilation est mise en file d’attente ; un tableau de correspondance des valeurs se trouve dans le tableau « raisons de compilation » ci-dessous.
TRAVIS_JOB_NAME AGENT_JOBNAME Nom du travail actuel, s’il est spécifié.
TRAVIS_OS_NAME AGENT_OS Système d’exploitation sur lequel le travail s’exécute ; une carte de valeurs se trouve dans le tableau « Systèmes d’exploitation » ci-dessous.
TRAVIS_PULL_REQUEST Azure Repos :
SYSTEM_PULLREQUEST_PULLREQUESTID

GitHub :
SYSTEM_PULLREQUEST_PULLREQUESTNUMBER
Numéro de demande de tirage (pull request) qui a déclenché cette build. (Pour les builds GitHub, il s’agit d’un identificateur unique qui n’est pas le numéro de la demande de tirage [pull request].)
TRAVIS_PULL_REQUEST_BRANCH SYSTEM_PULLREQUEST_SOURCEBRANCH Nom de la branche à partir de laquelle la demande de tirage (pull request) provient.
TRAVIS_PULL_REQUEST_SHA Builds de demande de tirage (pull request) :
git rev-parse HEAD^2
Pour les builds de validation de demande de tirage (pull request), Azure Pipelines définit BUILD_SOURCEVERSION selon la validation de fusion résultante de la demande de tirage en tant que valeur primaire ; cette commande identifie la validation de la demande de tirage elle-même.
TRAVIS_PULL_REQUEST_SLUG Nom du référentiel dupliqué, si la demande de tirage (pull request) provient d’une duplication. Il n’y a pas d’élément analogique dans Azure Pipelines.
TRAVIS_REPO_SLUG BUILD_REPOSITORY_NAME Nom du référentiel pour lequel cette build est configurée.
TRAVIS_TEST_RESULT AGENT_JOBSTATUS Travis définit cette valeur 0 si toutes les étapes précédentes réussissent (retour 0). Pour Azure Pipelines, vérifiez AGENT_JOBSTATUS=Succeeded.
TRAVIS_TAG BUILD_SOURCEBRANCH Si cette build est mise en file d’attente par la création d’une balise, cette valeur est le nom de cette balise. Pour Azure Pipelines, la valeur BUILD_SOURCEBRANCH est définie sur le nom de référence Git complet, par exemple refs/tags/tag_name.
TRAVIS_BUILD_STAGE_NAME Nom de l’index dans Travis. Comme nous l’avons vu précédemment, Azure Pipelines gère le contrôle de flux à l’aide de travaux. Vous pouvez référencer AGENT_JOBNAME.

Raisons de la compilation :

La variable TRAVIS_EVENT_TYPE contient des valeurs qui correspondent aux valeurs fournies par la variable BUILD_REASON Azure Pipelines :

Travis Azure Pipelines Description
push IndividualCI La build est une build d’intégration continue à partir d’un envoi (push).
pull_request PullRequest La build a été mise en file d’attente pour valider une demande de tirage (pull request).
api Manual La build a été mise en file d’attente par l’API REST ou une requête manuelle sur la page Web.
cron Schedule La build a été planifiée.

Système d’exploitation :

La variable TRAVIS_OS_NAME contient des valeurs qui correspondent aux valeurs fournies par la variable AGENT_OS Azure Pipelines :

Travis Azure Pipelines Description
linux Linux La build s’exécute sur Linux.
osx Darwin La build s’exécute sur macOS.
windows Windows_NT La build s’exécute sur Windows.

Pour plus d’informations, consultez Variables d’environnement prédéfinies.

S’il n’existe aucune variable pour les données dont vous avez besoin, utilisez une commande shell pour l’obtenir. Par exemple, un bon substitut à une variable d’environnement contenant l’ID de validation de la pull request en cours de création consiste à exécuter une commande git : git rev-parse HEAD^2.

Génération de branches spécifiques

Par défaut, Travis et Azure Pipelines effectuent des builds CI sur toutes les branches. De même, les deux systèmes vous permettent de limiter ces builds à des branches spécifiques. Dans Azure Pipelines, les branches à générer doivent être répertoriées dans la liste include, et les branches à ne pas générer doivent être répertoriées dans la liste d’exclusion. Les caractères génériques sont pris en charge.

Par exemple, pour générer uniquement la branche primaire et celles qui commencent par le mot « releases » (mises en production) :

.travis.yml

branches:
  only:
  - main
  - /^releases.*/

azure-pipelines.yml

trigger:
  branches:
    include:
    - main
    - releases*

Mise en cache de la sortie

Travis prend en charge la mise en cache des dépendances et de la sortie de build intermédiaire pour améliorer les temps de génération. Azure Pipelines ne prend pas en charge la mise en cache de la sortie de build intermédiaire, mais offre une intégration par le biais d’Azure Artifacts aux fins du stockage des dépendances.

Sous-modules Git

Travis et Azure Pipelines clonent les dépôts Git de manière récursive par défaut. Ce paramètre par défaut signifie que l’agent clone les sous-modules, ce qui est utile, car les sous-modules contiennent généralement des dépendances. Toutefois, le clonage supplémentaire prend du temps supplémentaire. Si vous n’avez pas besoin des dépendances, désactivez le clonage des sous-modules :

.travis.yml

git:
  submodules: false

azure-pipelines.yml

checkout:
  submodules: false