How no-mistakes Creates Pull Requests in Azure DevOps: CLI Integration Deep Dive
no-mistakes integrates with Azure DevOps by wrapping the official az CLI extension, detecting the provider from repository URLs, and executing az repos pr create commands with automatically extracted organization, project, and repository parameters.
The kunchenguid/no-mistakes repository automates pull request workflows across multiple SCM providers. For Azure DevOps specifically, it implements a lightweight Go wrapper around the Azure CLI rather than using REST APIs directly, enabling seamless no-mistakes Azure DevOps PR integration while maintaining consistent interfaces with GitHub, GitLab, and Bitbucket hosts.
Provider Detection and Host Initialization
Detecting Azure DevOps Repositories
Before creating PRs, no-mistakes identifies Azure DevOps repositories by analyzing the upstream URL. The scm.DetectProvider function in internal/scm/scm.go recognizes Azure DevOps URLs through substring matching for dev.azure.com or visualstudio.com domains (lines 24-33).
When the pipeline reaches the PR step, this detection triggers the construction of an Azure DevOps-specific host implementation.
Building the Azure DevOps Host
The buildHost function in internal/pipeline/steps/host.go (lines 66-83) constructs the Azure DevOps host by parsing the remote URL and initializing the wrapper:
return azuredevops.New(
cmdFactory,
func() bool { return stepCLIAvailable(sctx, provider) },
org, project, repo), ""
The azuredevops.New constructor in internal/scm/azuredevops/azuredevops.go (lines 45-67) stores three critical components: the command factory, a CLI availability checker, and the extracted org/project/repo identifiers required for all az commands.
Creating Pull Requests via the Azure CLI
Command Construction and Execution
The CreatePR method in internal/scm/azuredevops/azuredevops.go (lines 90-100) builds the CLI command dynamically:
args := []string{
"repos", "pr", "create",
"--source-branch", branch,
"--target-branch", base,
"--title", content.Title,
"--description", clampDescription(content.Body),
}
args = append(args, h.scopeArgs()...)
args = append(args, "--output", "json")
out, err := outputJSON(h.cmd(ctx, "az", args...))
The scopeArgs method appends the required --organization, --project, and --repository flags derived from URL parsing. The command returns JSON output, which unmarshals into an azPR struct and converts to the generic scm.PR type containing the PR number and browsable URL (lines 59-80).
Handling PR Metadata and Limits
Azure DevOps enforces description length limitations that could truncate PR bodies. The clampDescription function (lines 34-40) enforces the scm.MaxPRBodyChars limit before submission, ensuring the CLI command succeeds without validation errors.
PR Lifecycle Management
Finding and Updating Existing PRs
Beyond creation, no-mistakes manages PR states through additional CLI wrappers:
FindPR: Lists active PRs for a specific branch usingaz repos pr listUpdatePR: Modifies existing PRs viaaz repos pr updatewith--titleand--descriptionflags
These operations use the same scope arguments and JSON parsing patterns as the creation flow.
Status Checks and Mergeability
The host implements polling capabilities for CI/CD integration:
GetPRState: Retrieves current PR status viaaz repos pr showGetMergeableState: Determines merge readinessGetChecks: Fetches policy evaluation results usingaz repos pr policy list
These methods enable the pipeline to block or proceed based on Azure DevOps branch policies and build validation status.
CLI Availability and Authentication
The Available method in internal/scm/azuredevops/azuredevops.go (lines 103-119) validates that the az CLI is installed, the Azure DevOps extension is present, and the user is authenticated. This early validation surfaces configuration errors before attempting PR creation, preventing cryptic failures mid-pipeline.
Implementation Example
The following Go code demonstrates the integration flow as implemented in internal/pipeline/steps/pr.go (lines 101-108):
// Detect provider from repository URL
provider := scm.DetectProvider(sctx.Repo.UpstreamURL) // → ProviderAzureDevOps
// Build the appropriate host
host, _ := steps.BuildHost(sctx, provider) // returns *azuredevops.Host
// Prepare PR content
prContent := scm.PRContent{
Title: "feat: add Azure DevOps PR integration",
Body: "## What Changed\n- Implemented Azure DevOps host\n- Added PR creation flow",
}
// Create the pull request
created, err := host.CreatePR(context.Background(), "feature/azure-devops", "main", prContent)
if err != nil {
log.Fatalf("PR creation failed: %v", err)
}
fmt.Printf("Created PR: %s\n", created.URL)
Summary
- no-mistakes detects Azure DevOps repositories by scanning for
dev.azure.comorvisualstudio.comin remote URLs viascm.DetectProvider. - The Azure DevOps host in
internal/scm/azuredevops/azuredevops.gowraps theazCLI extension rather than using REST APIs. - PR creation executes
az repos pr createwith automatically scoped--organization,--project, and--repositoryarguments. - Description lengths are clamped to Azure DevOps limits using
clampDescriptionbefore submission. - The integration supports full PR lifecycle management including updates, status checks, and mergeability polling through consistent CLI commands.
Frequently Asked Questions
How does no-mistakes detect Azure DevOps repositories?
The DetectProvider function in internal/scm/scm.go (lines 24-33) inspects the repository upstream URL for dev.azure.com or visualstudio.com substrings. When matched, it returns ProviderAzureDevOps, triggering the Azure-specific host construction in the pipeline step.
What Azure CLI commands does no-mistakes use for PR creation?
According to the source code in internal/scm/azuredevops/azuredevops.go, no-mistakes executes az repos pr create with flags for source/target branches, title, description, and scope parameters. It also uses az repos pr list for discovery, az repos pr update for modifications, and az repos pr policy list for status checks.
How does no-mistakes handle Azure DevOps description length limits?
The clampDescription function (lines 34-40) truncates PR descriptions to the maximum character limit defined by scm.MaxPRBodyChars before passing them to the CLI. This prevents Azure DevOps from rejecting PRs with excessively long bodies.
Can no-mistakes update existing PRs in Azure DevOps?
Yes. The UpdatePR method in internal/scm/azuredevops/azuredevops.go executes az repos pr update with --title and --description parameters, allowing the pipeline to synchronize PR content when changes occur on the source branch after initial creation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →