|
| 1 | +# --------------------------------------------------------------------------- |
| 2 | +# adoqr — scheduled Azure DevOps best-practice assessment |
| 3 | +# --------------------------------------------------------------------------- |
| 4 | +# Runs invoke-adoqr.ps1 on a schedule and publishes the generated reports |
| 5 | +# (Markdown + executive/remediation HTML + JSON) as a pipeline artifact, so you |
| 6 | +# get a recurring, archived posture review without anyone running the tool by |
| 7 | +# hand. |
| 8 | +# |
| 9 | +# SETUP |
| 10 | +# 1. Import this file as a new pipeline (Pipelines ▸ New pipeline ▸ |
| 11 | +# "Existing Azure Pipelines YAML file" ▸ /examples/azure-pipelines.yml). |
| 12 | +# 2. Create an ARM service connection (Project settings ▸ Service connections) |
| 13 | +# and grant its service principal access to the Azure DevOps organization |
| 14 | +# you want to assess: |
| 15 | +# - Add the SP as a member of the org (Organization settings ▸ Users) |
| 16 | +# with at least "Project Collection Valid Users"; use "Project |
| 17 | +# Collection Administrators" for full admin/audit coverage. |
| 18 | +# 3. Set the pipeline variables below (Edit ▸ Variables), or override them at |
| 19 | +# queue time via the parameters. |
| 20 | +# |
| 21 | +# AUTHENTICATION |
| 22 | +# The AzureCLI@2 task signs in with the service connection, so adoqr's |
| 23 | +# `az account get-access-token` call obtains an Azure DevOps bearer token with |
| 24 | +# no PAT required — the same auth path as an interactive `az login`. |
| 25 | +# |
| 26 | +# SCHEDULE |
| 27 | +# The cron below runs every Monday at 06:00 UTC. `always: true` makes it run |
| 28 | +# even when main has not changed since the last assessment. Adjust as needed: |
| 29 | +# https://learn.microsoft.com/azure/devops/pipelines/process/scheduled-triggers |
| 30 | +# --------------------------------------------------------------------------- |
| 31 | + |
| 32 | +# Schedule-only: do not run on pushes or pull requests. |
| 33 | +trigger: none |
| 34 | +pr: none |
| 35 | + |
| 36 | +schedules: |
| 37 | + - cron: '0 6 * * 1' # 06:00 UTC every Monday |
| 38 | + displayName: Weekly adoqr assessment |
| 39 | + branches: |
| 40 | + include: |
| 41 | + - main |
| 42 | + always: true |
| 43 | + |
| 44 | +parameters: |
| 45 | + - name: organization |
| 46 | + displayName: ADO organization (URL or short name) |
| 47 | + type: string |
| 48 | + default: 'https://dev.azure.com/MyOrg' |
| 49 | + - name: projects |
| 50 | + displayName: Projects (space-separated; empty = all projects) |
| 51 | + type: string |
| 52 | + default: '' |
| 53 | + - name: maxParallel |
| 54 | + displayName: Max projects assessed concurrently |
| 55 | + type: number |
| 56 | + default: 3 |
| 57 | + - name: outputFormat |
| 58 | + displayName: Output format |
| 59 | + type: string |
| 60 | + default: 'all' |
| 61 | + values: |
| 62 | + - markdown |
| 63 | + - html |
| 64 | + - json |
| 65 | + - all |
| 66 | + |
| 67 | +variables: |
| 68 | + # Name of the ARM service connection authorized against the target ADO org. |
| 69 | + azureServiceConnection: 'adoqr-assessment' |
| 70 | + |
| 71 | +pool: |
| 72 | + vmImage: ubuntu-latest |
| 73 | + |
| 74 | +steps: |
| 75 | + - checkout: self |
| 76 | + displayName: Check out adoqr |
| 77 | + |
| 78 | + - task: AzureCLI@2 |
| 79 | + displayName: Run adoqr assessment |
| 80 | + env: |
| 81 | + # No interactive browser on a build agent; don't try to auto-open the |
| 82 | + # report. adoqr also auto-detects CI via TF_BUILD, so this is belt-and- |
| 83 | + # suspenders for self-hosted agents that don't set it. |
| 84 | + ADOQR_NO_OPEN: '1' |
| 85 | + inputs: |
| 86 | + azureSubscription: $(azureServiceConnection) |
| 87 | + scriptType: pscore |
| 88 | + scriptLocation: inlineScript |
| 89 | + inlineScript: | |
| 90 | + $ErrorActionPreference = 'Stop' |
| 91 | +
|
| 92 | + # Ensure the Azure DevOps CLI extension is present (adoqr also installs |
| 93 | + # it automatically, but doing it here keeps the assessment output clean). |
| 94 | + az extension add --name azure-devops --only-show-errors --output none 2>$null |
| 95 | +
|
| 96 | + # Build argument list. Splatting keeps optional args (projects) clean. |
| 97 | + $adoqrArgs = @{ |
| 98 | + Organization = '${{ parameters.organization }}' |
| 99 | + MaxParallel = ${{ parameters.maxParallel }} |
| 100 | + OutputFormat = '${{ parameters.outputFormat }}' |
| 101 | + OutputPath = '$(Build.ArtifactStagingDirectory)' |
| 102 | + } |
| 103 | +
|
| 104 | + $projects = '${{ parameters.projects }}'.Trim() |
| 105 | + if ($projects) { |
| 106 | + $adoqrArgs.Project = $projects -split '\s+' |
| 107 | + } |
| 108 | +
|
| 109 | + ./invoke-adoqr.ps1 @adoqrArgs |
| 110 | +
|
| 111 | + - task: PublishPipelineArtifact@1 |
| 112 | + displayName: Publish assessment reports |
| 113 | + condition: always() |
| 114 | + inputs: |
| 115 | + targetPath: $(Build.ArtifactStagingDirectory) |
| 116 | + artifactName: adoqr-assessment |
0 commit comments