Azure DevOps पाइपलाइनों में सशर्त चरण निष्पादन

Dec 09 2020

मैं एक Azure DevOps पाइपलाइन में एक मंच चाहता हूं जिसे पिछले चरण में एक चर सेट की सामग्री के आधार पर निष्पादित किया जाए।

यहाँ मेरी पाइपलाइन है:

stages:
  - stage: plan_dev
    jobs:
    - job: terraform_plan_dev
      steps:
      - bash: echo '##vso[task.setvariable variable=terraform_plan_exitcode;isOutput=true]2'
        name: terraform_plan

  - stage: apply_dev
    dependsOn: plan_dev
    condition: eq(stageDependencies.plan_dev.terraform_plan_dev.outputs['terraform_plan.terraform_plan_exitcode'], '2')
    jobs:
    - deployment: "apply_dev"
      ...

विचार apply_devमंच को छोड़ना है , यदि plan_devमंच कोई परिवर्तन नहीं दिखाता है। पृष्ठभूमि यह है कि हमारे पास plan_devचरण में तैनाती के लिए मैन्युअल अनुमोदन है जिसे हम छोड़ना चाहते हैं यदि कोई बदलाव अनुमोदित नहीं है।

दुर्भाग्य से यह काम नहीं करता है। कोई फर्क नहीं पड़ता कि क्या चर terraform_plan_exitcodeअपेक्षित मूल्य (2) के साथ सेट है या नहीं, apply_devमंच छोड़ दिया गया है।

सिंटैक्स के लिए, मैंने यहाँ प्रलेखन का अनुसरण किया है जो कहता है:

stageDependencies.StageName.JobName.outputs['StepName.VariableName']

जवाब

1 MariusSolbakkenMellum Dec 09 2020 at 22:00

मैंने इसी मुद्दे को देखा है। आपको स्टेजड निर्भरता के बजाय निर्भरता चर का उपयोग करने की आवश्यकता है:

stages:
- stage: plan_dev
jobs:
- job: terraform_plan_dev
  steps:
  - bash: echo '##vso[task.setvariable variable=terraform_plan_exitcode;isOutput=true]2'
    name: terraform_plan

- stage: apply_dev
dependsOn: plan_dev
condition: eq(dependencies.plan_dev.outputs['terraform_plan_dev.terraform_plan.terraform_plan_exitcode'], '2')
jobs:
- deployment: "apply_dev"

Terraform Plan + सशर्त के साथ मेरे द्वारा काम करने के लिए निम्नलिखित कुछ और अधिक पूर्ण उदाहरण है:


stages: 
  - stage: Build_zip_plan
    displayName: Build portal, zip files and terraform plan
    jobs:
    - job: Build_portal_zip_files_terraform_plan
      pool:
        vmImage: 'ubuntu-latest'
      steps:
        - task: Cache@2
          displayName: 'Register TF cache'
          inputs:
            key: terraform | $(Agent.OS) | $(Build.BuildNumber) | $(Build.BuildId) | $(Build.SourceVersion) | $(prefix) path: ${{ parameters.tfExecutionDir }}

        - task: TerraformInstaller@0
          displayName: 'Install Terraform'
          inputs:
            terraformVersion: ${{ parameters.tfVersion }} - task: TerraformTaskV1@0 displayName: 'Terraform Init' inputs: provider: 'azurerm' command: 'init' workingDirectory: ${{ parameters.tfExecutionDir }}
            backendServiceArm: ${{ parameters.tfStateServiceConnection }} backendAzureRmResourceGroupName: ${{ parameters.tfStateResourceGroup }}
            backendAzureRmStorageAccountName: ${{ parameters.tfStateStorageAccount }} backendAzureRmContainerName: ${{ parameters.tfStateStorageContainer }}
            backendAzureRmKey: '$(prefix)-$(environment).tfstate'

        - task: TerraformTaskV1@0
          displayName: 'Terraform Plan'
          inputs:
            provider: 'azurerm'
            command: 'plan'
            commandOptions: '-input=false -out=deployment.tfplan -var="environment=$(environment)" -var="prefix=$(prefix)" -var="tenant=$(tenant)" -var="servicenow={username=\"$(servicenowusername)\",instance=\"$(servicenowinstance)\",password=\"$(servicenowpassword)\",assignmentgroup=\"$(servicenowassignmentgroup)\",company=\"$(servicenowcompany)\"}" -var="clientid=$(clientid)" -var="username=$(username)" -var="password=$(password)" -var="clientsecret=$(clientsecret)" -var="mcasapitoken=$(mcasapitoken)" -var="portaltenantid=$(portaltenantid)" -var="portalclientid=$(portalclientid)" -var="customerdisplayname=$(customerdisplayname)" -var="reportonlymode=$(reportonlymode)"' workingDirectory: ${{ parameters.tfExecutionDir }}
            environmentServiceNameAzureRM: ${{ parameters.tfServiceConnection }} - task: PowerShell@2 displayName: 'Check Terraform plan' name: "Check_Terraform_Plan" inputs: filePath: '$(Build.SourcesDirectory)/Pipelines/Invoke-CheckTerraformPlan.ps1'
            arguments: '-TfPlan ''${{ parameters.tfExecutionDir }}/deployment.tfplan''' pwsh: true - stage: dependsOn: Build_zip_plan displayName: Terraform apply condition: eq(dependencies.Build_zip_plan.outputs['Build_portal_zip_files_terraform_plan.Check_Terraform_Plan.TFChangesPending'], 'yes') jobs: - deployment: DeployHub displayName: Apply pool: vmImage: 'ubuntu-latest' environment: '$(prefix)'
      strategy:
        runOnce:
          deploy:
            steps:
            - checkout: self

            - task: Cache@2
              displayName: 'Get Cache for TF Artifact'
              inputs:
                key: terraform | $(Agent.OS) | $(Build.BuildNumber) | $(Build.BuildId) | $(Build.SourceVersion) | $(prefix) path: ${{ parameters.tfExecutionDir }}
                
            - task: TerraformInstaller@0
              displayName: 'Install Terraform'
              inputs:
                terraformVersion: ${{ parameters.tfVersion }} - task: TerraformTaskV1@0 displayName: 'Terraform Apply' inputs: provider: 'azurerm' command: 'apply' commandOptions: 'deployment.tfplan' workingDirectory: ${{ parameters.tfExecutionDir }}
                environmentServiceNameAzureRM: ${{ parameters.tfServiceConnection }}
1 KrzysztofMadej Dec 09 2020 at 22:32

@ हार्स सही है। तो यह काम करता है

stages:
  - stage: plan_dev
    jobs:
    - job: terraform_plan_dev
      steps:
      - bash: echo '##vso[task.setvariable variable=terraform_plan_exitcode;isOutput=true]2'
        name: terraform_plan

  - stage: apply_dev
    dependsOn: plan_dev
    variables:
      varFromA: $[ stageDependencies.plan_dev.terraform_plan_dev.outputs['terraform_plan.terraform_plan_exitcode'] ] condition: eq(dependencies.plan_dev.outputs['terraform_plan_dev.terraform_plan.terraform_plan_exitcode'], 2) jobs: - job: apply_dev steps: - bash: echo 'apply $(varFromA)'
        name: terraform_apply

जब आप चरण से चरण निर्भरता का संदर्भ देते हैं तो आपके पास अलग-अलग वाक्यविन्यास होते हैं

"dependencies": {
  "<STAGE_NAME>" : {
    "result": "Succeeded|SucceededWithIssues|Skipped|Failed|Canceled",
    "outputs": {
        "jobName.stepName.variableName": "value"
    }
  },
  "...": {
    // another stage
  }
}

और जब आप नौकरी से संदर्भित करते हैं तो आपके पास अलग-अलग सिंटैक्स होते हैं

"stageDependencies": {
  "<STAGE_NAME>" : {
    "<JOB_NAME>": {
      "result": "Succeeded|SucceededWithIssues|Skipped|Failed|Canceled",
      "outputs": {
          "stepName.variableName": "value"
      }
    },
    "...": {
      // another job
    }
  },
  "...": {
    // another stage
  }
}

जब आप एक चरण में नौकरी करने के लिए नौकरी करते हैं तो क्या अजीब बात है, हम dependeciesफिर से वाक्यविन्यास का उपयोग करते हैं

"dependencies": {
  "<JOB_NAME>": {
    "result": "Succeeded|SucceededWithIssues|Skipped|Failed|Canceled",
    "outputs": {
      "stepName.variableName": "value1"
    }
  },
  "...": {
    // another job
  }
}

यह थोड़ा भ्रमित करने वाला है और इस रूप में इस पर विचार करें

  • जब आप कुछ स्तर मंच, काम पर हैं और मंच से मंच करने के लिए नौकरी से काम करने के लिए या एक ही स्तर का उल्लेख आप dependenciesवाक्य रचना
  • जब आप नौकरी से लेकर मंच तक गहरे स्तर का उल्लेख करना चाहते हैं, तो आपको इसका उपयोग करना चाहिए stageDependencies

क्या मज़ेदार है, ऊपर के उदाहरण में मैंने इसे स्टेज स्तर पर इस्तेमाल किया:

variables:
      varFromA: $[ stageDependencies.plan_dev.terraform_plan_dev.outputs['terraform_plan.terraform_plan_exitcode'] ]

लेकिन यह रनटाइम पर मूल्यांकन किया जाता है और नौकरी से मूल्यांकन किया जाता है, इसलिए यह सही है और सही तरीके से मूल्यांकन किया जाता है।

मुझे आशा है कि इसने पिछले उत्तर के लिए एक मूल्य जोड़ा है।