github-codeowners
A Python library and CLI for parsing, validating, and managing GitHub CODEOWNERS files. Perfect for CI/CD pipelines and automation workflows.
Features
- Parse CODEOWNERS files into structured Python objects
- Validate CODEOWNERS syntax and structure
- Programmatically add, remove, and modify ownership rules
- Command-line interface for common operations
- Support for all CODEOWNERS features:
- Multiple owner types (@username, @org/team, email addresses)
- Pattern-based file matching
- Proper precedence handling
Installation
pip install github-codeowners==0.0.1
For development:
git clone https://github.com/henryupton/github-codeowners.git
cd github-codeowners
pip install -e ".[dev]"
Quick Start
Command Line Usage
The codeowners CLI provides several commands for managing CODEOWNERS files:
# Show parsed CODEOWNERS file
codeowners show
codeowners show --repo /path/to/repo
codeowners show /path/to/CODEOWNERS
# Validate CODEOWNERS syntax
codeowners validate
codeowners validate --repo /path/to/repo
# Add a new rule
codeowners add-rule "*.py" @python-team @user1
codeowners add-rule "docs/**" @docs-team --comment "Documentation owners"
# Remove a rule
codeowners remove-rule "*.py"
# Add an owner to existing rule
codeowners add-owner "*.py" @new-maintainer
# Remove an owner from a rule
codeowners remove-owner "*.py" @old-maintainer
# Reformat the file
codeowners format
codeowners format --output CODEOWNERS.new
Python API Usage
from github_codeowners import (
parse_codeowners_file,
write_codeowners_file,
CodeOwnersFile,
)
# Parse an existing CODEOWNERS file
codeowners = parse_codeowners_file(".github/CODEOWNERS")
# Access rules
for entry in codeowners.get_rules():
print(f"{entry.pattern}: {[str(o) for o in entry.owners]}")
# Add a new rule
codeowners.add_rule("*.js", ["@frontend-team", "@user1"])
# Add a comment
codeowners.add_comment("Frontend code owners")
# Write back to disk
write_codeowners_file(codeowners, ".github/CODEOWNERS")
CLI Commands
show
Display the parsed CODEOWNERS file with line numbers and entry types.
codeowners show [FILE] [--repo PATH]
validate
Validate the CODEOWNERS file syntax and check for common issues.
codeowners validate [FILE] [--repo PATH]
Exit codes:
- 0: Valid
- 1: Validation errors or file not found
format
Parse and rewrite the CODEOWNERS file, normalizing formatting.
codeowners format [FILE] [--repo PATH] [--output PATH]
add-rule
Add a new ownership rule.
codeowners add-rule PATTERN OWNERS... [FILE] [OPTIONS]
Options:
--repo PATH Repository root (auto-find CODEOWNERS)
--output PATH Output file (default: overwrite input)
--comment TEXT Inline comment for the rule
Example:
codeowners add-rule "*.py" @python-team @user1 --comment "Python files"
remove-rule
Remove rules matching a pattern.
codeowners remove-rule PATTERN [FILE] [OPTIONS]
add-owner
Add an owner to an existing rule.
codeowners add-owner PATTERN OWNER [FILE] [OPTIONS]
Example:
codeowners add-owner "*.py" @new-maintainer
remove-owner
Remove an owner from an existing rule.
codeowners remove-owner PATTERN OWNER [FILE] [OPTIONS]
Python API
Parsing
from github_codeowners import parse_codeowners, parse_codeowners_file
from github_codeowners.parser import find_codeowners_file
# Parse from string
content = "*.py @python-team\n*.js @frontend-team"
codeowners = parse_codeowners(content)
# Parse from file
codeowners = parse_codeowners_file("/path/to/CODEOWNERS")
# Auto-find CODEOWNERS in repository
codeowners_path = find_codeowners_file("/path/to/repo")
codeowners = parse_codeowners_file(codeowners_path)
Creating and Modifying
from github_codeowners import CodeOwnersFile, CodeOwner
# Create a new CODEOWNERS file
codeowners = CodeOwnersFile()
# Add rules
codeowners.add_rule("*.py", ["@python-team", "@user1"])
codeowners.add_rule("docs/**", ["@docs-team"])
# Add comments and blank lines
codeowners.add_blank()
codeowners.add_comment("Frontend section")
codeowners.add_rule("*.js", ["@frontend-team"])
# Find and modify rules
rules = codeowners.find_rules_for_pattern("*.py")
for rule in rules:
# Add an owner
rule.owners.append(CodeOwner.from_string("@new-owner"))
# Modify inline comment
rule.comment = "Updated comment"
Writing
from github_codeowners import write_codeowners, write_codeowners_file
# Write to string
content = write_codeowners(codeowners)
print(content)
# Write to file
write_codeowners_file(codeowners, ".github/CODEOWNERS")
# Create parent directories if needed
write_codeowners_file(codeowners, ".github/CODEOWNERS", create_dirs=True)
Working with Entries
# Iterate over all entries
for entry in codeowners.entries:
if entry.is_rule():
print(f"Pattern: {entry.pattern}")
print(f"Owners: {[str(o) for o in entry.owners]}")
if entry.comment:
print(f"Comment: {entry.comment}")
elif entry.is_comment():
print(f"Comment: {entry.comment}")
elif entry.is_blank():
print("Blank line")
# Get only rules
rules = codeowners.get_rules()
# Find specific rules
py_rules = codeowners.find_rules_for_pattern("*.py")
# Remove entries
codeowners.remove_entry(entry)
# Clear all entries
codeowners.clear()
CI/CD Integration
GitHub Actions
name: Validate CODEOWNERS
on: [pull_request]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install github-codeowners
run: pip install github-codeowners
- name: Validate CODEOWNERS
run: codeowners validate
GitLab CI
validate-codeowners:
image: python:3.9
script:
- pip install github-codeowners
- codeowners validate
only:
- merge_requests
Pre-commit Hook
Add to .pre-commit-config.yaml:
repos:
- repo: local
hooks:
- id: validate-codeowners
name: Validate CODEOWNERS
entry: codeowners validate
language: system
pass_filenames: false
CODEOWNERS Format
This library supports the full GitHub CODEOWNERS format:
- Location:
.github/CODEOWNERS,CODEOWNERS, ordocs/CODEOWNERS - Pattern syntax: Same as
.gitignore(with some limitations) - Owner types:
- GitHub usernames:
@username - Teams:
@org/team-name - Email addresses:
user@example.com
- GitHub usernames:
- Comments: Lines starting with
# - Inline comments:
pattern @owner # comment - Precedence: Last matching pattern wins
Example CODEOWNERS file:
# Default owner for everything
* @default-owner
# Frontend
*.js @frontend-team
*.css @frontend-team
*.html @frontend-team
# Backend
*.py @backend-team @senior-dev
# Documentation
docs/** @docs-team @tech-writer
# CI/CD
.github/** @devops-team
Development
# Clone the repository
git clone https://github.com/yourusername/github-codeowners.git
cd github-codeowners
# Install development dependencies
pip install -e ".[dev]"
# Run tests
pytest
# Format code
black src/ tests/
# Type checking
mypy src/
License
MIT License - see LICENSE file for details
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Links
Metadata
Release files for github-codeowners 0.1.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 | |
|---|---|---|---|
| github_codeowners-0.1.0.tar.gz | 18.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| github_codeowners-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 30.1 kB
Release files / github_codeowners-0.1.0.tar.gz
| Download URL | github_codeowners-0.1.0.tar.gz |
|---|---|
| Size | 18.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c71d707aa779f84f747f7c291c22bd56426557da3ba0026464fec8ebf4c64a09
|
|
BLAKE2b-256 checksum How to use checksums |
9149a951629a69de7e91674108dc0526c6a89040e6ce3eb91c9611001d634493
|
| 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 Oct 16, 2025.
Transparency logRelease files / github_codeowners-0.1.0-py3-none-any.whl
| Download URL | github_codeowners-0.1.0-py3-none-any.whl |
|---|---|
| Size | 11.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e96f0b31c9826bdb5968529f0950eda6ba279185c8a4e5ed28ffbbd845c4bdb1
|
|
BLAKE2b-256 checksum How to use checksums |
1609323deb965f09170528e626962786cc89f08524f4ddf5de27b84a6a348229
|
| 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 Oct 16, 2025.
Transparency log