# Azure Devops Pipelines

> >

- **Type:** Skill
- **Install:** `agentstack add skill-iambrzdev-enterprise-agent-skills-azure-devops-pipelines`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [iamBrzDev](https://agentstack.voostack.com/s/iambrzdev)
- **Installs:** 0
- **Category:** [Cloud & Infrastructure](https://agentstack.voostack.com/c/cloud-infrastructure)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [iamBrzDev](https://github.com/iamBrzDev)
- **Source:** https://github.com/iamBrzDev/enterprise-agent-skills/tree/main/skills/azure-devops-pipelines

## Install

```sh
agentstack add skill-iambrzdev-enterprise-agent-skills-azure-devops-pipelines
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

## When to activate

- Creating a new Azure DevOps pipeline from scratch
- Migrating a Classic (UI) pipeline to YAML
- "How do I speed up my pipeline?" in an Azure DevOps context
- Adding caching for NuGet packages, Composer vendor/, or node_modules
- Configuring secrets — any mention of Key Vault, service connections, or tokens in YAML
- Setting up multi-stage pipelines (build → test → deploy)
- Parallelizing tests with strategy matrix or test sharding
- Adding approval gates or branch policies before production deploy
- Any mention of DORA metrics, lead time, change failure rate in CI/CD context

## Rules — Non-negotiable

1. **Classic pipelines are legacy. Always use YAML.** Every pipeline must be a
   versioned `.yml` file in the repository. No exceptions.

2. **Secrets never go in YAML files.** Use Azure Key Vault + Managed Identity
   or Variable Groups linked to Key Vault. Never hardcode tokens, passwords,
   or connection strings — not even as pipeline variables in plain text.

3. **Stages must have explicit dependencies.** Use `dependsOn` to enforce
   execution order. Deploy never runs without a passing Test stage.

4. **Cache dependencies, always.** A pipeline without caching is wasting
   40–60% of its build time on redundant downloads.

5. **Least privilege on service connections.** A build pipeline must not have
   write access to production resources. Scope permissions per environment.

## Pipeline Structure

Always enforce this multi-stage structure. Adapt stages to the project but
never skip the dependency chain:

```
Trigger → Build → Test (parallel) → Security Scan → Deploy (gated)
```

### Canonical YAML skeleton

```yaml
trigger:
  branches:
    include:
      - main
      - develop

pr:
  branches:
    include:
      - main

variables:
  - group: kv-enterprise-secrets   # Linked to Azure Key Vault
  - name: buildConfiguration
    value: Release

stages:
  - stage: Build
    displayName: 'Build'
    jobs:
      - job: BuildJob
        pool:
          vmImage: ubuntu-latest
        steps:
          - task: Cache@2                    # Cache NuGet / Composer here
            ...
          - script: echo "Build steps here"

  - stage: Test
    displayName: 'Test'
    dependsOn: Build
    jobs:
      - job: UnitTests
        ...
      - job: IntegrationTests
        ...

  - stage: SecurityScan
    displayName: 'Security Scan'
    dependsOn: Build

  - stage: Deploy
    displayName: 'Deploy to Production'
    dependsOn:
      - Test
      - SecurityScan
    condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
    jobs:
      - deployment: DeployProd
        environment: production          # Environments enable approval gates
        ...
```

## Caching — .NET (NuGet)

```yaml
- task: Cache@2
  inputs:
    key: 'nuget | "$(Agent.OS)" | **/packages.lock.json,!**/bin/**,!**/obj/**'
    restoreKeys: |
      nuget | "$(Agent.OS)"
    path: $(NUGET_PACKAGES)
  displayName: 'Cache NuGet packages'

- task: DotNetCoreCLI@2
  inputs:
    command: restore
    projects: '**/*.csproj'
    feedsToUse: select
```

## Caching — Laravel (Composer + NPM)

```yaml
- task: Cache@2
  inputs:
    key: 'composer | "$(Agent.OS)" | composer.lock'
    restoreKeys: composer | "$(Agent.OS)"
    path: vendor
  displayName: 'Cache Composer dependencies'

- task: Cache@2
  inputs:
    key: 'npm | "$(Agent.OS)" | package-lock.json'
    restoreKeys: npm | "$(Agent.OS)"
    path: node_modules
  displayName: 'Cache NPM dependencies'

- script: composer install --no-interaction --prefer-dist --optimize-autoloader
  displayName: 'Install Composer dependencies'
```

## Parallelization — Test Matrix

Reduce a 50-minute test suite to ~10 minutes by splitting across agents:

```yaml
- stage: Test
  jobs:
    - job: TestMatrix
      strategy:
        matrix:
          UnitTests:
            testCategory: 'Unit'
          IntegrationTests:
            testCategory: 'Integration'
          ContractTests:
            testCategory: 'Contract'
        maxParallel: 3
      steps:
        - script: dotnet test --filter "Category=$(testCategory)"
          displayName: 'Run $(testCategory) tests'
```

## Secret Management — Azure Key Vault

```yaml
# ✅ CORRECT — reference secrets from Key Vault via Variable Group
variables:
  - group: kv-production-secrets   # Variable Group linked to Key Vault

steps:
  - script: echo "Connection string is $(SqlConnectionString)"
    # $(SqlConnectionString) is injected at runtime, never stored in YAML

# ❌ WRONG — never do this
variables:
  SqlConnectionString: 'Server=prod-db;Password=SuperSecret123'
```

### Setting up Workload Identity Federation (preferred over service principals)

```yaml
- task: AzureCLI@2
  inputs:
    azureSubscription: 'workload-identity-connection'  # Federated credential
    scriptType: bash
    scriptLocation: inlineScript
    inlineScript: |
      az keyvault secret show --name SqlPassword --vault-name kv-enterprise
```

## Branch Policies and Approval Gates

Configure in Azure DevOps UI under **Environments → Approvals and checks**,
or enforce via pipeline:

```yaml
- stage: Deploy
  jobs:
    - deployment: DeployProduction
      environment: production           # Environment must have approval gate configured
      strategy:
        runOnce:
          deploy:
            steps:
              - script: echo "Deploying after approval"
```

Branch policies to always enable on `main`:
- Minimum 1 reviewer approval
- Build validation (pipeline must pass)
- Comment resolution required
- No direct pushes

## Templates — Reusable Steps

Centralize common steps in a `templates/` directory to avoid duplication:

```yaml
# templates/dotnet-build.yml
parameters:
  - name: configuration
    type: string
    default: Release

steps:
  - task: DotNetCoreCLI@2
    inputs:
      command: build
      arguments: '--configuration ${{ parameters.configuration }}'

# In main pipeline — consume the template
steps:
  - template: templates/dotnet-build.yml
    parameters:
      configuration: $(buildConfiguration)
```

## Common mistakes

- ❌ Storing secrets as plain pipeline variables visible in the UI
- ✅ Link Variable Groups to Azure Key Vault — secrets are never visible in plain text

- ❌ All stages in a single job with sequential steps — slow and fragile
- ✅ Separate jobs per concern, use `dependsOn` and parallelization

- ❌ Deploy stage with no environment — bypasses approval gate capability
- ✅ Always use `deployment` job type with `environment:` to enable gates

- ❌ Giving service connection Contributor access to the entire subscription
- ✅ Scope service connections to specific resource groups per environment

## Definition of Done

A pipeline built with this skill is complete only when:

- [ ] All stages are YAML, version-controlled, and reviewed via PR
- [ ] No secrets, tokens, or passwords exist anywhere in `.yml` files
- [ ] Caching is configured for package managers (NuGet, Composer, NPM)
- [ ] Test stage runs before Deploy — enforced with `dependsOn`
- [ ] Production deploy requires manual approval via Environment gate
- [ ] Service connection uses Workload Identity or scoped permissions
- [ ] Pipeline passes on a clean agent (no reliance on local state)

## Reference files

Load on demand:
- `references/variable-groups-keyvault.md` — step-by-step Key Vault integration
- `references/test-sharding-dotnet.md` — advanced test parallelization for large .NET suites
- `references/laravel-full-pipeline.md` — complete Laravel pipeline with deploy to App Service

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [iamBrzDev](https://github.com/iamBrzDev)
- **Source:** [iamBrzDev/enterprise-agent-skills](https://github.com/iamBrzDev/enterprise-agent-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-iambrzdev-enterprise-agent-skills-azure-devops-pipelines
- Seller: https://agentstack.voostack.com/s/iambrzdev
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
