Automation, Azure DevOps, Professional, YAML Pipelines

Azure DevOps PowerShell Task Template

Introduction

When deploying applications and infrastructure there are times when executing PowerShell is required as part of our Continuous Integration (CI) and Continuous Deployment (CD) Pipelines. There are two suggested ways to accomplish this. Either write the PowerShell inline of the ADO task or execute by passing in the path of the script. This post will cover passing a PowerShell file via the PowerShell ADO task. This task will be configured as a template to improve future usability.

When to Use

This task is to be used in YAML Pipelines. YAML pipelines are preferred to classic releases as the task steps will be defined as .yml file type and stored in Git. For this specific purpose I needed to run the PowerShell script which is part of Azure Data Factories deployment to stop and start triggers.

Seeing the script needed to be ran twice, I naturally created a task template to handle the execution. Additionally this task was templated to run any PowerShell script which is part of the artifact deployment.

Layout

This task template is stored in a centralized repository, in this case TheYAMLPipelineOne on GitHub. This task requires the PowerShell script be published as part of the artifact deployment. Publishing the script as part of the deployment as an artifact is a recommend practice as it will ensure the script that is deployed is retained as part of the pipeline and can be used across multiple stages.

The Template

Here is the PowerShell task template:

parameters:
- name: azureSubscriptionName
  type: string
- name: scriptPath
  type: string
- name: ScriptArguments
  type: string
  default: ''
- name: errorActionPreference
  type: string
  default: 'stop'
- name: FailOnStandardError
  type: boolean
  default: false
- name: azurePowerShellVersion
  type: string
  default: 'azurePowerShellVersion'
- name: preferredAzurePowerShellVersion
  type: string
  default: '3.1.0'
- name: pwsh
  type: boolean
  default: false
- name: workingDirectory
  type: string
- name: displayName
  type: string
  default: 'Running Custom Azure PowerShell script from file'

steps:
- task: AzurePowerShell@5
  displayName: ${{ parameters.displayName }}
  inputs:
    scriptType: 'FilePath'
    ConnectedServiceNameARM: ${{ parameters.azureSubscriptionName }}
    scriptPath: ${{ parameters.scriptPath  }}
    ScriptArguments: ${{ parameters.ScriptArguments }}
    errorActionPreference: ${{ parameters.errorActionPreference }}
    FailOnStandardError: ${{ parameters.FailOnStandardError }}
    azurePowerShellVersion: ${{ parameters.azurePowerShellVersion }}
    preferredAzurePowerShellVersion: ${{ parameters.preferredAzurePowerShellVersion }}
    pwsh: ${{ parameters.pwsh }}
    workingDirectory: ${{ parameters.workingDirectory }}
    

This task just requires the script path and the service connection. These are really the two things that can vary within a pipeline at a bare minimum. The rest of these parameters have been defaulted to the values associated with the task documentation. This is done to provide flexibility to override these values by any consuming template.

For an example of how to call this one can look at the adf_deploy_env_job.yml file on TheYAMLPipelineOne repository. One can check out the complete template by visiting the repository.

       - template: ../tasks/azpwsh_file_execute_task.yml
         parameters:
           azureSubscriptionName: ${{ variables.azureServiceConnectionName }}
           scriptPath: ${{ variables. powerShellScriptPath }}
           ScriptArguments: '-armTemplate "${{ variables.ARMTemplatePath }}" -ResourceGroupName ${{ variables.resourceGroupName }} -DataFactoryName ${{ variables.dataFactoryName }} -predeployment $true -deleteDeployment $false'
           displayName: 'Stop ADF Triggers'
           workingDirectory: ${{ parameters.workingDirectory }}

The Result

When this task executes, in this case, it will leverage the file PrePostDeploymentScript.ps1

Screenshot of ADFTemplates Pipeline Artifact

Here is the pipeline job results:

Screen shot of Pipeline Jobs and output of PowerShell Template task execution

Conclusion

This is a pretty basic example of how I template up my YAML deployments. This PowerShell template task is generic enough that it should provide flexibility for any PowerShell files one may want to execute as part of their deploments.

For information on this feel free to check out my other YAML Pipeline posts.