# Azure DevOps

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

***

### Setup

1. Create a **Variable Group** named `bluebricks-credentials` with a secret `BRICKS_API_KEY` (see [Long-Lived Tokens](https://bluebricks.co/docs/bricks-cli/authentication/authenticate-using-long-lived-tokens))
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`](https://bluebricks.co/docs/bricks-cli/cli-reference/bricks_install) and [`bricks blueprint publish`](https://bluebricks.co/docs/bricks-cli/cli-reference/bricks_blueprint/bricks_blueprint_publish) 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="https://454695563-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FL1aVoJ67VgVl8Uv83TuE%2Fuploads%2Fgit-blob-2e3b71dabba8f814d7cf07ee58a99ca8d1a7b3f5%2Fazure-devops-pipeline-stages.png?alt=media" 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](https://bluebricks.co/docs/orchestration/runs/deployment-manifest-file-format) for the full reference. For blueprint definitions (`bricks.yaml`), see [Creating Blueprints](https://bluebricks.co/docs/orchestration/packages/blueprints-overview/creating-blueprints).

***

### 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`)                                     |
