基本步骤的 Azure Pipelines 多阶段问题
Azure Pipelines multi stage problems for basic steps
我来自 GitLab 及其 .gitlab-ci.yml,我正在试验 Azure DevOps 多阶段管道,但我对它的工作原理和最佳策略感到非常困惑,即使在阅读了几篇文档文章后也是如此https://docs.microsoft.com/en-us/azure/devops/pipelines/?view=azure-devops
请允许我针对我正在尝试的基本场景提出几个相关问题,即编译,运行单元测试,为整个解决方案打包一个nuget包(它可以包含多个 projects/nuGet 包)并将包发布到 nuGet feed(如果分支是主分支,则为发布版本,否则为预发布版本) .
这是我从中获取代码的存储库:https://github.com/sasw-diego/sasw-test-support
它只会生成一个 nuGet 包,但我有其他多项目解决方案应该生成许多 nuGet 包
到目前为止,这是我的azure-pipelines.yml
:
trigger:
- master
- feature/*
pool:
vmImage: ubuntu-latest
variables:
NUGET_FOLDER_NAME: nupkgs
NUGET_REPOSITORY: https://whatever
PRERELEASE_SUFFIX: $(Build.BuildId)
PIPELINE_ARTIFACT_NAME: $(Build.BuildNumber)
stages:
- stage:
displayName: 'Build'
jobs:
- job: 'Build'
steps:
- task: NuGetAuthenticate@0
displayName: 'Authenticate in NuGet feed'
- script: dotnet restore --no-cache --force
displayName: 'Restore dependencies'
- script: dotnet build --configuration Release --no-restore
displayName: 'Build for Release'
- script: ls $(System.DefaultWorkingDirectory)
displayName: 'List content'
- publish: $(System.DefaultWorkingDirectory)
artifact: $(PIPELINE_ARTIFACT_NAME)
- stage:
displayName: 'Automated Tests'
condition: succeeded()
jobs:
- job:
displayName: 'Unit Tests'
steps:
- download: current
artifact: $(PIPELINE_ARTIFACT_NAME)
- script: ls -a
displayName: 'View'
- script: ls ./test
displayName: 'View test'
- script: ls ./test/Sasw.TestSupport.UnitTests
displayName: 'View folder'
- script: dotnet vstest test/*UnitTests/bin/Release/**/*UnitTests.dll
displayName: 'Run unit tests'
- stage:
displayName: 'NuGet Package'
condition: succeeded()
jobs:
- job:
displayName: 'Pack Preview Version'
condition: ne(variables['Build.SourceBranch'], 'refs/heads/master')
steps:
- script: dotnet pack *.sln --configuration Release --output $(NUGET_FOLDER_NAME)
displayName: 'Pack'
- job:
displayName: 'Pack Stable Version'
condition: eq(variables['Build.SourceBranch'], 'refs/heads/master')
steps:
- script: dotnet pack *.sln --configuration Release --output $(NUGET_FOLDER_NAME) --version-suffix $(PRERELEASE_SUFFIX) --include-source --include-symbols -p:SymbolPackageFormat=snupkg
displayName: 'Pack'
- 多阶段的 "best" 策略是什么? 我看到 Azure DevOps 管道有 Stage > Jobs > Task 的概念,但它们看起来都与我相似。所以我决定把这个过程分成几个阶段,比如
Build - AutomatedTests - NuGet Package - Publish
如您所见,这是一个顺序过程,每个阶段都需要前一个阶段的某些东西。自动化测试需要构建代码(dll),nuGet 包也需要访问构建代码,发布需要访问生成的 nupkg 等。我不知道遵循这个策略是否可以,或者最好有具有多个作业的单个阶段,甚至具有多个任务的单个作业。正如我所说,我不完全理解拥有这么多概念的好处以及它们如何满足我的需求。
- Azure 多级管道是否应该作为单独的概念取代旧的构建和发布?对我来说,通过多阶段方法将 CI/CD 放在一个地方并可编写脚本以使其在源代码控制存储库中进行版本控制对我来说很有意义。但我仍然将发布概念视为目前在 Azure DevOps 上的一个独立概念。所以我可能应该使用 azure pipelines yml 直到包 "step",然后使用 Release go 获取这个 nupkg 并将其发布到一些提要上。不确定有什么好处。
- 我在将一个阶段的输出作为下一个阶段的输入时遇到问题,可能是因为我没有完全理解它。在上面的 yml 中,构建阶段成功,但自动测试阶段在其 运行 单元测试 作业上失败并出现错误
No test source files were specified
.我证实会发生这种情况,因为根本没有生成文件夹 bin
。这似乎很奇怪,因为我正在复制前一阶段的所有内容(以及前一阶段使用 dll 生成的 bin 文件夹),但是下一阶段,尽管能够下载所有内容,但它找不到测试。
这是失败阶段的日志:https://gist.github.com/sasw-diego/df66eccf71bbfc044a4d72be96268c9a
如果有人能发现我遗漏的内容以便能够理解此过程,那将非常有帮助。任何 link 澄清所有这些概念将不胜感激。塔
PS:这是一个类似的通用 CI/CD 我在 GitLab 中将 1 个或多个 nuGet 上传到提要:
https://gist.github.com/sasw-diego/bf46258cb1ad0aa5241e8d1866b53f48
更新:
谢谢你的回答。我使用 多阶段管道 成功创建了一个 CI/CD yml,它恢复、构建、执行测试,运行 一个容器(例如:一个 eventStore 主机)到 运行 对其进行集成测试,并在工件中发布 nuGet。所以任务完成了!我把它分成不同的阶段和工作来探讨一些要点
trigger:
- master
- feature/*
pool:
vmImage: ubuntu-18.04
variables:
- group: sasw-common-variables
- name: NUGET_FOLDER_NAME
value: nupkgs
- name: PIPELINE_ARTIFACT_NAME
value: $(Build.BuildNumber)
- name: PATH_PIPELINE_ARTIFACT_NAME
value: $(Pipeline.Workspace)/$(PIPELINE_ARTIFACT_NAME)
- name: NUGET_API_KEY
value: $(nuget-api-key)
- name: NUGET_FEED
value: $(nuget-feed)
- name: PRERELEASE_SUFFIX
value: $(nuget-prerelease-suffix)
resources:
containers:
- container: eventstore
image: eventstore/eventstore:release-5.0.2
ports:
- 1113:1113
env:
EVENTSTORE_INT_TCP_PORT: 1113
EVENTSTORE_EXT_TCP_PORT: 1113
EVENTSTORE_INT_HTTP_PORT: 2113
EVENTSTORE_EXT_HTTP_PORT: 2113
EVENTSTORE_EXT_HTTP_PREFIXES: http://*:2113/
stages:
- stage:
displayName: 'Build'
jobs:
- job: 'Build'
displayName: 'Build & Create nuGet Package'
services:
eventstore: eventstore
steps:
- task: NuGetAuthenticate@0
displayName: 'Authenticate in NuGet feed'
- script: dotnet restore --no-cache --force
displayName: 'Restore dependencies'
- script: dotnet build --configuration Release --no-restore
displayName: 'Build with Release Configuration'
- script: dotnet vstest test/*UnitTests/bin/Release/**/*UnitTests.dll
displayName: 'Run unit tests'
- script: dotnet vstest test/*IntegrationTests/bin/Release/**/*IntegrationTests.dll
displayName: 'Run integration tests'
- script: dotnet pack *.sln --configuration Release --output $(NUGET_FOLDER_NAME)
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
displayName: 'Create release nuGet'
- script: dotnet pack *.sln --configuration Release --output $(NUGET_FOLDER_NAME) --version-suffix $(PRERELEASE_SUFFIX) --include-source --include-symbols -p:SymbolPackageFormat=snupkg
condition: and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/master'))
displayName: 'Create pre-release nuGet'
- publish: $(System.DefaultWorkingDirectory)/$(NUGET_FOLDER_NAME)
artifact: $(PIPELINE_ARTIFACT_NAME)
displayName: 'Publish pipeline artifact'
- stage:
displayName: 'Release'
condition: succeeded()
jobs:
- job: 'Publish'
displayName: 'Publish nuGet Package'
steps:
- download: current
artifact: $(PIPELINE_ARTIFACT_NAME)
displayName: 'Download pipeline artifact'
- script: ls $(PATH_PIPELINE_ARTIFACT_NAME)
displayName: 'Display contents of downloaded articacts path'
- task: NuGetAuthenticate@0
displayName: 'Authenticate in NuGet feed'
- task: UseDotNet@2
displayName: 'Use latest .NET Core sdk 3.x'
inputs:
packageType: sdk
version: 3.x
includePreviewVersions: true
installationPath: $(Agent.ToolsDirectory)/dotnet
- script: dotnet nuget push $(PATH_PIPELINE_ARTIFACT_NAME)/**/*.nupkg --source $(NUGET_FEED) --api-key $(NUGET_API_KEY) --skip-duplicate
displayName: 'Uploads nuGet packages'
- 您的整个构建定义应该是一个单一的 "stage"。那些
Build - AutomatedTests - NuGet Package - Publish
不是阶段,它们是构建的逻辑部分。
- 可能在未来某个时候will\might发生
- 那是因为您在不该使用的阶段使用了阶段。每个阶段 运行s 在不同的代理上。你应该有一个单一的阶段,所有的任务都应该 运行 在那个阶段。
我来自 GitLab 及其 .gitlab-ci.yml,我正在试验 Azure DevOps 多阶段管道,但我对它的工作原理和最佳策略感到非常困惑,即使在阅读了几篇文档文章后也是如此https://docs.microsoft.com/en-us/azure/devops/pipelines/?view=azure-devops
请允许我针对我正在尝试的基本场景提出几个相关问题,即编译,运行单元测试,为整个解决方案打包一个nuget包(它可以包含多个 projects/nuGet 包)并将包发布到 nuGet feed(如果分支是主分支,则为发布版本,否则为预发布版本) . 这是我从中获取代码的存储库:https://github.com/sasw-diego/sasw-test-support 它只会生成一个 nuGet 包,但我有其他多项目解决方案应该生成许多 nuGet 包
到目前为止,这是我的azure-pipelines.yml
:
trigger:
- master
- feature/*
pool:
vmImage: ubuntu-latest
variables:
NUGET_FOLDER_NAME: nupkgs
NUGET_REPOSITORY: https://whatever
PRERELEASE_SUFFIX: $(Build.BuildId)
PIPELINE_ARTIFACT_NAME: $(Build.BuildNumber)
stages:
- stage:
displayName: 'Build'
jobs:
- job: 'Build'
steps:
- task: NuGetAuthenticate@0
displayName: 'Authenticate in NuGet feed'
- script: dotnet restore --no-cache --force
displayName: 'Restore dependencies'
- script: dotnet build --configuration Release --no-restore
displayName: 'Build for Release'
- script: ls $(System.DefaultWorkingDirectory)
displayName: 'List content'
- publish: $(System.DefaultWorkingDirectory)
artifact: $(PIPELINE_ARTIFACT_NAME)
- stage:
displayName: 'Automated Tests'
condition: succeeded()
jobs:
- job:
displayName: 'Unit Tests'
steps:
- download: current
artifact: $(PIPELINE_ARTIFACT_NAME)
- script: ls -a
displayName: 'View'
- script: ls ./test
displayName: 'View test'
- script: ls ./test/Sasw.TestSupport.UnitTests
displayName: 'View folder'
- script: dotnet vstest test/*UnitTests/bin/Release/**/*UnitTests.dll
displayName: 'Run unit tests'
- stage:
displayName: 'NuGet Package'
condition: succeeded()
jobs:
- job:
displayName: 'Pack Preview Version'
condition: ne(variables['Build.SourceBranch'], 'refs/heads/master')
steps:
- script: dotnet pack *.sln --configuration Release --output $(NUGET_FOLDER_NAME)
displayName: 'Pack'
- job:
displayName: 'Pack Stable Version'
condition: eq(variables['Build.SourceBranch'], 'refs/heads/master')
steps:
- script: dotnet pack *.sln --configuration Release --output $(NUGET_FOLDER_NAME) --version-suffix $(PRERELEASE_SUFFIX) --include-source --include-symbols -p:SymbolPackageFormat=snupkg
displayName: 'Pack'
- 多阶段的 "best" 策略是什么? 我看到 Azure DevOps 管道有 Stage > Jobs > Task 的概念,但它们看起来都与我相似。所以我决定把这个过程分成几个阶段,比如
Build - AutomatedTests - NuGet Package - Publish
如您所见,这是一个顺序过程,每个阶段都需要前一个阶段的某些东西。自动化测试需要构建代码(dll),nuGet 包也需要访问构建代码,发布需要访问生成的 nupkg 等。我不知道遵循这个策略是否可以,或者最好有具有多个作业的单个阶段,甚至具有多个任务的单个作业。正如我所说,我不完全理解拥有这么多概念的好处以及它们如何满足我的需求。 - Azure 多级管道是否应该作为单独的概念取代旧的构建和发布?对我来说,通过多阶段方法将 CI/CD 放在一个地方并可编写脚本以使其在源代码控制存储库中进行版本控制对我来说很有意义。但我仍然将发布概念视为目前在 Azure DevOps 上的一个独立概念。所以我可能应该使用 azure pipelines yml 直到包 "step",然后使用 Release go 获取这个 nupkg 并将其发布到一些提要上。不确定有什么好处。
- 我在将一个阶段的输出作为下一个阶段的输入时遇到问题,可能是因为我没有完全理解它。在上面的 yml 中,构建阶段成功,但自动测试阶段在其 运行 单元测试 作业上失败并出现错误
No test source files were specified
.我证实会发生这种情况,因为根本没有生成文件夹bin
。这似乎很奇怪,因为我正在复制前一阶段的所有内容(以及前一阶段使用 dll 生成的 bin 文件夹),但是下一阶段,尽管能够下载所有内容,但它找不到测试。
这是失败阶段的日志:https://gist.github.com/sasw-diego/df66eccf71bbfc044a4d72be96268c9a
如果有人能发现我遗漏的内容以便能够理解此过程,那将非常有帮助。任何 link 澄清所有这些概念将不胜感激。塔
PS:这是一个类似的通用 CI/CD 我在 GitLab 中将 1 个或多个 nuGet 上传到提要: https://gist.github.com/sasw-diego/bf46258cb1ad0aa5241e8d1866b53f48
更新: 谢谢你的回答。我使用 多阶段管道 成功创建了一个 CI/CD yml,它恢复、构建、执行测试,运行 一个容器(例如:一个 eventStore 主机)到 运行 对其进行集成测试,并在工件中发布 nuGet。所以任务完成了!我把它分成不同的阶段和工作来探讨一些要点
trigger:
- master
- feature/*
pool:
vmImage: ubuntu-18.04
variables:
- group: sasw-common-variables
- name: NUGET_FOLDER_NAME
value: nupkgs
- name: PIPELINE_ARTIFACT_NAME
value: $(Build.BuildNumber)
- name: PATH_PIPELINE_ARTIFACT_NAME
value: $(Pipeline.Workspace)/$(PIPELINE_ARTIFACT_NAME)
- name: NUGET_API_KEY
value: $(nuget-api-key)
- name: NUGET_FEED
value: $(nuget-feed)
- name: PRERELEASE_SUFFIX
value: $(nuget-prerelease-suffix)
resources:
containers:
- container: eventstore
image: eventstore/eventstore:release-5.0.2
ports:
- 1113:1113
env:
EVENTSTORE_INT_TCP_PORT: 1113
EVENTSTORE_EXT_TCP_PORT: 1113
EVENTSTORE_INT_HTTP_PORT: 2113
EVENTSTORE_EXT_HTTP_PORT: 2113
EVENTSTORE_EXT_HTTP_PREFIXES: http://*:2113/
stages:
- stage:
displayName: 'Build'
jobs:
- job: 'Build'
displayName: 'Build & Create nuGet Package'
services:
eventstore: eventstore
steps:
- task: NuGetAuthenticate@0
displayName: 'Authenticate in NuGet feed'
- script: dotnet restore --no-cache --force
displayName: 'Restore dependencies'
- script: dotnet build --configuration Release --no-restore
displayName: 'Build with Release Configuration'
- script: dotnet vstest test/*UnitTests/bin/Release/**/*UnitTests.dll
displayName: 'Run unit tests'
- script: dotnet vstest test/*IntegrationTests/bin/Release/**/*IntegrationTests.dll
displayName: 'Run integration tests'
- script: dotnet pack *.sln --configuration Release --output $(NUGET_FOLDER_NAME)
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
displayName: 'Create release nuGet'
- script: dotnet pack *.sln --configuration Release --output $(NUGET_FOLDER_NAME) --version-suffix $(PRERELEASE_SUFFIX) --include-source --include-symbols -p:SymbolPackageFormat=snupkg
condition: and(succeeded(), ne(variables['Build.SourceBranch'], 'refs/heads/master'))
displayName: 'Create pre-release nuGet'
- publish: $(System.DefaultWorkingDirectory)/$(NUGET_FOLDER_NAME)
artifact: $(PIPELINE_ARTIFACT_NAME)
displayName: 'Publish pipeline artifact'
- stage:
displayName: 'Release'
condition: succeeded()
jobs:
- job: 'Publish'
displayName: 'Publish nuGet Package'
steps:
- download: current
artifact: $(PIPELINE_ARTIFACT_NAME)
displayName: 'Download pipeline artifact'
- script: ls $(PATH_PIPELINE_ARTIFACT_NAME)
displayName: 'Display contents of downloaded articacts path'
- task: NuGetAuthenticate@0
displayName: 'Authenticate in NuGet feed'
- task: UseDotNet@2
displayName: 'Use latest .NET Core sdk 3.x'
inputs:
packageType: sdk
version: 3.x
includePreviewVersions: true
installationPath: $(Agent.ToolsDirectory)/dotnet
- script: dotnet nuget push $(PATH_PIPELINE_ARTIFACT_NAME)/**/*.nupkg --source $(NUGET_FEED) --api-key $(NUGET_API_KEY) --skip-duplicate
displayName: 'Uploads nuGet packages'
- 您的整个构建定义应该是一个单一的 "stage"。那些
Build - AutomatedTests - NuGet Package - Publish
不是阶段,它们是构建的逻辑部分。 - 可能在未来某个时候will\might发生
- 那是因为您在不该使用的阶段使用了阶段。每个阶段 运行s 在不同的代理上。你应该有一个单一的阶段,所有的任务都应该 运行 在那个阶段。