Sign in

    moon-codeowners

    Deterministic CODEOWNERS parser, matcher, and coverage auditor for MoonBit.

    codeowners
    monorepo
    developer-tools
    ci
    github
    Download zip
    Author
    Version
    0.1.0
    License
    Apache-2.0
    Last updated
    4 days ago
    Downloads
    14

    #moon-codeowners

    CI

    Deterministic CODEOWNERS parsing, matching, and coverage auditing for MoonBit.

    moon-codeowners is a focused developer tool for monorepos and CI. It implements GitHub's CODEOWNERS precedence model, explains which rule selected an owner, and audits changed-file lists for missing ownership. The core library is pure MoonBit and works without network access.

    #Why this project

    Generic glob libraries answer "does this path match this pattern?". CODEOWNERS requires more:

    • the last matching rule wins;
    • rules can assign users, teams, or email addresses;
    • paths are case-sensitive;
    • a directory rule owns all descendants;
    • invalid lines are skipped and should be reported;
    • CI needs to know whether every changed file has an owner.

    The package separates those policy semantics from generic pattern matching.

    #Features

    • Parse users, teams, and email owners.
    • Support *, **, and ? path patterns.
    • Support root-anchored and unanchored patterns.
    • Apply GitHub's last-match-wins rule.
    • Explain the effective owner, matched pattern, and source line.
    • Audit one or many repository paths.
    • Report uncovered files and invalid CODEOWNERS lines.
    • Emit human-readable or JSON output from the CLI.
    • Run on the MoonBit Wasm target with no native dependency.

    #Quick start

    Build and test from source:

    git clone https://github.com/404-32/byc.git cd byc moon test --target wasm

    Explain an owner:

    moon run cmd/main -- explain .github/CODEOWNERS src/parser.mbt

    Check a changed-file list:

    moon run cmd/main -- check .github/CODEOWNERS examples/changed-files.txt

    Produce JSON for CI:

    moon run cmd/main -- coverage .github/CODEOWNERS examples/changed-files.txt --json

    Run the standalone library example:

    moon run examples/basic

    #Library API

    ///|
    let document = @codeowners.Codeowners::parse(
    (
    #|* @global-owner
    #|/src/ @src-team
    #|*.md docs@example.com
    ),
    )

    ///|
    let rule = document.find_rule("src/http/client.mbt")

    ///|
    let owners = document.owners_for("src/http/client.mbt")

    ///|
    let report = document.audit(["src/http/client.mbt", "build/tool.exe"])

    owners_for returns the effective owners. find_rule additionally exposes the matched pattern and line number. audit returns one result per input path, including uncovered paths and any parser diagnostics.

    #CLI

    moon-codeowners check <CODEOWNERS> [paths-file] [--json] moon-codeowners owners <CODEOWNERS> <repo-path> moon-codeowners explain <CODEOWNERS> <repo-path> moon-codeowners coverage <CODEOWNERS> <paths-file> [--json]

    A paths file contains one repository-relative path per line. check exits with an error when parsing or coverage checks fail, making it suitable for CI.

    #Supported CODEOWNERS semantics

    • The last matching rule takes precedence.
    • * and ? do not cross /.
    • ** may cross directory boundaries.
    • A leading / anchors a pattern to the repository root.
    • A trailing / marks a directory rule and covers its descendants.
    • A pattern containing no / matches path segments at any depth.
    • Paths are compared case-sensitively.
    • Windows-style path separators are normalized before matching.

    Following GitHub's documented limitations, these forms are rejected and reported as parse issues:

    • ! negation;
    • [abc] character classes;
    • backslash escaping.

    Owner existence, team membership, and repository permissions are intentionally outside this package. Those checks require GitHub API credentials and introduce network-dependent policy. moon-codeowners remains an offline, deterministic core that can be used by CI, review bots, and editor tooling.

    #Use cases

    1. CI gate: every changed file must resolve to an owner before a pull request is accepted.
    2. Review routing: a bot uses the matched user or team to request reviewers.
    3. Developer tooling: an editor command explains why a file is assigned to a particular owner.

    #Development

    moon check --target wasm --deny-warn moon test --target wasm --deny-warn moon fmt --check moon run cmd/main -- check .github/CODEOWNERS examples/changed-files.txt

    License: Apache-2.0.

    AuditEntry

    pub(all) struct AuditEntry {
    path : String
    owners : Array[Owner]
    matched_pattern : String?
    matched_line : Int?
    }

    The ownership result for one repository path.

    AuditReport

    pub(all) struct AuditReport {
    entries : Array[AuditEntry]
    uncovered : Array[String]
    issues : Array[ParseIssue]
    covered_count : Int
    total_count : Int
    }

    A complete coverage audit.

    Codeowners

    pub(all) struct Codeowners {
    rules : Array[Rule]
    issues : Array[ParseIssue]
    }

    A parsed CODEOWNERS document.

    Codeowners::audit

    fn Codeowners::audit(self : Codeowners, paths : Array[String]) -> AuditReport

    Codeowners::find_rule

    fn Codeowners::find_rule(self : Codeowners, path : String) -> Rule?

    Return the last matching rule. CODEOWNERS deliberately gives the last matching rule precedence.

    Codeowners::is_valid

    fn Codeowners::is_valid(self : Codeowners) -> Bool

    Codeowners::owners_for

    fn Codeowners::owners_for(self : Codeowners, path : String) -> Array[Owner]

    Return the effective owners for a repository path.

    Codeowners::parse

    fn Codeowners::parse(text : String) -> Codeowners

    Parse CODEOWNERS text. Invalid lines are skipped and collected in issues, mirroring GitHub's behavior.

    Codeowners::rule_count

    fn Codeowners::rule_count(self : Codeowners) -> Int

    Owner

    pub(all) struct Owner {
    raw : String
    kind : OwnerKind
    }

    A single CODEOWNERS owner token.

    OwnerKind

    pub(all) enum OwnerKind {
    User
    Team
    Email
    }

    The kind of owner accepted by a CODEOWNERS file.

    ParseIssue

    pub(all) struct ParseIssue {
    line : Int
    source : String
    message : String
    }

    A recoverable parsing problem. GitHub skips invalid CODEOWNERS lines, so the parser keeps valid rules and reports invalid lines separately.

    Rule

    pub(all) struct Rule {
    pattern : String
    owners : Array[Owner]
    line : Int
    }

    A parsed CODEOWNERS rule.

    normalize_path

    fn normalize_path(path : String) -> String

    Normalize repository paths accepted from Windows and Unix callers.

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io