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.1.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.1-py3-none-any.whl (40.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: ado_workflows-0.4.1.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.1.tar.gz
Algorithm Hash digest
SHA256 dc506e3b71406f09aeb45b24ba58221e7396318dfd4fae5d15f09e8b62ca11cd
MD5 b59eee041ca0a194f223cecfcdf160b6
BLAKE2b-256 cbbdce0f238b66b5cf3f6b70a9a689b45604c990943a0574dbe4858b186dd1df

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: ado_workflows-0.4.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c02728d7cf50b02da9a83240a64de4e8d93732cc6a1eadb5d283c05c36b95459
MD5 c8ec6040521876e14f72bb27bc6d21de
BLAKE2b-256 62142f8c6c2e393b82dbc367a820b6eefb7e0448fdef68b2d9c23d1ec3bbd915

See more details on using hashes here.

Provenance

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