Azure YAML 构建和发布管道

3

我正在使用Azure YAML管道在Azure应用服务上部署Web应用程序。

我的做法是创建了两个YAML管道,一个是构建管道,另一个是发布管道,并为不同的环境设置了多阶段,例如:开发、测试和生产环境。

我将其分成两个管道的原因是我的构建管道生成构建工件,通过在发布管道上使用“资源”部分,可以从UI中选择以前生成的构建并将其部署到任何我想要的阶段。想法是当我需要部署到其中一个阶段时,我不想每次都重新构建,而是应该能够使用以前生成的工件以及旧的构建工件版本。下面是我的发布管道以及我如何使用“资源”部分。

发布管道

trigger:
- none

resources:
  pipelines:
  - pipeline: myappbuild  
    source: build-test # name of the pipeline that produces an artifact
    trigger: 
      branches:
      - master

pool:
  vmImage: 'windows-latest'

stages: 
- stage: 'DeployToDev'
  jobs:
  - deployment: Deploy 
    displayName: Deploy
    environment: dev 
    pool: 
      vmImage: 'windows-latest'
    strategy: 
      runOnce: 
        deploy:
          steps:          
          - download: myappbuild
            artifact: drop  
          - task: AzureRmWebAppDeployment@4
            displayName: 'Deploy Azure App Service'
            inputs:
              packageForLinux: '$(System.DefaultWorkingDirectory)/**/*.zip'
              AppSettings: '-ASPNETCORE_ENVIRONMENT $(EnvironmentName) -ReleaseName $(Release.ReleaseName) -BuildId $(Build.BuildId)'

这个程序能正常运行。我可以从用户界面选择以前的构建版本,并将其部署到我的发布管道中任何阶段。

问题:

  1. 在发布管道中,很难知道当前每个阶段部署了什么内容。我想基于已运行的内容来确定每个环境中有哪些内容。在我的情况下,我有3个环境,我希望能够告诉哪次运行是为哪个环境的。因为经典的 UI 管道具有“发布”的概念,在一个屏幕上显示当前部署在哪个地方的构件。而在 YAML 中,您只能在“运行”部分下看到每个环境的三个绿点,无法告诉 Dev 环境上当前部署的内容。

  2. 我是否可以在一个管道中实现这一点,而不必创建两个管道?我能否只使用一个管道来进行构建和发布?我知道可以使用多阶段来实现,其中一个阶段用于构建,其他阶段用于发布。但是我不确定在这种情况下是否可以使用资源部分。我的想法是,我不想总是运行 build。如果这是可行的,请指导我正确的文档。

谢谢。

2个回答

1
我会将构建和部署阶段合并在一起,类似于这样:
stages:
- stage: Build
  jobs:
  - job: Build
    steps:
    - task: YourBuildTask1
      inputs:
        YourInputsHere: ...
    - task: Etc
      inputs:
        Etc: ...
    - task: PublishBuildArtifacts@1
      inputs:
        PathtoPublish: ...
        ArtifactName: 'drop'
        publishLocation: 'Container'
- stage: DEV
  dependsOn: Build
  jobs:
    - deployment: Deployment
      variables:
        - template: myDevVariables.template.yml
      environment: DEV
      strategy:
        runOnce:
          deploy:
            steps:     
            - task: AzureRmWebAppDeployment@4
              displayName: 'Deploy Azure App Service'
              inputs:
                packageForLinux: '$(Pipeline.Workspace)/**/*.zip'
                AppSettings: '-ASPNETCORE_ENVIRONMENT $(EnvironmentName) -ReleaseName $(Release.ReleaseName) -BuildId $(Build.BuildId)'
- stage: Test
  dependsOn: DEV
  jobs:
    - deployment: Deployment
      variables:
        - template: myTestVariables.template.yml
      environment: Test
      strategy:
        runOnce:
          deploy:
            steps:     
            - task: AzureRmWebAppDeployment@4
              displayName: 'Deploy Azure App Service'
              inputs:
                packageForLinux: '$(Pipeline.Workspace)/**/*.zip'
                AppSettings: '-ASPNETCORE_ENVIRONMENT $(EnvironmentName) -ReleaseName $(Release.ReleaseName) -BuildId $(Build.BuildId)'

显然没有调试过,但我在自己的管道中成功地进行了类似的操作。您将第一个部署阶段依赖于构建,每个后续环境都依赖于前一个环境。您为每个环境添加批准门,以添加手动干预并防止构建一次性在所有位置部署。
请注意,在此示例中,我已将$(System.DefaultWorkingDirectory)替换为$(Pipeline.Workspace),因为我发现在YAML管道中,$(System.DefaultWorkingDirectory)对于不同的作业类型具有不同的值。
在下面的示例中,如果我不喜欢20200105.1部署的结果,我可以单击其下方的20201218.1运行,并选择要部署到的新环境。

Example Run List


谢谢您的快速回复。但是,这是否允许我选择在3天前生成的构件(不是最新的构件)?想法是选择旧的构建版本,并将该版本应用于部署阶段(使用您提供的用例)。@WaitingForGuacamole 谢谢 :) - Auto geek
实际上,当您运行管道时,它会在管道下创建一个“运行”,您可以查看已将该构建推广到的所有环境。如果您想部署旧版本构建,则只需转到对应于要部署的构建的“运行”,并选择要重新部署的环境即可。我已经在上面包含了一个示例。 - WaitingForGuacamole
不幸的是,我找不到一种方式来选择旧版本并将其部署到环境阶段。即使可能,我也必须再次运行该构建,但由于我的构建阶段需要很长时间执行,因此我不想这样做。相反,我可以选择旧版本(已部署)并将其部署到环境阶段,而无需再次运行构建阶段。这就是为什么我将管道分成两部分的原因,它允许我选择旧版本并在不再次运行构建的情况下将该版本部署到阶段,这样我可以节省部署时间。@WaitingForGuacamole - Auto geek
1
OK. 你运行构建阶段,将其部署到DEV环境中,不错。你有一个运行列表,其中包含构建/部署条目,展示了发生的事情。然后,你继续进行其他一些构建。这些构建也在运行列表中创建条目,同样很不错。两周后,你决定想要将旧的构建产品部署到集成或生产环境中。点击那个旧构建的运行列表条目,你应该可以选择将其部署到这些环境中(前提是你有基于批准门禁的权限)。这假设你在构建中使用了“发布构建制品”步骤(请参见上一条评论)。 - WaitingForGuacamole
管道并不真正关心“运行”。它处理工作,并处于工作流状态。根据该状态和其他规则,您可以执行许多不同的操作(例如在部署新版本后重新部署旧版本)。 - WaitingForGuacamole
显示剩余3条评论

0

我会将它们组合起来,因为这样才能真正发挥其价值。将它们分开只会增加更多的开销和维护成本。如果担心CI/CD问题,可以通过使用一个条件包装部署阶段来检查分支的方式,使用-${{ if eq(variables['Build.SourceBranch'], 'refs/heads/master')}} :

关于环境可见性的问题,请单击Azure DevOps中的“环境”按钮,它将显示所有已经访问该环境的作业,跨项目仓库。

最佳实践是针对每个提交到主分支的创建CD。这将为所有环境创建一个发布并部署到DEV。从而保留每个构建的发布。


将所有内容放在一个管道中的问题在于,每次想要将构建部署到发布阶段时都必须运行构建,而我不想这样做。因为我的构建需要很长时间,所以想法是可以使用先前生成的任何构建(最新或旧构建),并将其部署到阶段而无需运行它,这将减少部署时间。在一个管道中使用CICD,我无法跳过构建阶段的运行。@DreadedFrost - Auto geek
只要您的构建阶段有一个发布构件的步骤,任何运行都应该允许您执行您想要的操作(在不重新构建的情况下部署先前构建的内容)。 - WaitingForGuacamole
@WaitingForGuacamole 你好,我对YAML管道也有点新奇,但感觉把Build和Release定义都放在一个地方似乎违反了单一职责原则。这对我来说听起来有点冒险,例如,在极端情况下,如果创建了错误的YAML定义,那么坏代码可能会在稍后发布到某些环境中。如果我理解错了,请纠正我。另一件事是,在完美的世界里,能够在本地主机上运行/测试Build YAML管道,然后再创建PR会很酷(目前不支持)。 - GoldenAge
无论如何,为什么将所有内容放在一个管道中比拥有单独的构建管道和发布管道更好?我对此非常困惑... - GoldenAge
一切都在一个管道中,从DevOps的角度来看,简化了流程。不再有单独的位置和单独的维护用于构建+发布。这也与经典的构建/发布进行比较,并将此过程转换为代码以允许SCM。关于YAML将损坏的代码部署到环境的问题。理想情况下,部署将为每个环境使用相同的工件(减去配置)。此外,通过使用模板进一步缓解了这种情况,其中步骤只定义一次并重复使用。 - DreadedFrost
1
@DreadedFrost在假日周末比我先完成了,谢谢。我明白你对SRP和pipelines的想法,但说实话,即使YAML pipeline是“代码”,我认为构建和部署活动是相互关联的。是的,可能会部署有问题的代码,但对我来说,这是一个破碎的过程问题(某人在推广之前没有验证构建和DEV部署),而无论如何都会发生。 - WaitingForGuacamole

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接