基本步骤的 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'

  1. 多阶段的 "best" 策略是什么? 我看到 Azure DevOps 管道有 Stage > Jobs > Task 的概念,但它们看起来都与我相似。所以我决定把这个过程分成几个阶段,比如 Build - AutomatedTests - NuGet Package - Publish 如您所见,这是一个顺序过程,每个阶段都需要前一个阶段的某些东西。自动化测试需要构建代码(dll),nuGet 包也需要访问构建代码,发布需要访问生成的 nupkg 等。我不知道遵循这个策略是否可以,或者最好有具有多个作业的单个阶段,甚至具有多个任务的单个作业。正如我所说,我不完全理解拥有这么多概念的好处以及它们如何满足我的需求。
  2. Azure 多级管道是否应该作为单独的概念取代旧的构建和发布?对我来说,通过多阶段方法将 CI/CD 放在一个地方并可编写脚本以使其在源代码控制存储库中进行版本控制对我来说很有意义。但我仍然将发布概念视为目前在 Azure DevOps 上的一个独立概念。所以我可能应该使用 azure pipelines yml 直到包 "step",然后使用 Release go 获取这个 nupkg 并将其发布到一些提要上。不确定有什么好处。
  3. 我在将一个阶段的输出作为下一个阶段的输入时遇到问题,可能是因为我没有完全理解它。在上面的 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'
  1. 您的整个构建定义应该是一个单一的 "stage"。那些 Build - AutomatedTests - NuGet Package - Publish 不是阶段,它们是构建的逻辑部分。
  2. 可能在未来某个时候will\might发生
  3. 那是因为您在不该使用的阶段使用了阶段。每个阶段 运行s 在不同的代理上。你应该有一个单一的阶段,所有的任务都应该 运行 在那个阶段。