简体   繁体   中英

Azure DevOps pipelines - how to execute a whole template stage in a docker container by a self-hosted agent

I have a multi stage Azure DevOps pipeline in yaml. Each stage includes multiple jobs. The pipeline runs properly by using Azure-hosted agents. I need to run it by our company's self-hosted agent. The self-hosted agent is a virtual machine scale set (VMSS) which is defined as an agent pool in DevOps, it has been tested and is working properly. Because the self-hosted agent does not have all the capabilities we need, our company's policy is to run the jobs inside docker containers. The docker images reside in our company's private Azure Container Registy.

My question is how can I run a whole template stage in a docker container? Please note that my question is not about executing a job but all the jobs in a stage template. This link explains how to execute jobs inside a container. It doesn't give any examples of how to run all the jobs in a stage in a container, especially when the stage is defined as a template.

My pipeline in simplified form is as follows:

## Name of self-hosted agent
pool: Platform-VMSS

resources:
  containers:
  - container: base
    image: myazurecontainerregistryname.azurecr.io/platform/myimg:1.0.0
    endpoint: 'serviceconnection-acr'

trigger:
  branches:
    include: 
      - "feature/ORGUS-4810"
    exclude:
      - "main"
      - "release"
  paths:
    include:
      - "usecase-poc/**"

variables:
  pythonVersion: 3.8
  whlPackageName: py_core  
  srcDirectory: usecase-poc/$(whlPackageName)
  ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}:
    BuildFrom: main
    PackageName: $(whlPackageName)
    versionOption: custom
    deployToDevPipeline: True
    deployToQAPipeline: True
    deployToProdPipeline: True
  ${{ else }}:
    BuildFrom: branch_${{ lower(variables['Build.SourceBranchName'] ) }}
    PackageName: $(whlPackageName)_$(BuildFrom)
    versionOption: patch
    deployToDevPipeline: True
    deployToQAPipeline: False
    deployToProdPipeline: False
    stageName: 'deployToDev'

stages:
  - stage: DownloadArtifact
    displayName: "Download python whl from artifactory"
    jobs: 
    - job: DownloadArtifactJob
      steps:
      - checkout: self

      - task: UniversalPackages@0
        displayName: 'Download Artifact with Universal Packages'
        inputs:
          vstsFeed: 'some-value/00000000-0000-0009-0000-d24300000000'
          vstsFeedPackage: '00000000-0000-0000-0000-0000000'
          vstsPackageVersion: 0.8.4 
          downloadDirectory: $(Build.ArtifactStagingDirectory)

      - task: Bash@3
        name: GetWheelName_Task
        inputs:
          targetType: 'inline'
          script: |
            echo $(Build.ArtifactStagingDirectory)
            find $(Build.ArtifactStagingDirectory) -name '*.whl'
            ArtifactName=$(find $(Build.ArtifactStagingDirectory) -name '*.whl')
            echo "Artifact name value is " $ArtifactName
            echo "##vso[task.setvariable variable=ArtifactName;isOutput=true]$ArtifactName"
        displayName: 'Get downloaded artifact in source directory'
 
      - task: PublishBuildArtifacts@1
        displayName: "Publish downloaded artifact to pipeline's output"
        inputs:
          pathToPublish: $(Build.ArtifactStagingDirectory)
          artifactName: whl

  - stage: ConstructSharedVariablesForAllStages
    displayName: Construct Shared Variables For All Stages
    dependsOn: DownloadArtifact
    variables:
    - group: proj-shared-vg
    - name: ArtifactName
      value:  $[stageDependencies.DownloadArtifact.DownloadArtifactJob.outputs['GetWheelName_Task.ArtifactName']]
    jobs: 

    - job: DownloadArtifact
      container: base
      steps:
      - task: Bash@3
        displayName: "Print variable value"
        inputs:
          targetType: 'inline'
          script: |
            echo $(ArtifactName)

      - task: Bash@3
        name: extractWheelName
        displayName: Extract Wheel Name
        inputs:
          targetType: inline
          script: |
            echo $(ArtifactName) | awk -F"/" '{print $NF}'           
            WhlName="py_core-0.8.4-py3-none-any.whl"
            echo "##vso[task.setvariable variable=WhlName;isOutput=true]$WhlName"


      - task: DownloadPipelineArtifact@2
        displayName: "Download artifact from previous stage"
        inputs:
          buildType: 'current'
          project: 'Project Name'
          buildVersionToDownload: 'latest'
          artifactName: whl
          targetPath: '$(System.ArtifactsDirectory)'


      - pwsh: |
          $whlFile = Get-ChildItem -Filter *.whl -Path "$(System.ArtifactsDirectory)" | ForEach-Object { $_.fullname } | Select-Object -First 1
          Write-Host "##vso[task.setvariable variable=whlFile]$whlFile"
        name: SetVars
        displayName: Get wheel name

  ## This is the section where my question is about. How can I make sure each stage runs in the self-hosted agent pool. The stage contains multiple jobs.
  - template: ../templates/azure-pipeline-stage-template.yaml
    parameters:
      deploy: ${{variables.deployToDevPipeline}}
      variableGroup: databricks-sp-vg-dev
      stageName: DeployToDev
      environment: DBRKS_Dev_WHL
      conditionParameter: deployToDev
      dependsOnStage: ConstructSharedVariablesForAllStages

  - template: ../templates/azure-pipeline-stage-template.yaml
    parameters:
      deploy: ${{variables.deployToQAPipeline}}
      variableGroup: databricks-sp-vg-qa
      stageName: DeployToQA
      environment: DBRKS_QA_WHL
      conditionParameter: deployToQA
      dependsOnStage: DeployToDev

  - template: ../templates/azure-pipeline-stage-template.yaml
    parameters:
      deploy: ${{variables.deployToProdPipeline}}
      variableGroup: databricks-sp-vg-prod
      stageName: DeployToProd
      environment: DBRKS_Prod_WHL
      conditionParameter: deployToProd
      dependsOnStage: DeployToQA

In the code above in resources the container resides in our Azure Container Registry (ACR), the endpoint is our DevOps service connection of type container registry to pull and push images to and from ACR. In the code above I have commented where the issue is. In templates where I am refering to stage templates, I would like to run them all inside a container where I have defined as a resource at the beginning of the pipeline. The stage template has multiple jobs. Here is just a sample of stage template when running to emphasize it has multiple jobs:

舞台模板有多个作业

The highlighted stage is the one created by template:

  - template: ../templates/azure-pipeline-stage-template.yaml
    parameters:
      deploy: ${{variables.deployToDevPipeline}}
      variableGroup: databricks-sp-vg-dev
      stageName: DeployToDev
      environment: DBRKS_Dev_WHL
      conditionParameter: deployToDev
      dependsOnStage: ConstructSharedVariablesForAllStages

Question is how to enforce all the jobs in the above template run in the docker container defined as resource in our pipeline. Thank you very much for your valuable input.

Add a container field at the job level as shown below. Then all the jobs in the template will be running on specified container.

pool:  
  vmImage: ubuntu-latest  
resources:  
  containers:  
    - container: testcontainer  
      image: ubuntu  
stages:  
  - stage: template01  
    displayName: tempate test  
    jobs:  
      - job: template  
        container: testcontainer  
        steps:  
          - template: templates/template01.yaml  
  - stage: template02  
    displayName: template test  
    jobs:  
      - job: template  
        container: testcontainer  
        steps:  
          - template: templates/template02.yaml

Else, add a step target field to all the required tasks in a template, as referred to in this link Build and Release Tasks - Azure Pipelines |Microsoft Learn]( https://learn.microsoft.com/en-us/azure/devops/pipelines/process/tasks?view=azure-devops&tabs=yaml#step-target ) "https://learn.microsoft.com/en-us/azure/devops/pipelines/process/tasks?view=azure-devops&tabs=yaml#step-target)")

resources:  
containers:  
- container: pycontainer  
image: python:3.11  
 
steps:  
- task: AnotherTask@1  
target: pycontainer  

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM