What you can export from Azure Pipelines, and what you must rebuild
If a renewal, a licensing change, a residency requirement or lock-in concern is pushing you to leave Azure Pipelines, start by sorting your estate into three groups. YAML pipeline definitions already sit in your repository, so they move with the code. Classic pipeline definitions, run history, logs and artifacts do not travel automatically and need a deliberate export. Secret variable values and service connection credentials cannot be read back, so they must be re-created on the new platform.
The YAML files are the easy part. Templates, variable group references and triggers are usually stored alongside the code, so a copy of the repository carries most of the pipeline logic. Classic release definitions and classic build definitions are different: they live in Azure DevOps and are exported through its REST API as JSON, which you then have to translate by hand into the target format. Run history and logs are kept by the service for a retention period set in your organization. Build artifacts and test results need to be downloaded before that window closes, because they will not be available once you decommission the organization.
Confirm the exact export limits, retention windows and API coverage in Microsoft's Azure DevOps documentation for your organization and version, since these depend on your configuration and can change. Then inventory secret variables, variable groups and service connections in a spreadsheet with an owner for each. Plan to rotate those credentials at the new platform, not to copy them, and check whether the same secret is shared with other systems. This inventory is the item most likely to delay cutover, so start it first.
Which Azure Pipelines data exports, and through which path
This table lists each category of Azure Pipelines data, the path to export it, the format you receive and what to confirm before you start. Read it as a checklist: items already stored in Git need little work, while run history, artifacts and classic definitions need an export step with a deadline set by your retention settings.
| Data type | Export method | Format | What to confirm |
|---|---|---|---|
| YAML pipeline definitions | Already in the Git repository, so no export is needed beyond cloning the repo | YAML files, usually azure-pipelines.yml or referenced pipeline files | Confirm that every pipeline is YAML and that no definition exists only in the Azure DevOps web interface |
| Classic pipeline and release definitions | Azure DevOps REST API, retrieved per definition | JSON | Check the Azure DevOps REST API reference for the endpoints and any paging rules, and save each definition before the service is switched off |
| Run history and logs | REST API or the web interface, exported run by run | JSON for run metadata, plain text for logs | Confirm how far back your organization retains runs and logs, and plan the export window against that retention setting |
| Build artifacts | Download from each completed run before retention ends | Original file types, such as packages, binaries and test results | Confirm the artifact retention settings for your organization and project, and whether any pipeline overrides them |
| Templates and variable group names | REST API for variable group metadata, or template files in the repository | YAML template files and JSON or plain text name lists | Confirm that variable group names and template references are recorded, since secret values cannot be read back |
Why secret values and service connection credentials cannot leave with the pipelines
Pipeline definitions can move through the repository, but the values that make them work cannot be read back out of Azure Pipelines. The cards below cover each category that stays behind, what the export path returns instead, and what your team must record and re-create before the first run on the new platform.
Secret variables
Variables marked as secret in pipeline variable groups or pipeline settings return no value through the REST API or the web interface after they are saved. Export the variable names, scopes, owners and the system each value came from. Then re-enter every value from its system of record into Jenkins credentials or the Woodpecker secret store, and confirm each consumer step still reads the expected name.
Service connection credentials
Service connections hold the credentials Azure Pipelines uses to reach cloud subscriptions, container registries and other endpoints. Their secret material cannot be exported, so the connection object itself does not move. Plan to issue new credentials or tokens for the target platform with the least privilege each job needs, and retire the old service principals only after the first successful deployment on the new platform.
Environment protections and approvals
Approval gates, branch controls and checks attached to environments are configuration, and the export path does not reproduce them as portable definitions. Record each approver group, the environment it guards and the branch rule that applies. Then rebuild approvals in the target tool as explicit pipeline stages or pull request rules, and test that an unapproved run stops before the deployment step.
Agent pool registrations
Self-hosted agents register to a pool with a token that is shown once and cannot be read back. Inventory each pool, the machines behind it, installed tools and the demands each pipeline sets. Then register new agents or Kubernetes pod templates on the target platform and remove the old registrations, so that a stale agent cannot pick up jobs after cutover.
Access tied to Azure identities
Permissions in Azure Pipelines often resolve to Microsoft Entra ID groups, managed identities and project roles, and these identities do not carry over to another CI system. List which users, groups and service identities can view, edit, approve or run each pipeline. Then map those rights to groups on the target platform and confirm that no pipeline depends on a managed identity that will be deleted.
Vendor-wide secret handling pattern
Other hosted CI services follow the same pattern: GitHub's REST API returns Actions secret names without values, and CircleCI does not show environment variable values after they are set. Treat this as a planning assumption rather than a gap specific to one vendor. Ask your team to confirm the export behavior for your organization's Azure DevOps version, and keep a secured copy of the names and owners as evidence for the migration record.
The export sequence, in order, with a check at each step
This sequence produces a dated, offline archive of everything Azure Pipelines holds for your projects, with a verification at each stage so you know what was captured and what must be rebuilt by hand. Run it before any cutover, and keep the archive until the new system has produced its first successful builds.
Freeze the inventory of projects and pipelines
Start by listing every Azure DevOps organization, project, pipeline, repository and variable group in scope, using the Azure DevOps REST API or the portal, and save the list as a dated inventory file. Name an owner for the inventory and agree with the teams that pipeline changes pause during export. The step is done when the inventory file exists and its pipeline and repository counts match what the portal shows for each project. Keep this file, since every later check compares against it.
Confirm all YAML is committed to the default branch
Check that each YAML pipeline definition lives in a Git repository on the branch the pipeline builds from, and that templates and referenced files are committed alongside it. Clone each repository into the archive and compare the YAML files against the pipeline list in the inventory, flagging any pipeline whose definition exists only in Azure DevOps. The step is done when every YAML pipeline maps to a committed file and the flagged list is empty or assigned to an owner. YAML in the repository is the most portable part of the export.
Export classic definitions and run metadata to files
Use the Azure DevOps REST API to fetch classic build and release definitions as JSON, and export run metadata such as run IDs, triggers, source versions, timestamps and results to files. Save each response under a folder per project, with the API version and export date recorded. Check that the number of definitions and runs in the files matches the counts from the inventory for each project. Classic release definitions may be unavailable in new organizations, so confirm their status with Microsoft before assuming a gap.
Download logs and artifacts before retention ends
Download build logs and published artifacts for the runs you need to keep, starting with the most recent successful runs for each release branch and any runs tied to audits or incidents. Record the run ID, artifact name and checksum for each file so you can verify it later. Confirm your organization's artifact retention settings in Azure DevOps and do this step before the window closes. The step is done when a sample of downloaded artifacts opens correctly and their checksums match the record.
Record secrets and service connections by name and owner
Azure DevOps does not return the values of secret variables or the credentials inside service connections, so the export cannot carry them. Instead, build a register that lists every secret variable, variable group entry and service connection by name, scope, owning team, the system it authenticates to and the person who can re-issue it. Check the register against the inventory and against each pipeline's references so no secret is missed. The step is done when the register is reviewed by the owners and every entry has a named replacement plan.
Store the archive with access controls
Move the completed export into storage your organization controls, such as an object store or file share in your own infrastructure, with access limited to the migration team and restricted by role. Enable versioning or write-once settings where your storage supports them, and record who accessed the archive. Open a sample of the archive from a clean machine, confirm the YAML, JSON, logs and artifacts are readable, and compare the file counts with the inventory. The step is done when that test passes and the access list has been reviewed.
What each target platform changes in the export plan
Jenkins treats the pipeline as a file in the project's repository, so the export starts with the YAML pipelines and classic definitions you want to keep. Most of what Jenkins needs beyond the pipeline files lives on the controller, so the backup plan centers on its home directory.
- Pipelines become Jenkinsfiles: Each Azure YAML pipeline is rewritten as a Jenkinsfile in Declarative or Scripted syntax, built from stages and steps, and committed to source control with the code it builds.
- Configuration and secrets come from `$JENKINS_HOME`: Configuration, plugins and secrets sit on the controller, so back up that directory and restrict access to it, because it holds the credentials your pipelines use.
- Configuration as Code holds settings, not plugins: The Configuration as Code plugin reads YAML from the path set in
CASC_JENKINS_CONFIG(default$JENKINS_HOME/jenkins.yaml), but it does not install plugins, so keep your plugin list in Docker images or the Helm chart. - Task-to-plugin mapping: Map each Azure Pipelines task to a Jenkins plugin and confirm that plugin is maintained, because the community plugin catalog varies in support.
- Secrets are re-entered: Azure secret variables and service connections cannot be read back, so re-create them as Jenkins credentials.
Confirm which plugins your current LTS line bundles and which you must install yourself, and check the Jenkins Pipeline documentation before writing the export spec.
Woodpecker CI reads repositories from a supported forge and runs container-based workflows, so the first question is where your repositories live. Its forge list covers GitHub, Gitea, Forgejo, GitLab, Bitbucket and Bitbucket Datacenter, but it does not list Azure Repos, which changes the order of the work.
- Move Azure Repos code first: If repositories live in Azure Repos, move them to a supported forge before Woodpecker can receive webhooks for them.
- Workflows are YAML under `.woodpecker`: Each pipeline becomes a single
.woodpecker.yamlfile or several files in a.woodpecker/directory, and those files run as parallel workflows withdepends_onordering. - Container images per step: Every step runs its commands in a container image you name, so each Azure agent environment needs an equivalent image, and Windows-heavy builds need a separate plan.
- Plugins and settings blocks: Azure tasks map to Woodpecker plugins, which are container images configured through a settings block. The docs say Drone plugins generally work but may need adjustments.
- Secrets and run history: Azure secret values cannot be read back, so re-create them in Woodpecker, and treat run history as an export task of its own rather than an assumed transfer.
Confirm with the Woodpecker forges overview that your forge is supported in the version you deploy, and note that the docs describe connecting multiple forges to one server as experimental.
GitLab CI/CD is built into a forge, so moving pipelines usually means moving repositories too. Before you plan the export, check whether GitLab's import tooling supports Azure Repos as a source, because that decides whether code and pipeline files can move together or as separate jobs.
- Pipelines become `.gitlab-ci.yml`: Azure stages, jobs and templates map to GitLab pipeline syntax, and reusable templates need an equivalent include structure.
- Runners replace agents: GitLab Runner executes jobs, so Azure agent pools map to runners you register and operate, including the executor type you choose for each.
- Repository import path: If Azure Repos is not a supported import source, the repository move becomes its own project with its own cutover, and the pipeline files follow it.
- Run history and the export archive: If run history does not transfer, keep your export archive as the record of past pipelines, logs and artifacts, and decide how long it is retained.
- Variables and secrets: Azure secret values cannot be read back, so re-enter them as GitLab CI/CD variables and set masking and protection for each one.
Confirm your planned GitLab edition and version, because the GitLab pricing page places advanced CI/CD in Premium, and check the GitLab import and migrate documentation for Azure Repos support before you commit to a path.
What to plan before the Azure DevOps contract or subscription ends
These six items decide whether the export succeeds on schedule. Each one depends on how many pipelines, service connections and repositories the organization runs, and on whether the target is Jenkins, Woodpecker CI or GitLab CI/CD. Set dates from your own inventory rather than from a generic duration.
Set the export window
Start from a complete inventory of pipelines, environments, agent pools and service connections, then work backward from the date access ends. Timelines depend on pipeline count and the target choice, so set dates from your own inventory. Confirm with Microsoft what remains readable after your subscription or contract ends, and export the history while the organization is still active.
Run a parallel period
Keep Azure Pipelines and the new system building the same repositories for a defined period, and compare build outputs, test results and deployment steps. Parallel runs expose missing variables, agent dependencies and Windows-specific tasks before the old system is switched off. Plan for reviewers to sign off on each pipeline before its trigger moves.
Re-issue secrets and service connections
Secret values cannot be read back from Azure Pipelines, so every secret variable and service connection must be re-entered in the new system by its owner. Build a register that lists each secret, its consuming pipeline, the target system and the person who will supply the new value. Rotate credentials at the same time, since the values are being re-created anyway.
Get owner sign-off on the archive
Each pipeline owner should confirm that the exported YAML, run history, logs and artifacts are complete for their projects before the source is closed. Record who approved the archive and on what date. Sign-off also settles which artifacts are still needed for audit, release traceability or rollback, and which can be left behind.
Define archive retention
Decide where the exported archive lives, who can read it, how long it is kept and how it is deleted at the end of its period. Logs and run history can contain secrets printed by mistake, so treat the archive as sensitive data. Confirm the retention requirements of your regulators and internal policy before choosing the storage location.
Decide repositories, boards and identities
Decide whether repositories and work items move with the pipelines or stay in Azure Repos and Azure Boards. Pipelines that point at Azure Repos need a different trigger path than pipelines hosted on GitHub or GitLab. Map each user identity to the new platform's accounts and groups, and confirm how access rights will be granted and removed.
How to verify the export is complete before cutover
Prove completeness by comparing counts and content, not by assuming the export ran. Start from the inventory you built during export and check each item against the archive: every pipeline definition, every run record with its logs, and every artifact you chose to keep. Match the totals, then sample a few runs per pipeline and confirm the log text opens and ends where it should. For YAML, list each azure-pipelines.yml and each template it includes, then confirm every file exists in the archive at the exact commit you exported from. Record that commit hash in the inventory. An export taken from a moving branch can silently miss a file that changed during the work, and the hash is what lets an auditor reproduce the state you exported.
A test build on the new platform from the same commit shows that the pipeline logic moved, and only that. Run the migrated pipeline, whether it is a Jenkinsfile, a Woodpecker workflow or a GitLab CI file, against the same commit and compare outputs with the last Azure Pipelines run: build artifacts, test counts, published versions and deployment targets. Differences in timestamps and agent names are expected. Differences in test results or package hashes need investigation before cutover. Be clear with stakeholders that a green build does not prove a secret was carried over. Secret values cannot be read back from Azure Pipelines, so each secret listed in the inventory must be re-created, given a new value and assigned a named owner who can rotate it. Check that every secret has an owner entry, and that a deployment step fails visibly when a secret is missing rather than succeeding with an empty value.
Have someone other than the exporter verify the archive. The person who produced the export is the least suitable person to certify it. Ask a second engineer to recompute checksums for the archived files, confirm the inventory counts match, and open a sample of the archived logs and YAML without the original tooling. Confirm the retention decision for the archive with your records and compliance owners, since the export is now the only copy of some run history. Keep the verification record, the commit hashes and the reviewer's sign-off together, so the cutover decision can be traced later.
Questions buyers ask before exporting Azure Pipelines
How much effort does exporting Azure Pipelines take?
The effort depends mainly on what you have built up in Azure Pipelines and how much of it is already in Git. Work grows with the number of pipelines, whether they are classic (defined in the web editor) or YAML (stored in the repository), the number of secret variables and service connections, the volume of artifacts you need to keep, and how far back your run logs must go. YAML definitions are already in your repositories, so they need review rather than extraction. Classic definitions, secrets and artifacts each need their own handling. Confirm current API limits and retention behavior with Microsoft's Azure DevOps documentation before you estimate, because those limits change.
How long does an Azure Pipelines export take?
There is no fixed duration that applies to every organization. The time depends on the inventory you complete first, the number of pipelines and secrets, how much artifact and log history you archive, and the target platform you choose, such as Jenkins, Woodpecker CI or GitLab CI/CD. A short inventory and a clear list of owners usually shortens the work, while unresolved ownership of secrets and undecided targets lengthen it. Ask any partner for a timeline tied to a written scope, and check the export limits for your organization in Microsoft's documentation.
What do we need to provide before an export starts?
Plan for four inputs from your side:
- Administrator access to the Azure DevOps organization and projects, so every pipeline, variable group and service connection can be listed.
- A named owner for each secret variable and service connection, because their values cannot be read back and must be re-created by someone who holds the source credential.
- A decision on the target platform and hosting model, including who will operate it.
- Storage for the archive of YAML, inventory, run history, logs and any artifacts you must keep, under your own retention rules.
Can our own team export Azure Pipelines without outside help?
Yes, for many teams the inventory and the YAML definitions can be handled in-house, since YAML already lives in your repositories and the REST API can list classic definitions and run history. Secrets, approvals, environments and the production cutover are harder. Secret values cannot be read back, so each one must be re-created by its owner, and mistakes there can break deployments. Teams with limited pipeline or security experience often find it useful to split the work: keep inventory and YAML in-house, and bring in help for secrets handling, deployment gates and cutover.
What would an implementation partner scope for an Azure Pipelines export?
A partner would normally scope a written inventory of projects, pipelines, variable groups, service connections, environments and approvals; a target design for the new CI/CD platform; a plan for re-creating secrets with named owners; the archive format and storage location for YAML, logs and artifacts; and a cutover and rollback plan. DeployOpen works on a fixed-scope basis, with scope, deliverables and timelines agreed in writing before work starts, and ongoing support available as a separate retainer. DeployOpen does not publish prices, so a quote follows from that written scope.
Can run history and logs move to the new platform?
Generally, no. Run history, logs and build outputs stay in Azure Pipelines and cannot be imported into Jenkins, Woodpecker CI or GitLab CI/CD as live history. What you can do is export the records you need for audit or reference, such as run metadata and logs, to your own archive through the REST API before access ends, and keep the new platform's history from the cutover date onward. Ask Microsoft how far back the logs and artifacts remain available in your organization, and confirm with your compliance team which records must be retained.
What happens to our secrets and service connections during the move?
Secret values cannot be exported from Azure Pipelines, so they are not copied to the new platform. Each secret and service connection is re-created by its owner in the target system, such as Jenkins credentials or GitLab CI/CD variables, after the owner confirms the value from the original source. Record the name, scope and owner of every secret in the inventory, rotate any credential that may have been exposed, and keep the old and new values separate until cutover is verified.
How DeployOpen scopes and delivers an exit from Azure Pipelines
DeployOpen plans, implements, documents and supports self-hosted open-source platforms inside your own infrastructure, including the CI/CD engine that replaces Azure Pipelines. For an export of Azure Pipelines data, we start from an inventory of what the pipelines actually hold, then agree the scope, deliverables and timelines in writing before any work begins.
How we scope
- Inventory YAML pipelines, classic definitions, run history, logs, artifacts and service connections in writing before any export runs.
- Agree which pipelines, repositories and retention windows are in the fixed-scope agreement and which are out.
- List every secret variable and service connection that must be re-created by its owners, since values cannot be read back.
- Confirm the target engine, forge connection and hosting model with your security and platform teams first.
How we build
- Export YAML definitions from the repositories and check them against the target CI engine's syntax.
- Pull classic pipeline definitions through the Azure DevOps REST API and convert them to documented pipeline code.
- Archive run history, logs and artifacts into storage you control, keeping an index that maps each run to its source pipeline.
- Test exported pipelines on the new engine against representative branches before cutover.
How we hand over
- Deliver a written record of what was exported, what was converted by hand and what remains with your team.
- Document the secret and service connection re-creation steps, with named owners for each credential.
- Provide restore and access instructions for the archived logs and artifacts so audit questions can be answered later.
- Walk your operators through the self-hosted platform, its backups and its upgrade routine before sign-off.
How we support
- Ongoing support, upgrades and continuous testing are available as a retainer after handover.
- Keep the self-hosted CI platform patched and backed up on a schedule agreed in the written scope.
- Re-run export checks if pipelines change during a parallel period before Azure Pipelines is switched off.
- Ask us for a quote based on the written scope, since DeployOpen does not publish a price list.

