Skip to content

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 has no fixed location for them, so if your repository keeps them elsewhere, name them here. Anything matched that is not YAML is still left out.azure-pipelines*.yml,azure-pipelines*.yamlGUARDRAIL_INPUT_PIPELINES

When a guardrail declares an input with the same name, it passes its value through. That means you set these values in the guardrail's configuration in buildnote.json.

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

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

Facts ​

These are the fields of the document azure collects. In a path, [] means each entry of the list before it, and [path] means 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 their YAML uses something outside the subset the collector can represent. A file listed here is not an empty file: nothing was read from it, so draw no verdict 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.

If a collector can't finish, it prints what it gathered so far along with an incomplete key that says why. Facts after the point where it stopped are missing, so a check that depends on them should read incomplete first.

Example facts ​

Here are the facts the azure collector gathers from an example project:

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