Search code examples
azure-devopsazure-pipelinesazure-devops-extensionsazure-pipelines-decorator

Restricting Azure Pipeline decorators


I wanted to restrict azure pipeline decorator from injecting into all the pipelines. As we know once the decorators are installed it will be applied to all the projects in the organization. how can I restrict it to certain projects?

I used Projects API and got my project id and then i added the project id to my json template as a targettask and targetid.

  "properties": {
                "template": "custom-postjob-decorator.yml",
                "targetid": "9146bcde-ef7b-492d-8289-b3dce5f750b0"
            }

it didn't work, do we need to provide a condition in the decorator.yaml for restricting it to certain projects in the organization?


I have a few more questions.

now i don't want to run my decorator on Project B and i define like the below

steps:
- ${{ if in(variables['System.TeamProject'], 'ProjectB')) }}:
  - task: ADOSecurityScanner@1 --> injected decorator

I ran this and it is still injecting the decorator to ProjectB.


as you said i have created two scenarios.

  1. to skip if the task already exists, it works like a charm, but it did not show any messages about the skipping part. how can we tell the decorator is skipped in the pipeline?
steps:
-  ${{ if eq(variables['Build.task'], 'ADOSecurityScanner@1') }}:
  - task: CmdLine@2
    displayName: 'Skipping the injector'
    inputs:
      script: |
        echo "##vso[task.logissue type=error]This Step '$(Build.task)' is not injected. You dont need this in pipeline"
        exit 1
  1. i have used the condition from the microsoft documentation and also similar to the one above you mentioned above.

enter image description here enter image description here

it did not skip the injector with just the conditional command and when i added the task(powershell) in the decorator and pipeline.yaml then it is skipped the decorator matching the tasks on both yaml files.

does it show or log any info if the decorator is skipped in the pipeline. i observed it does display differently when the decorator is skipped showing me the false statement.

do we need to define anything on the pipeline.yaml file as well?


I ran with the conditions you had provided above and somehow the decorator is still getting injected into projectB. can you let me know where i am doing wrong.

here is my basic azure-pipeline.yaml file pasted below.

trigger:
- main

pool:
  vmImage: ubuntu-latest

steps:
- script: echo Hello, world!
  displayName: 'Run a one-line script'

- script: |
    echo Add other tasks to build, test, and deploy your project.
    echo See https://aka.ms/yaml
  displayName: 'Run a multi-line script'

enter image description here enter image description here


Solution

  • Be sure to read these docs:

    Simplest solution is to add a condition to the pipeline decorator:

    steps:
    - ${{ if not(eq(variables['azure-pipelines-tfvc-fixparallel-decorator.skip'], 'true')) }}:
      - task: tf-vc-fixparallel-log@2
    

    The decorator can use the pre-defined variables, including System.TeamProject or System.TeamProjectId:

    System.TeamProject The name of the project that contains this build.

    System.TeamProjectId The ID of the project that this build belongs to.

    For example:

    steps:
    - ${{ if in(variables['System.TeamProject'], 'ProjectA', 'ProjectB', 'ProjectC')) }}:
      - task: tf-vc-fixparallel-log@2
    

    You will need to include the steps: if you aren't already. For some reason returning an empty steps[] is fine, but returning nothing will result in a failing decorator.


    When you want to exclude a list of projects, simply inverse the condition. So to exclude 'ProjectB':

    steps:
    - ${{ if not(in(variables['System.TeamProject'], 'ProjectB')) }}:
      - task: ADOSecurityScanner@1 --> injected decorator
    

    Your statement above explicitly inserts into ProjectB, nowhere else.


    With regards to skipping the injector. The above -${{ if ... }}: completely removed the steps indented below it when the don't need to run. They will not appear at all.

    You can also put a condition on the task itself, in that case it will show up in the timeline, but as skipped:

    steps:
    - task: ADOSecurityScanner@1 --> injected decorator
      condition: not(in(variables['System.TeamProject'], 'ProjectB'))
    

    You can combine the condition with a variable, add it to the expression:

    steps:
    - ${{ if not(or(in(variables['System.TeamProject'], 'ProjectB'), 
             eq(variables['skipInjector'], 'true')) }}:
      - task: ADOSecurityScanner@1 --> injected decorator
    

    As you can see you can and(..., ...) and or(..., ...) these things together to form expressions as complex as you need.

    You can see the evaluation of your decorator in the top level log panel of your pipeline job. You need to expand the Job preparation parameters section. And make sure you queue the pipeline with diagnostics turned on.

    enter image description here

    When you used a condition on the task within the decorator, expand the log for the task to see the condition evaluation:

    enter image description here


    Looking at she screenshot you posted, two versions of the decorator are included, one with conditions and one without it. Make sure you uninstall/disable that other version.

    enter image description here