将 Azure DevOps 中的选定工件作为 docker 图像部署到 ECR

Deploy selected artifact in Azure DevOps as docker image to ECR

环境

现状

目前正在使用 dotnet build(powershell 脚本)构建应用程序并使用 azurepipeline.yml 将 zip 文件推送到 Azure DevOps 工件。这很好用。我为 ECR 推送添加了另一个任务,它还使用源代码中的 Docker 文件将生成的 docker 图像推送到 ECR。

业务问题

我们希望能够在 Azure Artifact 中选择特定版本(例如 0.1.24)(使用变量提供版本号),并使用相应的二进制文件和Docker文件。我无法找到这样做的方法。具体任务如下:-

  1. 使用工件 ID 或名称部署用户更新变量“versionNoToDeploy”
  2. 部署用户运行特定管道
  3. 管道找到工件(假设其有效,否则发送错误),在临时位置解压缩包(-需要帮助
  4. 流水线运行docker文件来构建图像(-已知且有效)
  5. 管道将此映像推送到 ECR(-已知且有效)

目的是继续构建分支,直到我们获得稳定的构建。此版本手动部署在测试服务器上并经过测试。构建获得认证后,需要将其推送到生产 ECR/ECS 个实例。

我们的流水线(仅限具体代码)

- pwsh: ./build.ps1 --target Clean Protolint Compile --runtime $(runtime) 
  displayName: ⚙️ Compile

- task: Docker@2
  displayName: Build
  inputs:
     command: build
     repository: appRepo
     tags: |
       $(Build.BuildId)
       deploy
     addPipelineData: true
     Dockerfile: src\DockerfileNew

- task: ECRPushImage@1
  inputs:
     awsCredentials: 'AWS ECR Connection'
     regionName: 'ap-south-1'
     imageSource: 'imagename'
     sourceImageName: 'myApplication'
     sourceImageTag: 'deploy'
     repositoryName: 'devops-demo'
     outputVariable: 'imageTagOutputVar'

- pwsh: ./build.ps1 --target Test Coverage --skip
  displayName:  Test

- pwsh: ./build.ps1 --target BuildImage Pack --runtime $(runtime) --skip
  displayName:  Pack

- pwsh: ./build.ps1 --target Publish --runtime $(runtime) --skip
  displayName:  Publish

神器详情

可以提供任何需要的具体方面

由于这里涉及到人工干预,你可以考虑将工作流分成几个工作,像这样:

jobs:
- job: BuildAndDeployToTest
  steps:
  - bash: echo "A"

- job: waitForValidation
    displayName: Wait for external validation
    pool: server
    timeoutInMinutes: 4320 # job times out in 3 days
    steps:
    - task: ManualValidation@0
      timeoutInMinutes: 1440 # task times out in 1 day
      inputs:
        notifyUsers: |
          test@test.com
          example@example.com
        instructions: 'Please validate the build configuration and resume'
        onTimeout: 'resume'  


- job: DeployToProd
  steps:
  - bash: echo "B"

这不是你想要的变量,但你将能够实现你的目标。等待验证并部署以仅生产经过验证的构建。

依赖ManualValidation task.

另一种方法可能是使用部署作业和批准:

jobs:
- job: BuildAndDeployToTest
  steps:
  - bash: echo "A"


jobs:
  # Track deployments on the environment.
- deployment: DeployToProd
  displayName: deploy Web App
  pool:
    vmImage: 'Ubuntu-16.04'
  # Creates an environment if it doesn't exist.
  environment: 'PROD'
  strategy:
    # Default deployment strategy, more coming...
    runOnce:
      deploy:
        steps:
        - checkout: self 
        - script: echo my first deployment

为此你需要定义 evnironment and define approval.

通过这两种方式,您都可以清楚地了解交付给产品的内容以及谁批准了产品部署的信息。

最后,在大量使用管道并自定义调整各个步骤之后,我得出了以下结果(摘自 yml)。

这涉及将构建版本存储在变量中,该变量在管道的每个步骤中都被引用。 管理员必须决定他们是否想要一个通用的构建,生成一个工件;或者只是将特定构建部署到 AWS。有条件地评估具有 build-id 的变量,并基于此执行或绕过这些步骤。

- pwsh: ./build.ps1 --target Clean Protolint Compile --runtime $(runtime)
  condition: eq(variables['artifactVersionToPush'], '')
  displayName: ⚙️ Compile

- task: DownloadBuildArtifacts@0
  condition: ne(variables['artifactVersionToPush'], '')
  inputs:
     buildType: 'specific'
     project: 'NitinProj'
     pipeline: 'NitinProj'
     buildVersionToDownload: specific
     buildId: $(artifactVersionToPush)
     downloadType: 'single'
     artifactName: 'app'
     downloadPath: '$(System.ArtifactsDirectory)'   #(this needs to be mentioned as default is Build directory)

 - task: ExtractFiles@1
   displayName: Extract Artifact to temp location
   condition: ne(variables['artifactVersionToPush'], '')
   inputs:
     archiveFilePatterns: '$(System.ArtifactsDirectory)/app/*.zip'    #path need update
     cleanDestinationFolder: false
     overwriteExistingFiles: true
     destinationFolder: src

 - task: Docker@2
   displayName: Docker Build image with compiled code in artifact
   condition: ne(variables['artifactVersionToPush'], '')
   inputs:
     command: build
     repository: myApp
     tags: |
       $(Build.BuildId)
       deploy
     addPipelineData: true
     Dockerfile: src\DockerfileNew

 - task: ECRPushImage@1
   displayName: Push built image to AWS ECR
   condition: ne(variables['artifactVersionToPush'], '')
   inputs:
     awsCredentials: 'AWS ECR Connection'
     regionName: 'ap-south-1'
     imageSource: 'imagename'
     sourceImageName: 'myApp'
     sourceImageTag: 'deploy'
     pushTag: '$(Build.BuildId)'
     repositoryName: 'devops-demo'
     outputVariable: 'imageTagOutputVar'

 - pwsh: ./build.ps1 --target Test Coverage --skip
   condition: eq(variables['artifactVersionToPush'], '')
   displayName:  Test

 - pwsh: ./build.ps1 --target BuildImage Pack --runtime $(runtime) --skip
   condition: eq(variables['artifactVersionToPush'], '')
   displayName:  Pack

 - pwsh: ./build.ps1 --target Publish --runtime $(runtime) --skip
   condition: eq(variables['artifactVersionToPush'], '')
   displayName:  Publish

我将更新此 yml 以将步骤组织到作业中,但这是一个优化故事..:)