Azure DevOps Harvester
A CLI tool and Python library to search across Azure Devops repositories, with built-in support for downloading matched files. It utilizes Azure Devops APIs for Search, and Retrieval.
Features
- 🔍 Search across all repositories in an organization
- 📁 Search file contents using Azure DevOps Code Search API
- 🎯 Filter by specific projects
- 📥 Download matched files using Git Items API with hash-based naming
- 📊 Beautiful formatted output with Rich
- ⚡ Parallel downloads with 5 concurrent workers
- 🔐 SHA256 hash verification for downloaded files
- 🐍 Python library for programmatic access
Installation
From PyPI (Recommended)
pip install azdo-harvest
From Source
git clone https://github.com/rothoma2/azdo-harvest.git
cd azdo-harvest
poetry install
Configuration
The tool requires a Personal Access Token (PAT) from Azure DevOps with at least Code (Read) permissions.
Creating a PAT
- Go to Azure DevOps:
https://dev.azure.com/{your-org} - Click on User Settings (top right) → Personal Access Tokens
- Create a new token with Code (Read) scope
- Copy the token (you won't see it again!)
Setting up authentication
You can provide the PAT in two ways:
-
Environment variable (recommended):
export AZDO_PAT="your-personal-access-token"
-
Command-line option:
azdo-harvest search "term" --organization myorg --project myproject
Usage
Basic Search (Summary Mode)
By default, the CLI shows only a summary of results:
azdo-harvest search "file:Dockerfile" --organization myorg --project myproject
Output:
Searching for: file:Dockerfile
Organization: myorg
Project: myproject
✓ Found 2 repositories and 2 files
Download Files
Use --download or -d to automatically download all found files:
azdo-harvest search "file:Dockerfile" --organization myorg --project myproject --download
Files are downloaded with naming format: {repository}__{filename}__{hash}
- Example:
docker-test__Dockerfile__a4b3c5d7.txt - Hash is the first 8 characters of SHA256 hash of file content
- Ensures unique filenames even for files with same name
Specify custom output directory:
azdo-harvest search "file:*.py" -o myorg -p myproject --download --output-dir ./my-files
Verbose Mode
Use --verbose or -v to see detailed tables:
azdo-harvest search "TODO" --organization myorg --project myproject --verbose
Search Options
Search in a specific project:
azdo-harvest search "configuration" --organization myorg --project MyProject
Search only in file contents
azdo-harvest search "function" --organization myorg --project myproject --file-only
Search only repository names
azdo-harvest search "api" --organization myorg --project myproject --repo-only
Limit results
azdo-harvest search "test" --organization myorg --project myproject --limit 50
Complete example with all options
export AZDO_PAT="your-personal-access-token"
azdo-harvest search "file:Dockerfile" \
--organization myorg \
--project MyProject \
--download \
--output-dir ./dockerfiles \
--verbose
Features:
- ⚡ Parallel downloads with 5 concurrent workers
- 📊 Progress bar showing download status
- ✓ Success/failure summary
- 🎯 Unique file naming:
repo__filename__hash.ext - 🔐 SHA256 hash for file verification
Command Reference
azdo-harvest search SEARCH_TERM [OPTIONS]
Arguments:
SEARCH_TERM The term to search for in repositories and files
Options:
-o, --organization TEXT Azure DevOps organization name [required]
-p, --project TEXT Project name [required]
--pat TEXT Personal Access Token (or set AZDO_PAT env var) [required]
--file-only Search only in file contents
--repo-only Search only repository names
-l, --limit INTEGER Maximum number of results [default: 100]
-d, --download Download all found files
--output-dir PATH Directory to save downloaded files [default: ./downloads]
-v, --verbose Show detailed results tables
--help Show this message and exit
Python Library Usage
The package can also be used as a Python library:
import os
from azdo_harvest import AzureDevOpsSearcher
# Initialize
organization = "your-org"
project = "your-project"
pat = os.environ['AZDO_PAT']
searcher = AzureDevOpsSearcher(organization, project, pat)
# Search for files
results = searcher.search(
search_term="file:Dockerfile",
project=project,
search_files=True,
search_repos=False,
max_results=10
)
# Access file results (FileResult objects)
for file in results['files']:
print(f"Found: {file.repository}:{file.filepath}")
print(f"Branch: {file.branch}")
print(f"Download URL: {file.get_download_url()}")
# Download files
output_path = searcher.downloader.download_file(
results['files'][0],
output_dir="./downloads",
preserve_structure=True
)
# Or get file content without downloading
content = searcher.downloader.get_file_content(results['files'][0])
Requirements
- Python >= 3.12
- Azure DevOps organization with Code Search enabled
- Personal Access Token with Code (Read) permissions
License
MIT - See LICENSE file for details
Author
rothoma2 - GitHub
Acknowledgments
Metadata
Release files for azdo-harvest 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| azdo_harvest-0.2.0.tar.gz | 10.8 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| azdo_harvest-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 22.5 kB
Release files / azdo_harvest-0.2.0.tar.gz
| Download URL | azdo_harvest-0.2.0.tar.gz |
|---|---|
| Size | 10.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
391d6cdd778e5c44512a63cfe9c5ce273c883574509c07b1f5329ffbed3e91eb
|
|
BLAKE2b-256 checksum How to use checksums |
45a923f3985f202d4d697805315f68e51f95a41471503d8a66dca0aad7ab7081
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 13, 2025.
Transparency logRelease files / azdo_harvest-0.2.0-py3-none-any.whl
| Download URL | azdo_harvest-0.2.0-py3-none-any.whl |
|---|---|
| Size | 11.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4c374236acef3123fbe90e6b029594458e389a18add019c6b36f1926892b724e
|
|
BLAKE2b-256 checksum How to use checksums |
a29bc4c715da4253b9e0be3d54d8573872f47dbf12a3d1e59116dd368472635d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 13, 2025.
Transparency logSecurity for azdo-harvest 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for azdo_harvest-0.2.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 13, 2025.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.