Skip to main content

Azure DevOps workflow automation library — PR context, repository discovery, and SDK client wrappers

Project description

ado-workflows

Azure DevOps workflow automation library — PR review analysis, comment lifecycle, repository discovery, and Python SDK wrappers.

CI Coverage PyPI License: MIT

Install

pip install ado-workflows

Quick Start

from ado_workflows import ConnectionFactory, AdoClient

# Authenticate (uses DefaultAzureCredential — Azure CLI, managed identity, etc.)
factory = ConnectionFactory()
connection = factory.get_connection("https://dev.azure.com/MyOrg")
client = AdoClient(connection)

PR Review Status

from ado_workflows import get_review_status

status = get_review_status(client, "MyProject", "MyRepo", pr_id=12345)
print(status.approval_status)    # ApprovalStatus.APPROVED / PENDING / REJECTED
print(status.total_reviewers)    # 3
print(status.required_approvals) # 2
for vs in status.vote_statuses:
    print(f"{vs.name}: {vs.vote_text} (stale: {vs.vote_invalidated})")

Pending Review Analysis

from ado_workflows import analyze_pending_reviews

result = analyze_pending_reviews(
    client, "MyProject", "MyRepo",
    max_days_old=14,
    creator_filter="alice",
)
for pr in result.pending_prs:  # sorted by days_open descending
    print(f"PR #{pr.pr_id} ({pr.days_open}d): {pr.title}")
    print(f"  Needs {pr.needs_approvals_count} more approvals")
    for r in pr.pending_reviewers:
        print(f"  - {r.display_name}")

Comment Operations

from ado_workflows import (
    analyze_pr_comments,
    post_comment,
    reply_to_comment,
    resolve_comments,
)

# Analyze threads
analysis = analyze_pr_comments(client, "MyProject", "MyRepo", pr_id=12345)
print(f"{analysis.summary.active_count} active, {analysis.summary.resolved_count} resolved")

# Post, reply, resolve
thread_id = post_comment(client, "MyProject", "MyRepo", pr_id=12345, content="LGTM")
reply_to_comment(client, "MyProject", "MyRepo", pr_id=12345, thread_id=thread_id, content="Thanks!")
result = resolve_comments(client, "MyProject", "MyRepo", pr_id=12345, thread_ids=[thread_id])
print(f"Resolved: {result.resolved}, Failed: {result.failed}")

Repository Discovery

from ado_workflows import discover_repositories, parse_ado_url

# Parse any Azure DevOps URL
org, project, repo, pr_id = parse_ado_url(
    "https://dev.azure.com/MyOrg/MyProject/_git/MyRepo/pullrequest/42"
)

# Discover git repos in a workspace
repos = discover_repositories("/path/to/workspace")
for r in repos:
    print(f"{r['name']}{r['remote_url']}")

PR Context

from ado_workflows import establish_pr_context

# From a URL
ctx = establish_pr_context("https://dev.azure.com/MyOrg/MyProject/_git/MyRepo/pullrequest/42")

# From a PR ID (requires RepositoryContext to be set)
ctx = establish_pr_context(42, working_directory="/path/to/repo")

print(ctx.org_url)    # https://dev.azure.com/MyOrg
print(ctx.pr_id)      # 42

Architecture

Three-layer API:

Layer Purpose State SDK dependency
1 — Primitives URL parsing, git inspection, date parsing None None
2 — Context Repository context caching Thread-safe None
3 — PR Operations Review, comments, lifecycle, pending analysis Composes L1+L2 azure-devops

See docs/ARCHITECTURE.md for full design rationale.

Error Handling

All errors are ActionableError instances (from actionable-errors) with structured context:

from actionable_errors import ActionableError

try:
    status = get_review_status(client, "MyProject", "MyRepo", pr_id=99999)
except ActionableError as e:
    print(e.error_type)   # ErrorType.CONNECTION
    print(e.service)      # "AzureDevOps"
    print(e.suggestion)   # "Verify the PR ID exists and you have read access..."

Development

uv sync --extra dev
task check          # lint + type-check + test

See CONTRIBUTING.md for full development setup and coding standards.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ado_workflows-0.7.0.tar.gz (174.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ado_workflows-0.7.0-py3-none-any.whl (45.7 kB view details)

Uploaded Python 3

File details

Details for the file ado_workflows-0.7.0.tar.gz.

File metadata

  • Download URL: ado_workflows-0.7.0.tar.gz
  • Upload date:
  • Size: 174.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ado_workflows-0.7.0.tar.gz
Algorithm Hash digest
SHA256 4401a091fd8a7493913b1ffb9dda5ae7e827c9a0b939fd7aab9a383b7dd3ed76
MD5 095803bf8bd4004511541833dd3b624a
BLAKE2b-256 ffd7230c7127738fcbfe59c6631a44092be0657cefaa32441d82181d594de6bd

See more details on using hashes here.

Provenance

The following attestation bundles were made for ado_workflows-0.7.0.tar.gz:

Publisher: release.yml on grimlor/ado-workflows

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ado_workflows-0.7.0-py3-none-any.whl.

File metadata

  • Download URL: ado_workflows-0.7.0-py3-none-any.whl
  • Upload date:
  • Size: 45.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for ado_workflows-0.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e6e3e95ef4cf410abcc381cc50cfa2fed61083d7883124b275e2d2e7a14e4017
MD5 547ce264d174b95213a5ae3ea371175f
BLAKE2b-256 4daf63e20309c36d648c8d674d7f088b8ec31dcdc9106ac552f866e91382f8fd

See more details on using hashes here.

Provenance

The following attestation bundles were made for ado_workflows-0.7.0-py3-none-any.whl:

Publisher: release.yml on grimlor/ado-workflows

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page