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.11.0.tar.gz (196.9 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.11.0-py3-none-any.whl (52.1 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for ado_workflows-0.11.0.tar.gz
Algorithm Hash digest
SHA256 fe99a7d4680f3c8f2e421672dcf83965882551dba30f308ce2592414d6f6f8ec
MD5 0e748f968f51a2e16f79fa14f52ae869
BLAKE2b-256 a0a8be46ab5abfc25ce1543d9d14c466fb00b10252e822f906059e537b7d00e5

See more details on using hashes here.

Provenance

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

File metadata

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

File hashes

Hashes for ado_workflows-0.11.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e5a7ddda804885eb24210ad26afe059b4f3aa8f1aa12a9b1b89c98060eee1c2e
MD5 1f6a8045a7f5d1f05cd0b0df316fa071
BLAKE2b-256 78ef19331d3a11aa482f34b5050cabcb4bf798601ed3f7f73b6b8669aa401037

See more details on using hashes here.

Provenance

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