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.5.0.tar.gz (165.7 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.5.0-py3-none-any.whl (43.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: ado_workflows-0.5.0.tar.gz
  • Upload date:
  • Size: 165.7 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.5.0.tar.gz
Algorithm Hash digest
SHA256 af7cbc90306f8b58b96c34a21c7efcbfdeeef977edee388f428c32e6386fd20e
MD5 a43dc211aa19af84dff3ff1c1c451c58
BLAKE2b-256 aa600944b3f3ab5a9bc9eaaf1050f8f2729f188dba4694aa188597bd32de0b23

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: ado_workflows-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 43.0 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.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0146830815843dd94ae6e051502bd18bf7719edccb7047717dec7f04ca97b3ea
MD5 1563a3b187f72f901bc23c2bc5a85778
BLAKE2b-256 beb2b3d0f3d24868acd785d41fe6a6761e3540aa4fbd8a2098e9477d0ba0bad0

See more details on using hashes here.

Provenance

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