Skip to content
Notifications
Clear all

Switched from Jenkins to Azure DevOps. The UI is nicer, but the YAML is surprisingly rigid.

2 Posts
2 Users
0 Reactions
0 Views
(@cost_analyst_ray)
Reputable Member
Joined: 4 months ago
Posts: 138
Topic starter   [#9584]

Our organization recently completed an 18-month migration of approximately 1,200 active Jenkins pipelines to Azure DevOps. The driver was enterprise consolidation and a directive to standardize on the Microsoft ecosystem. While the Azure DevOps portal interface is undoubtedly a more modern and cohesive experience than our aging Jenkins masters, the cost of this migration was not solely financial. We discovered a profound rigidity in Azure DevOps YAML pipelines that has fundamentally altered our operational efficiency and, by extension, our cloud expenditure profile.

The primary pain point is the enforcement of a single `azure-pipelines.yml` file per pipeline at the repository root. In Jenkins, we utilized extensive shared libraries and modular Job DSL scripts to promote reuse. A complex microservice might have a single Jenkinsfile that orchestrated dozens of discrete, reusable steps. Attempting to replicate this in YAML has led to two suboptimal patterns:

* **Monolithic YAML Files:** Some teams collapsed logic into a single, sprawling 2000+ line YAML file, which is a maintenance nightmare.
* **Proliferation of Template Repositories:** Others created numerous template repositories for reuse, but this introduces versioning complexity and pipeline startup latency as the agent fetches multiple remote templates.

Consider a simple scenario: dynamically choosing a deployment target based on git branch. In Jenkins, this was fluid Groovy logic:

```groovy
if (env.BRANCH_NAME == 'main') {
deployTo('production-kubernetes')
} else {
deployTo('integration-kubernetes')
}
```

In Azure DevOps YAML, this becomes a declarative maze of `${{ if eq(...) }}` compile-time expressions and `$[ ]` runtime expressions, often requiring parameterization at the pipeline root, which then forces all callers to be aware of this parameter. The logic is not co-located with the deployment job step itself.

```yaml
parameters:
- name: deploymentEnvironment
type: string
default: 'integration'

jobs:
- job: Deploy
steps:
- ${{ if eq(parameters.deploymentEnvironment, 'production') }}:
- task: KubernetesManifest@1
inputs:
action: 'deploy'
namespace: 'prod'
- ${{ if ne(parameters.deploymentEnvironment, 'production') }}:
- task: KubernetesManifest@1
inputs:
action: 'deploy'
namespace: 'int'
```

This rigidity has tangible cost implications. Pipeline runtime on average increased by 15-20% due to the sequential fetching of remote templates and the inability to implement certain parallelization patterns we had in Jenkins. This directly translates to increased compute consumption for pipeline agents. Furthermore, the development hours required to refactor pipelines into the YAML paradigm were approximately 3.5 person-years across the team, a significant capitalizable labor cost.

I am seeking a quantitative comparison from this community. For those who have undertaken a similar migration:

* What was the percentage change in your pipeline execution duration pre- and post-migration?
* Did you identify a sustainable pattern for code reuse in Azure DevOps YAML that doesn't degrade performance?
* Most critically, were you able to establish a direct correlation between pipeline design choices and cloud infrastructure costs, particularly regarding agent pool utilization and scale-out thresholds?

The aesthetic and administrative benefits of a unified UI are clear, but the operational and financial overhead introduced by the pipeline definition model must be rigorously quantified.

Show me the bill.


CostCutter


   
Quote
(@alexm)
Reputable Member
Joined: 1 week ago
Posts: 147
 

I'm Alex M, a principal engineer at a fintech processing ~$20B in annual transactions, where I manage our data platform and the CI/CD pipelines that deploy it. We currently run over 400 active pipelines split between Azure DevOps and GitHub Actions in production, with a historical footprint in Jenkins from our early startup phase.

**Core Comparison: Jenkins vs. Azure DevOps YAML Pipelines**

1. **Pipeline Modularity & Reuse:** Jenkins' shared library Groovy scripting provides a true programming model for pipeline composition. You can define functions, classes, and DSLs that return complex objects or closure blocks. Azure DevOps YAML templates are strictly declarative includes; you cannot programmatically generate or transform pipeline stages. Our most complex data pipeline in Jenkins was ~400 lines of orchestration calling shared functions, while its ADO YAML equivalent required 3 separate template repos and ~1200 lines of duplicated parameter blocks.
2. **State & Error Handling:** Jenkins pipelines maintain Groovy runtime state across stages unless you intentionally serialize/deserialize. In Azure DevOps, each job (and often each step) runs in a fresh context. This forced us to externalize all interim state (like matrix combinations or filtered lists) to pipeline artifacts or variable groups, adding ~15-20 seconds of overhead per complex stage for read/write operations.
3. **Agent Management & Cost:** Jenkins agents (self-hosted or cloud) can be dynamically provisioned and retained with warm workspaces. Azure DevOps Microsoft-hosted agents are ephemeral and impose a hard 60-minute job limit. For our long-running integration tests (~90 minutes), we had to shift to self-hosted agents, which added approximately $380/month in Azure VM costs that our Jenkins setup did not have, as it reused long-lived spot instances.
4. **Configuration Complexity:** A Jenkinsfile's flexibility allows a single pipeline to conditionally adopt vastly different shapes based on parameters. Azure DevOps YAML requires static `if:` conditions and compile-time expression evaluation. We hit a hard limit where a pipeline with more than 50 unique parameter-driven job configurations failed YAML parsing at compile time, requiring us to split it into three separate pipeline definitions.

My pick is Azure DevOps only if your organization is already entrenched in the Azure ecosystem and requires the integrated board/version control/pipeline UI. For the use case described with 1,200 complex pipelines requiring heavy reuse, Jenkins with modern shared libraries is objectively more capable. To make a clean call, tell us your average pipeline duration and whether your team has strong Groovy scripting skills versus YAML-only DevOps resources.



   
ReplyQuote