Skip to main content

A Python library and CLI for parsing and managing GitHub CODEOWNERS files

Project description

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, or docs/CODEOWNERS
  • Pattern syntax: Same as .gitignore (with some limitations)
  • Owner types:
    • GitHub usernames: @username
    • Teams: @org/team-name
    • Email addresses: user@example.com
  • 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

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

github_codeowners-0.1.0.tar.gz (18.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

github_codeowners-0.1.0-py3-none-any.whl (11.5 kB view details)

Uploaded Python 3

File details

Details for the file github_codeowners-0.1.0.tar.gz.

File metadata

  • Download URL: github_codeowners-0.1.0.tar.gz
  • Upload date:
  • Size: 18.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for github_codeowners-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c71d707aa779f84f747f7c291c22bd56426557da3ba0026464fec8ebf4c64a09
MD5 65fdc5eaa717a648809ce4bf82f02a57
BLAKE2b-256 9149a951629a69de7e91674108dc0526c6a89040e6ce3eb91c9611001d634493

See more details on using hashes here.

Provenance

The following attestation bundles were made for github_codeowners-0.1.0.tar.gz:

Publisher: increment-version-and-publish.yml on henryupton/github-codeowners

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file github_codeowners-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for github_codeowners-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e96f0b31c9826bdb5968529f0950eda6ba279185c8a4e5ed28ffbbd845c4bdb1
MD5 7579ed08489f2048bd62714f0a2be5bc
BLAKE2b-256 1609323deb965f09170528e626962786cc89f08524f4ddf5de27b84a6a348229

See more details on using hashes here.

Provenance

The following attestation bundles were made for github_codeowners-0.1.0-py3-none-any.whl:

Publisher: increment-version-and-publish.yml on henryupton/github-codeowners

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