Skip to content
BETAGuardrails are in beta. The library, the configuration format and the CLI command can still change.

Guardrails / Collectors

Azure Pipelines definitions

The Azure Pipelines YAML the repository carries, read as Azure writes it: what starts a run, the stages and jobs it declares, the pool each job lands on and how long it may run, and every task a step reaches for with the version it asks for, alongside the macro, template and runtime expressions a script interpolates. Names and shapes only, never a secret, an input value or a variable value.

Facts keyazure
Versionv1
Scriptazure.py
Timeout60 seconds

Inputs

InputDescriptionDefaultEnvironment
pipelinesComma separated globs matched against every file in the working directory and against bare file names, naming the pipeline definitions to read. Azure fixes no location for them, so a repository that names its own must say so here; anything matched that is not YAML is still left out.azure-pipelines*.yml,azure-pipelines*.yamlGUARDRAIL_INPUT_PIPELINES

A guardrail that declares an input of the same name passes it through, so the guardrail's configuration in buildnote.json is what decides these values.

A guardrail asks for these facts by name, and reads them back the same way:

json
{
  "collect": ["azure"]
}
python
azure = guardrail.facts("azure")

Facts

The document azure collects. A path carrying [] is an entry of the list before it, and one carrying [path] is a key of the object before it.

FactMeaning
sourcereport when a pipeline definition was read, none when there was none.
reasonWhy nothing was read, present only when source is none.
reportsEvery definition that was read, in path order.
reports[].pathPath of the definition, relative to the directory the CLI runs in.
reports[].modifiedWhen it was last written, ISO 8601.
reports[].formatAlways azure.
pipelinesThe pipelines themselves, one entry per file that was read.
pipelines[].pathPath of the file, relative to the directory the CLI runs in.
pipelines[].nameThe name the pipeline gives its runs, exactly as written, or null.
pipelines[].triggersWhich of trigger, pr, schedules and resources the file declares. A file declaring none of them runs only when somebody starts it.
pipelines[].variablesNames of the variables the pipeline declares, whether written as a mapping, as name entries, or as a group or template it pulls in. Names only, never values.
pipelines[].stagesThe stages the file declares, in the order it declares them. Empty for a pipeline written as jobs or steps alone.
pipelines[].jobsEvery job in the file, whatever it is nested under: the jobs of each stage in order, then the top level jobs, and a pipeline written as bare steps as the one job it is.
pipelines[].jobs[].idThe job or deployment key, or the stage's name for a stage that declares neither, or null.
pipelines[].jobs[].displayNameDisplay name the job gives itself, or null.
pipelines[].jobs[].stageThe stage the job sits in, or null for a job declared outside one.
pipelines[].jobs[].poolThe pool the job asks for, exactly as written: a name, or a mapping naming a vmImage or an agent pool.
pipelines[].jobs[].hostedImageThe vmImage the job asks for, or null when it names none.
pipelines[].jobs[].selfHostedfalse when the job names a vmImage, which is one of Microsoft's hosted agents, and null when it names a pool Azure does not say is hosted or names no pool at all.
pipelines[].jobs[].timeoutInMinutesThe declared timeoutInMinutes, exactly as written, or null when the job declares none and takes the organisation's own limit.
pipelines[].jobs[].environmentThe environment a deployment job targets, exactly as written, or null. An environment is what carries an approval check.
pipelines[].jobs[].dependsOnJobs this one waits for, by name.
pipelines[].jobs[].conditionThe raw condition guarding the job, or null.
pipelines[].jobs[].templateThe template this job comes from instead of declaring steps, exactly as written, or null.
pipelines[].jobs[].stepsThe steps the job declares, in order.
pipelines[].jobs[].steps[].displayNameDisplay name of the step, or null.
pipelines[].jobs[].steps[].taskThe task the step runs, exactly as written with its version, or null for a step that only runs a script.
pipelines[].jobs[].steps[].taskNameThe part of task before the @, or null.
pipelines[].jobs[].steps[].taskVersionWhat follows the @ in task, which for an Azure task is a major version rather than a revision anybody can pin further, or null.
pipelines[].jobs[].steps[].templateThe template the step pulls in instead of running something itself, exactly as written, or null.
pipelines[].jobs[].steps[].scriptThe script body the step runs, whether written as script, bash, pwsh or powershell, truncated to 2000 characters, or null.
pipelines[].jobs[].steps[].shellThe shell keyword the body was written under, bash, pwsh or powershell, or null for a plain script step taking the agent's default.
pipelines[].jobs[].steps[].inputKeysNames of the inputs the step passes to the task. Names only, never values.
pipelines[].jobs[].steps[].macrosEvery $( ) macro appearing in the script body, read from the whole body before it was truncated. A macro is substituted into the script before it runs, which is the script injection surface.
pipelines[].jobs[].steps[].templateExpressionsEvery ${{ }} template expression appearing in the script body, which Azure resolves when the pipeline is compiled.
pipelines[].jobs[].steps[].runtimeExpressionsEvery $[ ] runtime expression appearing in the script body, which Azure resolves when the run starts.
stagesEvery stage declared across the files that were read.
counts.pipelinesFiles that were read.
counts.jobsJobs across every file.
counts.stepsSteps across every job.
unparsedFiles that matched but were not read, because the YAML they are written in is outside the subset the collector can represent. A file here is not a file with nothing in it: nothing was read from it and no verdict should be drawn about it.
unparsed[].pathPath of the file that was not read.
unparsed[].reasonThe construct that could not be represented, and the line it is on.

A collector that cannot finish prints what it had along with an incomplete key saying why, so the facts below the point it stopped are absent. A check that cares reads incomplete before the rest.

Example facts

The example facts collected by azure collector:

json
{
  "source": "report",
  "reports": [
    {
      "path": "azure-pipelines.yml",
      "modified": "2026-03-04T10:15:00Z",
      "format": "azure"
    }
  ],
  "pipelines": [
    {
      "path": "azure-pipelines.yml",
      "name": "build",
      "triggers": [
        "trigger",
        "pr"
      ],
      "variables": [
        "gradleOptions"
      ],
      "stages": [
        "build"
      ],
      "jobs": [
        {
          "id": "check",
          "displayName": "Build and test",
          "stage": "build",
          "pool": {
            "vmImage": "ubuntu-latest"
          },
          "hostedImage": "ubuntu-latest",
          "selfHosted": false,
          "timeoutInMinutes": 15,
          "environment": null,
          "dependsOn": [],
          "condition": null,
          "template": null,
          "steps": [
            {
              "displayName": null,
              "task": "JavaToolInstaller@0",
              "taskName": "JavaToolInstaller",
              "taskVersion": "0",
              "template": null,
              "script": null,
              "shell": null,
              "inputKeys": [
                "versionSpec",
                "jdkArchitectureOption",
                "jdkSourceOption"
              ],
              "macros": [],
              "templateExpressions": [],
              "runtimeExpressions": []
            },
            {
              "displayName": "Build",
              "task": null,
              "taskName": null,
              "taskVersion": null,
              "template": null,
              "script": "./gradlew check",
              "shell": "bash",
              "inputKeys": [],
              "macros": [],
              "templateExpressions": [],
              "runtimeExpressions": []
            }
          ]
        }
      ]
    }
  ],
  "stages": [
    "build"
  ],
  "counts": {
    "pipelines": 1,
    "jobs": 1,
    "steps": 2
  },
  "unparsed": []
}

Collected for

GuardrailCategoryInputs
azure/job-timeout-setazurepipelines

All collectors

Buildnote Limited
Registered in England and Wales, Reg: 16140412