Aracılığıyla paylaş


Şablon kullanım başvurusu

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

Şablonlar YAML işlem hatlarında yeniden kullanılabilir içerik, mantık ve parametreler tanımlamanıza olanak sağlar. Şablonlarla etkili bir şekilde çalışmak için aşamalar, adımlar ve işler gibi Azure Pipelines temel kavramları hakkında temel bilgilere sahip olmanız gerekir.

Şablonlar geliştirmeyi hızlandırmanıza yardımcı olabilir. Örneğin, bir şablonda aynı görevlerin bir serisine sahip olabilir ve ardından şablonu YAML işlem hattınızın farklı aşamalarında birden çok kez ekleyebilirsiniz.

Şablonlar işlem hattınızın güvenliğini sağlamaya da yardımcı olabilir. Şablon işlem hattında izin verilenleri denetlediğinde, şablon başka bir dosyanın izlemesi gereken mantığı tanımlar. Örneğin, çalışmasına izin verilen görevleri kısıtlamak isteyebilirsiniz. Bu senaryoda, birinin kuruluşunuzun güvenlik ilkelerini ihlal eden bir görevi başarıyla çalıştırmasını önlemek için şablonu kullanabilirsiniz.

İki tür şablon vardır: içerir ve genişletir.

  • Şablonlar içerir, bir şablonla yeniden kullanılabilir içerik eklemenize olanak verir. Bir şablon içerik eklemek için kullanılıyorsa, birçok programlama dilindeki bir ekleme yönergesi gibi çalışır. Bir dosyadan içerik başka bir dosyaya eklenir.
  • şablon denetimini bir işlem hattında izin verilenlere genişletir. Bir genişletme şablonu bir işlem hattında izin verilenleri denetlediğinde, şablon başka bir dosyanın izlemesi gereken mantığı tanımlar.

Şablonlardan tam olarak yararlanmak için şablon ifadelerini ve şablon parametrelerini de kullanmanız gerekir.

Uygulanan sınırlar

Şablonlar ve şablon ifadeleri, işlem hattının boyutu ve karmaşıklığında önemli ölçüde büyümeye neden olabilir. Azure Pipelines, kaçak büyümeyi önlemeye yardımcı olmak için aşağıdaki sınırları uygular:

  • En fazla 100 ayrı YAML dosyası dahil edilebilir (doğrudan veya dolaylı olarak)
  • En fazla 20 şablon düzeyi iç içe yerleştirilebilir (diğer şablonları içeren şablonlar)
  • YAML ayrıştırılırken 10 megabayttan fazla bellek tüketilmemiştir (pratikte, bu genellikle kullanılan özelliklere bağlı olarak 600 KB - 2 MB disk içi YAML arasındadır)

Mantığınızı bir kez tanımlamak için şablonları kullanın ve ardından birkaç kez yeniden kullanın. Şablonlar, birden çok YAML dosyasının içeriğini tek bir işlem hattında birleştirir. Parametreleri üst işlem hattınızdan bir şablona geçirebilirsiniz.

Şablondan genişletme

Güvenliği artırmak için, bir işlem hattının belirli bir şablondan genişletildiğini zorlayabilirsiniz. dosyasıstart.yml, işlem hattında azure-pipelines.ymlkullanılan parametresini buildStepstanımlar. içinde start.yml, bir buildStep betik adımıyla geçirilirse reddedilir ve işlem hattı derlemesi başarısız olur. Şablondan genişletirken, gerekli bir şablon onayı ekleyerek güvenliği artırabilirsiniz.

# File: start.yml
parameters:
- name: buildSteps # the name of the parameter is buildSteps
  type: stepList # data type is StepList
  default: [] # default value of buildSteps
stages:
- stage: secure_buildstage
  pool:
    vmImage: windows-latest
  jobs:
  - job: secure_buildjob
    steps:
    - script: echo This happens before code 
      displayName: 'Base: Pre-build'
    - script: echo Building
      displayName: 'Base: Build'

    - ${{ each step in parameters.buildSteps }}:
      - ${{ each pair in step }}:
          ${{ if ne(pair.value, 'CmdLine@2') }}:
            ${{ pair.key }}: ${{ pair.value }}       
          ${{ if eq(pair.value, 'CmdLine@2') }}: 
            # Step is rejected by raising a YAML syntax error: Unexpected value 'CmdLine@2'
            '${{ pair.value }}': error         

    - script: echo This happens after code
      displayName: 'Base: Signing'
# File: azure-pipelines.yml
trigger:
- main

extends:
  template: start.yml
  parameters:
    buildSteps:  
      - bash: echo Test #Passes
        displayName: succeed
      - bash: echo "Test"
        displayName: succeed
      # Step is rejected by raising a YAML syntax error: Unexpected value 'CmdLine@2'
      - task: CmdLine@2
        inputs:
          script: echo "Script Test"
      # Step is rejected by raising a YAML syntax error: Unexpected value 'CmdLine@2'
      - script: echo "Script Test"

Kaynaklarla şablondan genişletme

Kaynakları içeren Azure işlem hattınızdaki bir şablondan genişletmek için de kullanabilirsiniz extends .

# File: azure-pipelines.yml
trigger:
- none

extends:
  template: resource-template.yml
# File: resource-template.yml
resources:
  pipelines:
  - pipeline: my-pipeline 
    source: sourcePipeline

steps:
- script: echo "Testing resource template"

Şablon ekleme

Bir YAML'den içerik kopyalayabilir ve farklı bir YAML'de yeniden kullanabilirsiniz. Bir YAML'den diğerine içerik kopyalamak, aynı mantığı birden çok yere el ile eklemek zorunda kalmadan sizi kurtarır. Dosya include-npm-steps.yml şablonu içinde azure-pipelines.ymlyeniden kullanılan adımları içerir.

Not

Şablon dosyalarının işlem hattı çalıştırmasının başlangıcında dosya sisteminizde bulunması gerekir. Yapıttaki şablonlara başvuramazsınız.

# File: templates/include-npm-steps.yml

steps:
- script: npm install
- script: yarn install
- script: npm run compile
# File: azure-pipelines.yml

jobs:
- job: Linux
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - template: templates/include-npm-steps.yml  # Template reference
- job: Windows
  pool:
    vmImage: 'windows-latest'
  steps:
  - template: templates/include-npm-steps.yml  # Template reference

Adım yeniden kullanma

Birkaç işte bir veya daha fazla adımı yeniden kullanmak için şablon ekleyebilirsiniz. Şablondaki adımlara ek olarak, her iş daha fazla adım tanımlayabilir.

# File: templates/npm-steps.yml
steps:
- script: npm install
- script: npm test
# File: azure-pipelines.yml

jobs:
- job: Linux
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - template: templates/npm-steps.yml  # Template reference

- job: macOS
  pool:
    vmImage: 'macOS-latest'
  steps:
  - template: templates/npm-steps.yml  # Template reference

- job: Windows
  pool:
    vmImage: 'windows-latest'
  steps:
  - script: echo This script runs before the template's steps, only on Windows.
  - template: templates/npm-steps.yml  # Template reference
  - script: echo This step runs after the template's steps.

İş yeniden kullanımı

Adımlar gibi işler de şablonlarla yeniden kullanılabilir.

# File: templates/jobs.yml
jobs:
- job: Ubuntu
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - bash: echo "Hello Ubuntu"

- job: Windows
  pool:
    vmImage: 'windows-latest'
  steps:
  - bash: echo "Hello Windows"
# File: azure-pipelines.yml

jobs:
- template: templates/jobs.yml  # Template reference

Birden çok iş ile çalışırken, çakışmayı önlemek için şablon dosyasında işin adını kaldırmayı unutmayın

# File: templates/jobs.yml
jobs:
- job: 
  pool:
    vmImage: 'ubuntu-latest'
  steps:
  - bash: echo "Hello Ubuntu"

- job:
  pool:
    vmImage: 'windows-latest'
  steps:
  - bash: echo "Hello Windows"
# File: azure-pipelines.yml

jobs:
- template: templates/jobs.yml  # Template reference
- template: templates/jobs.yml  # Template reference
- template: templates/jobs.yml  # Template reference

Aşama yeniden kullanımı

Aşamalar şablonlarla da yeniden kullanılabilir.

# File: templates/stages1.yml
stages:
- stage: Angular
  jobs:
  - job: angularinstall
    steps:
    - script: npm install angular
# File: templates/stages2.yml
stages:
- stage: Build
  jobs:
  - job: build
    steps:
    - script: npm run build
# File: azure-pipelines.yml
trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

stages:
- stage: Install
  jobs: 
  - job: npminstall
    steps:
    - task: Npm@1
      inputs:
        command: 'install'
- template: templates/stages1.yml # Template reference
- template: templates/stages2.yml # Template reference

Parametrelerle iş, aşama ve adım şablonları

Aşağıdaki şablonlarda:

  • templates/npm-with-params.yml iki parametre tanımlar: name ve vmImage iş adı için ad parametresiyle ve VM görüntüsü için vmImage parametresiyle bir iş oluşturur.
  • İşlem hattı (azure-pipelines.yml), şablona üç kez başvurur ve her birinde işletim sistemi ve VM görüntü adlarına başvuran farklı parametre değerleri bulunur.
  • Oluşturulan işlem hattı farklı bir VM görüntüsü üzerinde çalışır ve belirtilen işletim sistemine göre adlandırılır. Her iş npm yükleme ve npm test adımları gerçekleştirir.
# File: templates/npm-with-params.yml

parameters:
- name: name  # defaults for any parameters that aren't specified
  default: ''
- name: vmImage
  default: ''

jobs:
- job: ${{ parameters.name }}
  pool: 
    vmImage: ${{ parameters.vmImage }}
  steps:
  - script: npm install
  - script: npm test

şablonu işlem hattınızda kullandığınızda, şablon parametreleri için değerleri belirtin.

# File: azure-pipelines.yml

jobs:
- template: templates/npm-with-params.yml  # Template reference
  parameters:
    name: Linux
    vmImage: 'ubuntu-latest'

- template: templates/npm-with-params.yml  # Template reference
  parameters:
    name: macOS
    vmImage: 'macOS-latest'

- template: templates/npm-with-params.yml  # Template reference
  parameters:
    name: Windows
    vmImage: 'windows-latest'

Şablonları birden çok parametreyle hazırlama

Aşağıdaki şablonlarda:

  • Şablon stage-template.yml dört parametre tanımlar: stageName, jobName, vmImage, ve scriptPath, tüm tür dizeleri. Şablon, aşama adını ayarlamak için parametresini stageName kullanarak bir aşama oluşturur, ile jobNamebir iş tanımlar ve bir betik çalıştırma adımı içerir.
  • İşlem hattı, azure-pipeline.ymlardından parametreleri kullanarak aşamaları ve işleri dinamik olarak tanımlar ve betik build-script.shyürüten bir iş çalıştırır.
# stage-template.yml

parameters:
  - name: stageName
    type: string
  - name: jobName
    type: string
  - name: vmImage
    type: string
  - name: scriptPath
    type: string

stages:
  - stage: ${{ parameters.stageName }}
    jobs:
      - job: ${{ parameters.jobName }}
        pool:
          vmImage: ${{ parameters.vmImage }}
        steps:
          - script: ./${{ parameters.scriptPath }}
# azure-pipelines.yml
trigger:
- main

stages:
- template: stage-template.yml
  parameters:
    stageName: 'BuildStage'
    jobName: 'BuildJob'
    scriptPath: 'build-script.sh' # replace with script in your repository
    vmImage: 'ubuntu-latest'

Adım ve parametre içeren şablonlar

Parametreleri adım veya aşama şablonlarıyla da kullanabilirsiniz.

Aşağıdaki şablonlarda:

  • Şablon (templates/steps-with-params.yml), varsayılan değeri false olan adlı runExtendedTests bir parametre tanımlar.
  • İşlem hattı (azure-pipelines.yml) ve parametresi true olduğundan runExtendedTests çalışır npm test npm test --extended.
# File: templates/steps-with-params.yml

parameters:
- name: 'runExtendedTests'  # defaults for any parameters that aren't specified
  type: boolean
  default: false

steps:
- script: npm test
- ${{ if eq(parameters.runExtendedTests, true) }}:
  - script: npm test --extended

şablonu işlem hattınızda kullandığınızda, şablon parametreleri için değerleri belirtin.

# File: azure-pipelines.yml

steps:
- script: npm install

- template: templates/steps-with-params.yml  # Template reference
  parameters:
    runExtendedTests: 'true'

Not

Belirtilen türe sahip olmayan Skaler parametreler dize olarak değerlendirilir. Örneğin, eq(true, parameters['myparam']) parametresi açıkça yapılmadıysa booleanmyparam sözcüğü falseolsa myparam bile döndürürtrue. Boş olmayan dizeler Boole bağlamında olarak oluşturulur true . Bu ifade , dizeleri açıkça karşılaştırmak için yeniden yazılabilir: eq(parameters['myparam'], 'true').

Parametreler skaler dizelerle sınırlı değildir. Veri türlerinin listesine bakın. Örneğin, türünü kullanarak object :

# azure-pipelines.yml
jobs:
- template: process.yml
  parameters:
    pool:   # this parameter is called `pool`
      vmImage: ubuntu-latest  # and it's a mapping rather than a string


# process.yml
parameters:
- name: 'pool'
  type: object
  default: {}

jobs:
- job: build
  pool: ${{ parameters.pool }}

Değişken yeniden kullanımı

Değişkenler bir YAML'de tanımlanabilir ve başka bir şablona eklenebilir. Tüm değişkenlerinizi tek bir dosyada depolamak istiyorsanız bu yararlı olabilir. bir işlem hattına değişken eklemek için şablon kullanıyorsanız, dahil edilen şablon yalnızca değişkenleri tanımlamak için kullanılabilir. Bir şablondan genişletirken adımları ve daha karmaşık mantığı kullanabilirsiniz. Türü kısıtlamak istediğinizde değişkenler yerine parametreleri kullanın.

Bu örnekte değişkenine favoriteVeggie azure-pipelines.ymldahil edilir.

# File: vars.yml
variables:
  favoriteVeggie: 'brussels sprouts'
# File: azure-pipelines.yml

variables:
- template: vars.yml  # Template reference

steps:
- script: echo My favorite vegetable is ${{ variables.favoriteVeggie }}.

Parametresi olan değişken şablonları

Şablonlarla değişkenlere parametre geçirebilirsiniz. Bu örnekte parametresini DIRECTORY bir RELEASE_COMMAND değişkene geçiriyorsunuz.

# File: templates/package-release-with-params.yml

parameters:
- name: DIRECTORY 
  type: string
  default: "." # defaults for any parameters that specified with "." (current directory)

variables:
- name: RELEASE_COMMAND
  value: grep version ${{ parameters.DIRECTORY }}/package.json | awk -F \" '{print $4}'  

şablonu işlem hattınızda kullandığınızda, şablon parametreleri için değerleri belirtin.

# File: azure-pipelines.yml

variables: # Global variables
  - template: package-release-with-params.yml # Template reference
    parameters:
      DIRECTORY: "azure/checker"

pool:
  vmImage: 'ubuntu-latest'

stages:
- stage: Release_Stage 
  displayName: Release Version
  variables: # Stage variables
  - template: package-release-with-params.yml  # Template reference
    parameters:
      DIRECTORY: "azure/todo-list"
  jobs: 
  - job: A
    steps: 
    - bash: $(RELEASE_COMMAND) #output release command

Şablondan genişletme ve değişkenlerle ekleme şablonu kullanma

Yaygın senaryolardan biri, hem değişkenler için bir şablon hem de aşamalar veya işler için bir şablon kullanan geliştirme, test ve üretim aşamalarına sahip bir işlem hattına sahip olmaktır.

Aşağıdaki örnekte, variables-template.yml daha sonra içinde azure-pipeline.ymlkullanılan bir dizi sanal makine değişkeni tanımlar.

# variables-template.yml

variables:
- name: devVmImage
  value: 'ubuntu-latest'
- name: testVmImage
  value: 'ubuntu-latest'
- name: prodVmImage
  value: 'ubuntu-latest'

Aşağıdaki dosya, stage-template.yml üç parametre (name, vmImage, steps) ve adlı Buildbir iş ile yeniden kullanılabilir bir aşama yapılandırmasını tanımlar.

# stage-template.yml
parameters:
- name: name
  type: string
  default: ''
- name: vmImage
  type: string
  default: ''
- name: steps
  type: stepList
  default: []

stages:
- stage: ${{ parameters.name }}
  jobs:
  - job: Build
    pool:
      vmImage: ${{ parameters.vmImage }}
    steps: ${{ parameters.steps }}

Aşağıdaki işlem hattı, azure-pipelines.ymldeğişkenlerini içinden variables-template.ymliçeri aktarır ve ardından her aşama için şablonu kullanır stage-template.yml . Her aşama (Geliştirme, Test, Üretim) aynı şablonla ancak farklı parametrelerle tanımlanır ve bu da aşamalar arasında tutarlılık sağlarken özelleştirmeye olanak tanır. Prod aşaması, kimlik doğrulaması için kullanabileceğiniz bir şeye örnek olarak bir ortam değişkeni içerir.

# azure-pipelines.yml
trigger:
- main

variables:
- template: variables-template.yml

stages:
- template: stage-template.yml
  parameters:
    name: Dev
    vmImage: ${{ variables.devVmImage }}
    steps:
      - script: echo "Building in Dev"
- template: stage-template.yml
  parameters:
    name: Test
    vmImage: ${{ variables.testVmImage }}
    steps:
      - script: echo "Testing in Test"
- template: stage-template.yml
  parameters:
    name: Prod
    vmImage: ${{ variables.prodVmImage }}
    steps:
      - script: echo "Deploying to Prod"
        env:
          SYSTEM_ACCESSTOKEN: $(System.AccessToken)

Başvuru şablonu yolları

Şablon yolları, depo içinde veya dahil eden dosyaya göre mutlak bir yol olabilir.

Mutlak yol kullanmak için şablon yolunun ile /başlaması gerekir. Diğer tüm yollar göreli olarak kabul edilir.

Aşağıda iç içe yerleştirilmiş bir hiyerarşi örneği verilmiş.

|
+-- fileA.yml
|
+-- dir1/
     |
     +-- fileB.yml
     |
     +-- dir2/
          |
          +-- fileC.yml

Ardından, içinde fileA.yml buna başvurabilir fileB.yml ve fileC.yml bunu beğenebilirsiniz.

steps:
- template: dir1/fileB.yml
- template: dir1/dir2/fileC.yml

Başlangıç noktanız buysa fileC.yml , bunu dahil fileA.yml edebilir ve fileB.yml beğenebilirsiniz.

steps:
- template: ../../fileA.yml
- template: ../fileB.yml

Başlangıç noktanız ne zaman fileB.yml olursa, bunu dahil fileA.yml edebilir ve fileC.yml beğenebilirsiniz.

steps:
- template: ../fileA.yml
- template: dir2/fileC.yml

Alternatif olarak, fileB.yml bunun gibi mutlak yollara fileA.yml başvurabilir ve fileC.yml kullanabilirsiniz.

steps:
- template: /fileA.yml
- template: /dir1/dir2/fileC.yml

Diğer depoları kullanma

Şablonlarınızı diğer depolarda tutabilirsiniz. Örneğin, tüm uygulama işlem hatlarınızın kullanmasını istediğiniz bir çekirdek işlem hattınız olduğunu varsayalım. Şablonu bir çekirdek depoya koyabilir ve ardından uygulama depolarınızın her birinden bu şablona başvurabilirsiniz:

# Repo: Contoso/BuildTemplates
# File: common.yml
parameters:
- name: 'vmImage'
  default: 'ubuntu-22.04'
  type: string

jobs:
- job: Build
  pool:
    vmImage: ${{ parameters.vmImage }}
  steps:
  - script: npm install
  - script: npm test

Artık bu şablonu birden çok işlem hattında yeniden kullanabilirsiniz. Çekirdek deponun resources konumunu sağlamak için belirtimini kullanın. Çekirdek depoya başvururken ve içinde resourcesbu depoya vermiş olduğunuz adı kullanın@.

# Repo: Contoso/LinuxProduct
# File: azure-pipelines.yml
resources:
  repositories:
    - repository: templates
      type: github
      name: Contoso/BuildTemplates

jobs:
- template: common.yml@templates  # Template reference
# Repo: Contoso/WindowsProduct
# File: azure-pipelines.yml
resources:
  repositories:
    - repository: templates
      type: github
      name: Contoso/BuildTemplates
      ref: refs/tags/v1.0 # optional ref to pin to

jobs:
- template: common.yml@templates  # Template reference
  parameters:
    vmImage: 'windows-latest'

name içintype: github, yukarıdaki örneklerde olduğu gibi.<identity>/<repo> için type: git (Azure Repos), name şeklindedir <project>/<repo>. Bu proje ayrı bir Azure DevOps kuruluşundaysa, projeye erişimi olan türde Azure Repos/Team Foundation Server bir hizmet bağlantısı yapılandırmanız ve bunu YAML'ye eklemeniz gerekir:

resources:
  repositories:
  - repository: templates
    name: Contoso/BuildTemplates
    endpoint: myServiceConnection # Azure DevOps service connection
jobs:
- template: common.yml@templates

Depolar, işlem hattı başlatıldığında yalnızca bir kez çözümlenir. Bundan sonra, işlem hattı süresi boyunca aynı kaynak kullanılır. Yalnızca şablon dosyaları kullanılır. Şablonlar tamamen genişletildikten sonra, son işlem hattı tamamen kaynak depoda tanımlanmış gibi çalışır. Başka bir deyişle işlem hattınızdaki şablon deposundaki betikleri kullanamazsınız.

Şablonun belirli, sabit bir sürümünü kullanmak istiyorsanız, bir reföğesine sabitlediğinizden emin olun. refs dallardır (refs/heads/<name>) veya etiketlerdir (refs/tags/<name>). Belirli bir işlemeyi sabitlemek istiyorsanız, önce bu işlemeye işaret eden bir etiket oluşturun, ardından bu etikete sabitleyin.

Not

Belirtilmezse ref , işlem hattı varsayılan olarak kullanır refs/heads/main.

Ayrıca Git'te depo kaynağının SHA değeriyle belirli bir işlemeye sabitleyebilirsiniz. SHA değeri, işlemeyi benzersiz olarak tanımlayan 40 karakterlik sağlama toplamı karmasıdır.

resources:
  repositories:
    - repository: templates
      type: git
      name: Contoso/BuildTemplates
      ref: 1234567890abcdef1234567890abcdef12345678

Ayrıca, özgün işlem hattının bulunduğu depoya başvurmak için de kullanabilirsiniz @self . Genişletme işlem hattının deposundaki extends içeriklere geri başvurmak istiyorsanız bu, şablonlar için kullanışlıdır. Örneğin:

# Repo: Contoso/Central
# File: template.yml
jobs:
- job: PreBuild
  steps: []

  # Template reference to the repo where this template was
  # included from - consumers of the template are expected
  # to provide a "BuildJobs.yml"
- template: BuildJobs.yml@self

- job: PostBuild
  steps: []
# Repo: Contoso/MyProduct
# File: azure-pipelines.yml
resources:
  repositories:
    - repository: templates
      type: git
      name: Contoso/Central

extends:
  template: template.yml@templates
# Repo: Contoso/MyProduct
# File: BuildJobs.yml
jobs:
- job: Build
  steps: []

SSS

Şablonların içinde değişkenleri nasıl kullanabilirim?

Parametreleri değişkenleri temel alan değerlere ayarlamanın yararlı olabileceği durumlar vardır. Parametreler bir işlem hattı çalıştırması işlenirken erken genişletilir, bu nedenle tüm değişkenler kullanılamaz. Önceden tanımlanmış hangi değişkenlerin şablonlarda kullanılabildiğini görmek için bkz. Önceden tanımlanmış değişkenleri kullanma.

Bu örnekte, önceden tanımlanmış değişkenler Build.SourceBranch ve Build.Reason template.yml koşullarında kullanılır.

# File: azure-pipelines.yml
trigger:
- main

extends:
  template: template.yml
# File: template.yml
steps:
- script: echo Build.SourceBranch = $(Build.SourceBranch) # outputs refs/heads/main
- script: echo Build.Reason = $(Build.Reason) # outputs IndividualCI
- ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}: 
  - script: echo I run only if Build.SourceBranch = refs/heads/main 
- ${{ if eq(variables['Build.Reason'], 'IndividualCI') }}: 
  - script: echo I run only if Build.Reason = IndividualCI 
- script: echo I run after the conditions