A comprehensive Python automation tool for creating branches across Azure DevOps repositories and executing pipelines using the Azure DevOps REST API. This tool supports both single repository operations and bulk processing across all repositories in a project, with advanced configuration management and comprehensive logging.
- Features
- Prerequisites
- Installation
- Configuration
- Usage
- Project Structure
- Classes and Functions
- Logging
- Error Handling
- Examples
- Troubleshooting
- Contributing
- Bulk Branch Creation: Create branches across all repositories in an Azure DevOps project
- Single Repository Mode: Target specific repositories for branch creation
- Pipeline Automation: Automatically run pipelines after branch creation
- Advanced Configuration Management: Flexible configuration system supporting both Python files and environment variables
- Branch Validation: Check if source branch exists and target branch doesn't already exist
- Branch Locking: Automatically lock source branches during creation process
- Comprehensive Logging: Detailed logging with configurable output to console and file
- Modular Architecture: Well-organized code structure with separate packages for utilities and configuration
- Error Handling: Robust error handling with detailed error messages and recovery strategies
- REST API Integration: Uses Azure DevOps REST API for reliable operations
- Configuration Validation: Built-in validation for all configuration parameters
- Python 3.7 or higher
- Azure DevOps organization access
- Personal Access Token (PAT) with appropriate permissions:
- Code (Read & Write): For repository and branch operations
- Project and Team (Read): For listing repositories
- Clone or download the project files
- Install required dependencies:
python -m venv .venv .\.venv\Scripts\Activate.ps1 pip install -r requirements.txt
The application now uses a sophisticated configuration management system that supports multiple configuration sources.
The primary configuration file contains all settings organized in sections:
# Azure DevOps Configuration
AZURE_CONFIG = {
'organization': 'your-organization', # Your Azure DevOps organization name
'project': 'your-project', # Your project name
'pat': 'your-personal-access-token' # Your Personal Access Token
}
# Repository Configuration
REPOSITORY_CONFIG = {
'repository': None, # Set to specific repo name or None for all repos
'source_branch': 'main', # Source branch to create from
'new_branch': 'feature/your-branch' # New branch name to create
}
# Logging Configuration
LOGGING_CONFIG = {
'log_level': 'INFO', # DEBUG, INFO, WARNING, ERROR, CRITICAL
'log_to_file': True, # Enable file logging
'log_to_console': True, # Enable console logging
'log_dir': 'logs' # Log directory path
}
# Pipeline Configuration
PIPELINE_CONFIG = {
'run_pipeline_after_branch_creation': True # Auto-run pipelines after branch creation
}You can also use environment variables by setting use_env_vars=True:
# In main.py
config_manager = get_config_manager(use_env_vars=True)Required environment variables:
AZURE_ORGANIZATIONAZURE_PROJECTAZURE_PATREPOSITORY_NAME(optional)SOURCE_BRANCHNEW_BRANCH
The ConfigManager class provides:
- Dual Configuration Sources: Python files or environment variables
- Validation: Automatic validation of all required parameters
- Type Safety: Ensures configuration values are correct types
- Fallback Values: Sensible defaults for optional parameters
- Go to Azure DevOps β User Settings β Personal Access Tokens
- Create a new token with the following scopes:
- Code (Read & Write)
- Project and Team (Read)
- Copy the token and update the
AZURE_CONFIG['pat']inconfig.py
# Set environment variable (Windows PowerShell)
$env:AZURE_PAT = "your-personal-access-token"
# Set environment variable (Linux/Mac)
export AZURE_PAT="your-personal-access-token"cd src
python main.pyThe application now automatically loads configuration from config.py. No need to edit the main script directly.
Update config.py to target a specific repository:
REPOSITORY_CONFIG = {
'repository': 'my-specific-repo', # Target specific repository
'source_branch': 'main',
'new_branch': 'feature/my-feature'
}Update config.py to process all repositories:
REPOSITORY_CONFIG = {
'repository': None, # Process all repositories in the project
'source_branch': 'main',
'new_branch': 'feature/my-feature'
}Enable or disable automatic pipeline execution:
PIPELINE_CONFIG = {
'run_pipeline_after_branch_creation': True # or False to skip pipelines
}Branch-Out/
βββ src/
β βββ main.py # Main application entry point
β βββ config.py # Configuration variables
β βββ requirements.txt # Python dependencies
β βββ .env.example # Environment variables template
β βββ utils/ # Utilities package
β β βββ __init__.py # Package initialization
β β βββ logger_config.py # Logging configuration module
β βββ config/ # Configuration management package
β β βββ __init__.py # Package initialization
β β βββ config_manager.py # Configuration management system
β βββ classes/ # Business logic classes
β β βββ devops_repos.py # Azure DevOps repository operations
β β βββ devops_pipelines.py # Pipeline management and execution
β βββ modules/ # Additional modules (if any)
βββ logs/ # Generated log files (created automatically)
β βββ branch_creation_*.log # Timestamped log files
βββ README.md # This documentation file
Contains utility functions and helper modules:
- logger_config.py: Centralized logging configuration with file and console output
Contains configuration management modules:
- config_manager.py: Flexible configuration system supporting multiple sources
Contains main business logic:
- devops_repos.py: Azure DevOps repository operations (branch creation, listing)
- devops_pipelines.py: Pipeline management and execution automation
The main class that handles Azure DevOps repository API interactions.
az_devops(organization, project, repository, pat, new_branch, source_branch)| Method | Description | Returns |
|---|---|---|
get_all_repositories() |
Retrieves all repositories in the project | JSON response with repository list |
get_main_branch_commit() |
Gets the commit ID of the source branch | Commit ID string or None |
list_branches() |
Lists all branches in the current repository | List of branch objects |
create_branch(base_branch_commit) |
Creates a new branch from base commit | JSON response with creation status |
lock_branch(branch_name) |
Locks a branch to prevent changes | None (prints status) |
Handles Azure DevOps pipeline operations and automation.
AzurePipelineManager(organization, project, pat, logger)| Method | Description | Returns |
|---|---|---|
run_pipeline_by_name(pipeline_name, branch_name) |
Runs a pipeline on specified branch | Pipeline run response or None |
get_run_status(run_id) |
Gets the status of a pipeline run | Status string |
list_pipelines() |
Lists all pipelines in the project | List of pipeline objects |
Manages application configuration from multiple sources.
ConfigManager(use_env_vars=False, env_file_path=None)| Method | Description | Returns |
|---|---|---|
validate_config() |
Validates all configuration parameters | Boolean |
get_azure_config() |
Returns Azure DevOps configuration | Dictionary |
get_repository_config() |
Returns repository configuration | Dictionary |
get_logging_config() |
Returns logging configuration | Dictionary |
get_pipeline_config() |
Returns pipeline configuration | Dictionary |
print_config_summary() |
Prints formatted configuration summary | None |
| Function | Description | Parameters |
|---|---|---|
branch_exists(existing_branches, target_branch) |
Checks if a branch already exists | branches list, branch name |
ensure_source_branch(client, repo_name, source_branch) |
Validates source branch exists | client, repo name, branch name |
create_branch_from_source(client, commit_id, source_branch, new_branch) |
Creates new branch | client, commit ID, source/target branches |
process_repositories(client, pipeline_manager, repo_name, source_branch, new_branch, pipeline_config) |
Processes single repository | client, pipeline manager, repo details, config |
process_single_repository(client, pipeline_manager, repo_name, source_branch, new_branch, pipeline_config) |
Handles single repo with pipeline execution | client, pipeline manager, repo details, config |
run_pipeline_for_repository(pipeline_manager, pipeline_name, branch_name) |
Executes pipeline for repository | pipeline manager, pipeline name, branch |
list_all_repositories(client) |
Lists all project repositories | client object |
main() |
Main orchestration function | None |
| Function | Description | Parameters |
|---|---|---|
setup_logging(log_level, log_to_file, log_to_console, log_dir) |
Configures comprehensive logging system | log settings |
get_logger() |
Returns configured logger instance | None |
The application uses a comprehensive logging system that outputs to both console and file with configurable levels and destinations.
- INFO: General process information
- ERROR: Critical errors that stop execution
- WARNING: Non-critical issues (e.g., branch already exists)
- DEBUG: Detailed diagnostic information
logs/branch_creation_YYYYMMDD_HHMMSS.log
2025-10-12 14:30:22,141 - INFO - Logging initialized. Log Level: 10. Log file: logs\branch_creation_20251012_143022.log
2025-10-12 14:30:22,141 - INFO - Starting branch creation process
π Configuration Summary:
Organization: your-organization-name
Project: your-project-name
Repository: All repositories
Source Branch: main
New Branch: feature/branch01
Log Level: DEBUG
Run Pipeline: True
2025-10-12 14:30:22,141 - INFO - Processing repository: my-repo
2025-10-12 14:30:23,000 - INFO - Branch 'feature/branch01' created successfully.
2025-10-12 14:30:23,500 - INFO - Pipeline run initiated successfully!
- Organized Packages: Separated code into logical packages (
utils/,config/,classes/) - Python Packages: Added
__init__.pyfiles for proper package structure - Clean Imports: Simplified import statements using package-level imports
- Flexible Configuration: Support for both Python configuration files and environment variables
- Configuration Validation: Built-in validation for all required parameters
- Centralized Settings: All configuration organized in
config.pywith logical sections - Configuration Summary: Automatic display of active configuration at startup
- Pipeline Integration: Automatic pipeline execution after successful branch creation
- Pipeline Management: New
AzurePipelineManagerclass for pipeline operations - Configurable Execution: Enable/disable pipeline runs via configuration
- Centralized Logging: Moved to dedicated
utils/logger_config.pymodule - Configurable Output: Control file and console logging independently
- Timestamped Files: Automatic log file naming with timestamps
- Multiple Log Levels: Support for DEBUG, INFO, WARNING, ERROR, CRITICAL
- Graceful Failures: Better handling of repository access errors
- Detailed Error Messages: More informative error reporting
- Configuration Validation: Pre-execution validation of all settings
- Recovery Strategies: Continue processing other repositories when one fails
The script handles various error scenarios:
- Source branch not found: Logs error and exits
- Target branch already exists: Logs warning and skips
- API authentication failures: HTTP errors with details
- Network timeouts: 30-second timeout on all requests
- Invalid repository names: Validation and error reporting
# Configuration
organization = 'mycompany'
project = 'web-applications'
repository = None # Process all repositories
source_branch = 'main'
new_branch = 'feature/new-payment-system'# Configuration
organization = 'mycompany'
project = 'web-applications'
repository = 'payment-service' # Specific repository
source_branch = 'main'
new_branch = 'hotfix/critical-bug-fix'import os
# Secure configuration
organization = os.getenv('AZURE_ORG', 'default-org')
project = os.getenv('AZURE_PROJECT', 'default-project')
PAT = os.getenv('AZURE_DEVOPS_PAT')
if not PAT:
raise ValueError("AZURE_DEVOPS_PAT environment variable is required")-
Authentication Error (401)
- Verify your PAT is correct and has required permissions
- Check PAT expiration date
-
Repository Not Found (404)
- Verify organization and project names
- Ensure repository exists and you have access
-
Source Branch Not Found
- Check source branch name spelling
- Verify branch exists in the repository
-
Branch Already Exists
- The script will skip repositories where the target branch already exists
- Check logs for specific repositories affected
For detailed troubleshooting, enable debug logging:
logger = setup_logging(log_level=logging.DEBUG)Azure DevOps has API rate limits. If you encounter rate limiting:
- Add delays between operations
- Process repositories in smaller batches
- Check your organization's rate limit policies