Azure DevOps Services
本指南旨在帮助你从 Travis 迁移到 Azure Pipelines。 本指南介绍如何从 Travis 配置转换为 Azure Pipelines 配置。
我们需要你的帮助来完善本指南! 请提交评论或直接贡献你的更改。
主要区别
Travis 和 Azure Pipelines 之间存在许多差异,包括:
Travis 生成具有“阶段”、“作业”和“时期”,而 Azure Pipelines 具有可以按你选择的任意顺序或分组排列和执行的步骤。
Azure Pipelines 允许将作业定义和步骤存储在相同或不同存储库中的单独 YAML 文件中,从而允许跨多个管道共享步骤。
Azure Pipelines 为在 Microsoft 管理的 Linux、Windows 和 macOS 映像上进行生成和测试提供完全支持。 有关托管代理的详细信息,请参阅 Microsoft 托管代理。
先决条件
- GitHub 帐户,可在其中创建存储库。 免费创建一个。
- Azure DevOps 组织。 免费创建一个。 如果你的团队已创建帐户,请确保你是要使用的 Azure DevOps 项目的管理员。
- 能够在 Microsoft 托管的代理上运行管道。 可以购买并行作业,也可以请求免费层。
- Azure Pipelines 的基础知识。 如果不熟悉 Azure Pipelines,请在开始迁移之前参阅以下内容,详细了解 Azure Pipelines 及其工作原理:
语言
Travis 使用 language
关键字来确定要为生成设置的必备生成环境。 例如,若要选择 Node.JS 16.x:
.travis.yml
language: node_js
node_js:
- 16
默认情况下,Microsoft 托管代理包含多种语言的 SDK。 若要使用特定语言版本,可能需要使用语言选择任务来设置环境。
例如,若要选择 Node.JS 16.x:
azure-pipelines.yml
steps:
- task: UseNode@1
inputs:
version: '16.x'
语言映射
Travis 中的关键字 language
意味着应使用语言工具的该版本以及应隐式执行许多生成步骤。 在 Azure Pipelines 中,需要指定要运行的命令。
下面是从 language
关键字到针对最常用的语言自动执行的命令的转换指南:
语言 | 命令 |
---|---|
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 或 go 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 或 npm ci 或 yarn npm test |
objective-c swift |
pod install 或 bundle 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 |
此外,可以启用不太常见的语言,但需要另一个依赖项安装步骤或 docker 容器内的执行:
语言 | 命令 |
---|---|
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 |
多种语言选择
还可以配置一个可支持以多种语言生成不同应用程序的环境。 例如,若要确保生成环境同时面向 Node.JS 16.x 和 Ruby 3.2 或更高版本:
azure-pipelines.yml
steps:
- task: UseNode@1
inputs:
version: '8.x'
- task: UseRubyVersion@0
inputs:
versionSpec: '>= 3.2'
阶段
在 Travis 中,步骤在一组固定的命名时期(如 before_install
或 before_script
)中定义。 Azure Pipelines 没有已命名的时期,并且步骤可以通过任何对管道有意义的方式进行分组、命名和组织。
例如:
.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
或者,可将步骤组合在一起,并进行命名(可选):
azure-pipelines.yml
steps:
- script: |
npm install -g bower
npm install
bower install
displayName: 'Install dependencies'
- script: npm run build
- script: npm test
并行作业
Travis 通过让你定义一个阶段(一组并行执行的作业)来提供并行。 Travis 生成可以有多个阶段;一个阶段中的所有作业都完成后,下一阶段将开始。
使用 Azure Pipelines,可以使每个步骤或阶段依赖于任何其他步骤。 通过这种方式,可以指定哪些步骤以串行方式运行,哪些步骤可以并行运行。 因此,可以在完成一个步骤后通过并行运行多个步骤进行扇出,然后使用随后运行的单个步骤重新扇入。 此模型提供用于在必要时定义复杂工作流的选项。 现在,下面是一个简单的示例:
例如,若要运行生成脚本,然后在其完成后并行运行单元测试和集成测试,并在所有测试完成后将工件打包,然后运行部署到预生产:
.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
高级并行执行
在 Azure Pipelines 中,对于管道的编排方式,你有更多的选项和控制。
例如,一个团队有一组快速运行的单元测试,以及另一组速度较慢的集成测试。 该团队希望在单元完成后立即开始为发布创建 .ZIP 文件,因为他们对该生成提供了良好的包很有信心。 但在部署到预生产之前,他们希望等到所有测试都通过:
在 Azure Pipelines 中,他们可以这样做:
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
步骤重用
在 Travis 中,可以使用矩阵通过单个配置运行多个执行。 在 Azure Pipelines 中,可以采用相同的方式使用矩阵,但也可以使用模板实现配置重用。
示例:矩阵中的环境变量
运行多个稍有变化的生成的最常见方法之一是使用环境变量更改执行。 例如,生成脚本可以查看是否存在环境变量,并更改软件的生成方式或测试方式。
可以使用矩阵多次运行某个生成配置,为环境变量中的每个值都运行一次。 例如,若要运行给定脚本三次,每次使用一个环境变量的不同设置:
.travis.yml
os: osx
env:
matrix:
- 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)
示例:矩阵中的语言版本
另一种常见方案是针对多个不同语言环境运行。 Travis 支持使用 language
关键字进行隐式定义,而 Azure Pipelines 需要显式任务来定义如何配置该语言版本。
可以使用 Azure Pipelines 中的环境变量矩阵选项为不同语言版本启用矩阵。 例如,可以在对应于要使用的语言版本的每个矩阵变量中设置环境变量,然后在第一步中使用该环境变量运行语言配置任务:
.travis.yml
os: linux
matrix:
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
示例:矩阵中的操作系统
在多个操作系统中运行生成也很常见。 Travis 支持使用 os
关键字进行此定义,而 Azure Pipelines 允许你通过使用 vmImage
关键字选择要在其中运行的池来配置操作系统。
例如,可以在对应于要使用的操作系统映像的每个矩阵变量中设置环境变量。 然后,可以将计算机池设置为已设置的变量:
.travis.yml
matrix:
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!
成功和失败处理
Travis 允许你使用 after_success
时期指定在生成成功时运行的步骤或使用 after_failure
时期指定在生成失败时运行的步骤。 借助 Azure Pipelines,可以基于任何步骤的结果定义成功和失败条件,从而实现更灵活、更强大的管道。
.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()
高级的成功和失败处理
在 Azure Pipelines 中,可以针对作业之间的流控制为一组灵活的依赖项和条件进行编程。
可以将作业配置为基于以前作业的成功或失败或基于环境变量运行。
甚至可以将作业配置为始终运行,而不考虑其他作业是否成功。
例如,如果要在生成失败(但仅当它是在主分支上作为生成运行的情况下)时运行脚本:
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
预定义变量
Travis 和 Azure Pipelines 都设置了多个环境变量,使你能够检查 CI 系统的执行环境并与之交互。
在大多数情况下,都有与 Travis 中的环境变量匹配的 Azure Pipelines 变量。 下面是 Travis 中常用的环境变量及其在 Azure Pipelines 中的类似项的列表:
Travis | Azure Pipelines | 说明 |
---|---|---|
CI=true 或 TRAVIS=true |
TF_BUILD=True |
表明你的生成正在 CI 系统中运行;对于也要在开发期间在本地运行的脚本很有用。 |
TRAVIS_BRANCH |
CI 生成:BUILD_SOURCEBRANCH 拉取请求生成: SYSTEM_PULLREQUEST_TARGETBRANCH |
该生成排队的分支的名称,或拉取请求的目标分支的名称。 |
TRAVIS_BUILD_DIR |
BUILD_SOURCESDIRECTORY |
签出源的位置和默认工作目录。 |
TRAVIS_BUILD_NUMBER |
BUILD_BUILDID |
当前生成调用的唯一数字标识符。 |
TRAVIS_COMMIT |
CI 生成:BUILD_SOURCEVERSION |
当前正在生成的提交 ID。 |
TRAVIS_COMMIT |
拉取请求生成:git rev-parse HEAD^2 |
对于拉取请求验证生成,Azure Pipelines 将 BUILD_SOURCEVERSION 设置为将拉取请求合并到主分支的结果合并提交;此命令标识了拉取请求提交本身。 |
TRAVIS_COMMIT_MESSAGE |
BUILD_SOURCEVERSIONMESSAGE |
要生成的提交的日志消息。 |
TRAVIS_EVENT_TYPE |
BUILD_REASON |
该生成排队的原因;值的映射位于下面的“生成原因”表中。 |
TRAVIS_JOB_NAME |
AGENT_JOBNAME |
当前作业的名称(如果指定)。 |
TRAVIS_OS_NAME |
AGENT_OS |
运行作业的操作系统;值的映射位于下面的“操作系统”表中。 |
TRAVIS_PULL_REQUEST |
Azure Repos:SYSTEM_PULLREQUEST_PULLREQUESTID GitHub: SYSTEM_PULLREQUEST_PULLREQUESTNUMBER |
触发此生成的拉取请求编号。 (对于 GitHub 生成,这是一个并非拉取请求编号的唯一标识符。) |
TRAVIS_PULL_REQUEST_BRANCH |
SYSTEM_PULLREQUEST_SOURCEBRANCH |
拉取请求来源的分支的名称。 |
TRAVIS_PULL_REQUEST_SHA |
拉取请求生成:git rev-parse HEAD^2 |
对于拉取请求验证生成,Azure Pipelines 将 BUILD_SOURCEVERSION 设置为将拉取请求合并到主分支的结果合并提交;此命令标识了拉取请求提交本身。 |
TRAVIS_PULL_REQUEST_SLUG |
分支存储库的名称(如果拉取请求源自分支)。 这在 Azure Pipelines 中没有类似项。 | |
TRAVIS_REPO_SLUG |
BUILD_REPOSITORY_NAME |
为其配置此生成的存储库的名称。 |
TRAVIS_TEST_RESULT |
AGENT_JOBSTATUS |
如果前面的所有步骤都成功(返回了 0 ),Travis 会将此值设置为 0 。 对于 Azure Pipelines,请检查是否满足 AGENT_JOBSTATUS=Succeeded 。 |
TRAVIS_TAG |
BUILD_SOURCEBRANCH |
如果此生成因创建标记而排队,则这是该标记的名称。 对于 Azure Pipelines,BUILD_SOURCEBRANCH 设置为完整的 Git 引用名称,例如 refs/tags/tag_name 。 |
TRAVIS_BUILD_STAGE_NAME |
Travis 中阶段的名称。 如前所述,Azure Pipelines 使用作业处理流控制。 可以引用 AGENT_JOBNAME 。 |
生成原因:
TRAVIS_EVENT_TYPE
变量包含映射到 Azure Pipelines BUILD_REASON
变量提供的值的值:
Travis | Azure Pipelines | 说明 |
---|---|---|
push |
IndividualCI |
该生成是来自推送的持续集成生成。 |
pull_request |
PullRequest |
该生成已排队以验证拉取请求。 |
api |
Manual |
REST API 或网页上的手动请求已将该生成排队。 |
cron |
Schedule |
已计划该生成。 |
操作系统:
TRAVIS_OS_NAME
变量包含映射到 Azure Pipelines AGENT_OS
变量提供的值的值:
Travis | Azure Pipelines | 说明 |
---|---|---|
linux |
Linux |
该生成在 Linux 上运行。 |
osx |
Darwin |
该生成在 macOS 上运行。 |
windows |
Windows_NT |
该生成在 Windows 上运行。 |
有关详细信息,请参阅 预定义环境变量。
如果没有你所需数据的变量,则可以使用 shell 命令获取它。 例如,对于包含所生成拉取请求提交 ID 的环境变量,一个好的替代方法是运行 git 命令:git rev-parse HEAD^2
。
生成特定分支
默认情况下,Travis 和 Azure Pipelines 均在所有分支上执行 CI 生成。 同样,这两个系统都允许将这些生成限制到特定的分支。 在 Azure Pipelines 中,要生成的分支列表应列在 include
列表中,而不要生成的分支应列在 `exclude 列表中。 支持通配符。
例如,若要仅生成主分支以及以单词“releases”开头的分支:
.travis.yml
branches:
only:
- main
- /^releases.*/
azure-pipelines.yml
trigger:
branches:
include:
- main
- releases*
输出缓存
Travis 支持缓存依赖项和中间生成输出,以缩短生成时间。 Azure Pipelines 不支持缓存中间生成输出,但提供与 Azure Artifacts 的集成以便存储依赖项。
Git 子模块
默认情况下,Travis 和 Azure Pipelines 都以“递归方式”克隆 git 存储库。 这意味着子模块由代理克隆,它很有用,因为子模块通常包含依赖项。 但是,额外的克隆需要时间,因此,如果不需要依赖项,则可以禁用克隆子模块:
.travis.yml
git:
submodules: false
azure-pipelines.yml
checkout:
submodules: false