PI Branch-Out & Artifact Shipping Automation
Two Python tools automating both ends of the PI release cycle across 80+ repositories: one creates branches and triggers builds automatically, the other promotes QA-verified artifacts from release-candidate to stable in Product Library, replacing manual, per-repository work that was slow and easy to get wrong at scale.
Solely researched, designed, and built two complementary Python automation tools covering both ends of the PI release cycle across 80+ repositories
Built Excel-driven bulk processing for both tools, with per-row status written back to the same workbook for a full audit trail and safe re-runs
Made branch and pipeline operations idempotent, including source-branch locking, so partially-completed runs can resume without repeating work or failing on already-done steps
Designed the release-promotion tool to validate against actual Azure DevOps release data (RC stage success, real Build ID) rather than trusting values typed into a spreadsheet
Built resilient batch processing that logs and continues past individual repository failures instead of aborting an entire 80+ repository run
Added an optional FastAPI wrapper around the release-promotion tool alongside its CLI, for future integration beyond manual runs
// overview
Two complementary Python tools automating the start and end of the PI release cycle across 80+ repositories: one creates branches and triggers builds automatically, publishing every result as a release candidate; the other promotes exactly the modules QA has verified from release-candidate to stable, driven by an auditable Excel workbook.
I researched, designed, and built both tools entirely on my own, using the Azure DevOps REST API directly for repository, pipeline, and release operations, with Excel-driven bulk processing, idempotent operations, and a full audit trail as the core design goals for both.
// problem
At the end of every PI, a DevOps engineer had to create a new branch from main for each of the organization's 80+ repositories, then manually trigger the corresponding build pipeline for every one of them. Once QA verified the artifacts on those branches, the same manual process repeated in reverse: triggering the Product Library (PL) publish stage on each release pipeline individually.
Both steps were repetitive and purely mechanical, but at 80+ repositories the time cost added up every single PI. The real risk wasn't the time, though; it was that forgetting to publish even one or two repositories out of 80+ could have a significant effect on the released product version, and a manual, repetitive process is exactly where that kind of mistake happens.
// approach
Analyzed the full end-of-PI workflow and split it into two independent problems: getting new branches built and validated automatically, and getting QA-verified artifacts published automatically, then designed a separate Python project for each rather than one monolithic tool.
Researched the Azure DevOps REST API and found it covered nearly everything both tools needed: repository and branch operations, pipeline triggering, and release inspection.
Built the first tool, a branch creator and pipeline runner, supporting three modes: a single targeted repository, all repositories in the project, or an Excel-driven bulk mode reading repository, base branch, and new branch per row, which is what's actually used at PI end across 80+ repositories.
Had the tool validate that the source branch exists and the target branch doesn't already exist before attempting creation, and made source-branch locking idempotent, so re-running against a branch that's already locked is treated as success instead of failing the run.
Wired pipeline triggering directly into branch creation: once a branch is created, the tool automatically runs the pipeline whose name matches the repository, with that behavior configurable on or off.
From there, the release pipeline itself takes over automatically, with no manual step: it deploys the new branch to Dev, deploys to the QA Automation environment, and triggers the RC (release candidate) stage, publishing the build as a release candidate into Product Library.
Made the Excel-driven mode idempotent and resumable: branch status and pipeline status are written back to the same workbook after every row (created/exists/failed/skipped, triggered/failed/skipped), so a partially-completed run across 80+ repositories can be re-run safely without repeating work that already succeeded.
Designed error handling so one repository's failure doesn't stop the batch: the tool logs the failure with detail and continues processing the rest of the repositories, rather than aborting the whole run.
Built the second tool, an artifact release tool, to handle the other end of the PI cycle: once QA has verified the release candidates against a dedicated QA environment sourced from Product Library, this tool promotes exactly the modules QA cleared from release-candidate to stable.
Drove this tool from the same kind of Excel input: a row per repository and branch, with a PL Status column that reflects what QA has actually verified, values like ready, new, or yes trigger promotion, anything else, including a blank cell, is deliberately skipped rather than assumed.
For each row the tool finds the matching release definition, fetches releases filtered by that branch, and only proceeds if the most recent one has a succeeded RC stage, so nothing gets promoted to stable off a release candidate that never actually passed.
Extracted the Build ID directly from the release artifacts rather than trusting a value typed into Excel, so what gets promoted is verified against Azure DevOps itself, and wrote the Build ID, release name, release ID, and target environment ID back to the workbook alongside the final status, so there's a full audit trail of exactly what was published and when.
Built both tools with the same security discipline: PATs are never hardcoded, loaded from environment variables or a gitignored .env file instead, scoped to the minimum permissions each tool actually needs, and documented with a short-expiry, regular-rotation recommendation.
Added an optional FastAPI wrapper around the artifact release tool alongside its CLI, so the same promotion logic can be triggered as an API call instead of a manual script run, for teams that want it wired into other tooling later.
// architecture
// outcome
Branch creation and build triggering across 80+ repositories, and the eventual promotion of QA-verified releases to stable, both went from manual, per-repository work to a single Excel-driven run per tool. The risk that used to matter most, forgetting to publish one or two repositories out of 80+ and having that affect the released product version, is gone: promotion is driven by an auditable spreadsheet and validated against Azure DevOps release data itself, not memory.
Every run leaves a full audit trail: branch and pipeline status per repository from the first tool, and Build ID, release ID, and final publish status per repository from the second, both written back into the same workbook the team already works from. QA verification against a dedicated environment sourced from the release candidate remains a deliberate manual step, not something either tool tries to remove.