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.4.0.tar.gz (155.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.4.0-py3-none-any.whl (40.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: ado_workflows-0.4.0.tar.gz
  • Upload date:
  • Size: 155.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.4.0.tar.gz
Algorithm Hash digest
SHA256 5280bf738a027cf5c7d5ff311992864976b1f78965ccde7e94e76a35a226de86
MD5 46e45b8c88562c9ecad3a6dce3df28af
BLAKE2b-256 e85a8110aeaf1241b1ab4259db04ce3b8eb4bcac56495c3b7073851028cb141b

See more details on using hashes here.

Provenance

The following attestation bundles were made for ado_workflows-0.4.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.4.0-py3-none-any.whl.

File metadata

  • Download URL: ado_workflows-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 40.3 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.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 499b24de0d0111667901804f1cb27fc27e8afb0c82383e15477e3482e854d944
MD5 ca92177d210e65c9d9c9f591cb08237b
BLAKE2b-256 ccc04d44f0084e8e2b5eaa56f3acf84012929fd6220ca63b084c4b1ad658d09e

See more details on using hashes here.

Provenance

The following attestation bundles were made for ado_workflows-0.4.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