# Azure DevOps

Integrate [bricks CLI](/docs/bricks-cli/bricks-cli.md) into your Azure DevOps pipelines to publish [blueprints](/docs/orchestration/packages/blueprints-overview/creating-blueprints.md), plan infrastructure changes on PRs, and deploy across [collections](/docs/orchestration/collections.md) with approval gates.

***

### Setup

1. Create a **Variable Group** named `bluebricks-credentials` with a secret `BRICKS_API_KEY` (see [Long-Lived Tokens](/docs/bricks-cli/authentication/authenticate-using-long-lived-tokens.md))
2. Create **Environments** (`bluebricks-dev`, `bluebricks-staging`, `bluebricks-production`) with approval checks on staging and production

Install the CLI in any pipeline job:

```yaml
- script: |
    /bin/bash -c "$(curl -fsSL https://brickscli.s3.eu-west-1.amazonaws.com/releases/latest/install.sh)"
  displayName: 'Install bricks CLI'
```

The CLI reads configuration from environment variables prefixed with `BRICKS_`. Set `BRICKS_NON_INTERACTIVE` and `BRICKS_API_KEY` at the pipeline level so every step picks them up automatically. Since `BRICKS_API_KEY` is a secret, it must also be mapped via `env:` on each step.

#### CI/CD Flags

See [`bricks install`](/docs/bricks-cli/cli-reference/bricks_install.md) and [`bricks blueprint publish`](/docs/bricks-cli/cli-reference/bricks_blueprint/bricks_blueprint_publish.md) for full reference.

| Flag / Env Var           | Purpose                            |
| ------------------------ | ---------------------------------- |
| `BRICKS_API_KEY`         | Authenticate without browser login |
| `BRICKS_NON_INTERACTIVE` | Suppress interactive prompts       |
| `--plan-only`            | Preview changes without applying   |
| `--yes`                  | Auto-approve and apply             |

***

### Deploy Pipeline

Plans on PRs, then deploys through dev (automatic), staging (approval), and production (approval). Uses `${{ each }}` to loop over environments so the deploy logic is defined once:

<figure><img src="/files/OjIqvSStnYT80AEaTr1Q" alt=""><figcaption><p>Multi-environment deployment pipeline with plan, dev, staging, and production stages</p></figcaption></figure>

{% hint style="info" %}
YAML `pr:` triggers work only with GitHub and Bitbucket Cloud repositories. If your code is in **Azure Repos Git**, configure a [branch policy for build validation](https://learn.microsoft.com/en-us/azure/devops/repos/git/branch-policies#build-validation) instead to trigger plans on pull requests.
{% endhint %}

```yaml
parameters:
  - name: environments
    type: object
    default:
      - name: dev
        file: environments/dev/deploy.yaml
        dependsOn: Plan
        condition: "and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))"
      - name: staging
        file: environments/staging/deploy.yaml
        dependsOn: Deploy_dev
        condition: succeeded()
      - name: production
        file: environments/production/deploy.yaml
        dependsOn: Deploy_staging
        condition: succeeded()

trigger:
  branches:
    include:
      - main
  paths:
    include:
      - environments/**

# PR triggers work with GitHub/Bitbucket repos.
# For Azure Repos Git, use branch policy build validation instead.
pr:
  branches:
    include:
      - main
  paths:
    include:
      - environments/**

variables:
  - group: bluebricks-credentials
  - name: BRICKS_NON_INTERACTIVE
    value: true

stages:
  - stage: Plan
    displayName: 'Plan deployments'
    jobs:
      - job: PlanAll
        pool:
          vmImage: 'ubuntu-latest'
        steps:
          - checkout: self
          - script: |
              /bin/bash -c "$(curl -fsSL https://brickscli.s3.eu-west-1.amazonaws.com/releases/latest/install.sh)"
            displayName: 'Install bricks CLI'
          - ${{ each env in parameters.environments }}:
            - script: |
                bricks install \
                  --file ${{ env.file }} \
                  --plan-only
              displayName: 'Plan ${{ env.name }}'
              env:
                BRICKS_API_KEY: $(BRICKS_API_KEY)

  - ${{ each env in parameters.environments }}:
    - stage: Deploy_${{ env.name }}
      displayName: 'Deploy to ${{ env.name }}'
      dependsOn: ${{ env.dependsOn }}
      condition: ${{ env.condition }}
      jobs:
        - deployment: Deploy_${{ env.name }}
          pool:
            vmImage: 'ubuntu-latest'
          environment: bluebricks-${{ env.name }}
          strategy:
            runOnce:
              deploy:
                steps:
                  - checkout: self
                  - script: |
                      /bin/bash -c "$(curl -fsSL https://brickscli.s3.eu-west-1.amazonaws.com/releases/latest/install.sh)"
                    displayName: 'Install bricks CLI'
                  - script: |
                      bricks install \
                        --file ${{ env.file }} \
                        --yes
                    displayName: 'Deploy ${{ env.name }}'
                    env:
                      BRICKS_API_KEY: $(BRICKS_API_KEY)
```

***

### Publish Pipeline

Publishes blueprints to the registry when changes merge to `main`:

```yaml
trigger:
  branches:
    include:
      - main
  paths:
    include:
      - blueprints/**

variables:
  - group: bluebricks-credentials
  - name: BRICKS_NON_INTERACTIVE
    value: true

stages:
  - stage: Publish
    displayName: 'Publish blueprints'
    condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')
    jobs:
      - job: Publish
        pool:
          vmImage: 'ubuntu-latest'
        steps:
          - checkout: self

          - script: |
              /bin/bash -c "$(curl -fsSL https://brickscli.s3.eu-west-1.amazonaws.com/releases/latest/install.sh)"
            displayName: 'Install bricks CLI'

          - script: |
              bricks blueprint publish \
                --src blueprints/web-app
            displayName: 'Publish web-app blueprint'
            env:
              BRICKS_API_KEY: $(BRICKS_API_KEY)
```

***

### Deployment Manifest

Each environment has a `deploy.yaml`:

```yaml
apiVersion: bricks/v1
kind: Deployment

metadata:
  name: web-app-dev

spec:
  blueprint: web_app
  version: "0.3.0"
  collection: dev
  props:
    environment: "dev"
    instance_type: "t3.medium"
    min_replicas: 2
    max_replicas: 4
```

See [Deployment Manifest File Format](/docs/orchestration/runs/deployment-manifest-file-format.md) for the full reference. For blueprint definitions (`bricks.yaml`), see [Creating Blueprints](/docs/orchestration/packages/blueprints-overview/creating-blueprints.md).

***

### Repository Structure

```
.
├── azure-pipelines.yml               # Deploy pipeline
├── azure-pipelines-publish.yml       # Publish pipeline
├── environments/
│   ├── dev/deploy.yaml
│   ├── staging/deploy.yaml
│   └── production/deploy.yaml
├── blueprints/
│   └── web-app/bricks.yaml
└── README.md
```

***

### Troubleshooting

| Issue                     | Solution                                                                                         |
| ------------------------- | ------------------------------------------------------------------------------------------------ |
| `authentication required` | Verify `BRICKS_API_KEY` is set and linked to the pipeline                                        |
| Pipeline hangs on publish | Bump the version in `bricks.yaml` before merging - the CLI prompts when a version already exists |
| `INVALID_PACKAGE_NAME`    | Use underscores, not hyphens (e.g., `aws_vpc` not `aws-vpc`)                                     |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://bluebricks.co/docs/integrations/azure-devops.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
