summaryrefslogtreecommitdiff
path: root/docs/handbook/ci/codeowners.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/handbook/ci/codeowners.md')
-rw-r--r--docs/handbook/ci/codeowners.md370
1 files changed, 370 insertions, 0 deletions
diff --git a/docs/handbook/ci/codeowners.md b/docs/handbook/ci/codeowners.md
new file mode 100644
index 0000000000..0054a168f1
--- /dev/null
+++ b/docs/handbook/ci/codeowners.md
@@ -0,0 +1,370 @@
+# CODEOWNERS
+
+## Overview
+
+Project Tick uses a code ownership system based on the `ci/OWNERS` file. This file
+follows the same syntax as GitHub's native `CODEOWNERS` file but is stored in a
+custom location and validated by a patched version of the
+[codeowners-validator](https://github.com/mszostok/codeowners-validator) tool.
+
+The OWNERS file serves two purposes:
+1. **Automated review routing** — PR authors know who to request reviews from
+2. **Structural validation** — CI checks that referenced paths and users exist
+
+---
+
+## File Location and Format
+
+### Location
+
+```
+ci/OWNERS
+```
+
+Unlike GitHub's native CODEOWNERS (which must be in `.github/CODEOWNERS`,
+`CODEOWNERS`, or `docs/CODEOWNERS`), Project Tick stores ownership data in
+`ci/OWNERS` to keep CI infrastructure colocated.
+
+### Syntax
+
+The file uses CODEOWNERS syntax:
+
+```
+# Comments start with #
+# Pattern followed by one or more @owner references
+/path/pattern/ @owner1 @owner2
+```
+
+### Header
+
+```
+# This file describes who owns what in the Project Tick CI infrastructure.
+# Users/teams will get review requests for PRs that change their files.
+#
+# This file uses the same syntax as the natively supported CODEOWNERS file,
+# see https://help.github.com/articles/about-codeowners/ for documentation.
+#
+# Validated by ci/codeowners-validator.
+```
+
+---
+
+## Ownership Map
+
+The OWNERS file maps every major directory and subdirectory in the monorepo to
+code owners. Below is the complete ownership mapping:
+
+### GitHub Infrastructure
+
+```
+/.github/actions/change-analysis/ @YongDo-Hyun
+/.github/actions/meshmc/package/ @YongDo-Hyun
+/.github/actions/meshmc/setup-dependencies/ @YongDo-Hyun
+/.github/actions/mnv/test_artefacts/ @YongDo-Hyun
+/.github/codeql/ @YongDo-Hyun
+/.github/ISSUE_TEMPLATE/ @YongDo-Hyun
+/.github/workflows/ @YongDo-Hyun
+```
+
+### Archived Projects
+
+```
+/archived/projt-launcher/ @YongDo-Hyun
+/archived/projt-minicraft-modpack/ @YongDo-Hyun
+/archived/projt-modpack/ @YongDo-Hyun
+/archived/ptlibzippy/ @YongDo-Hyun
+```
+
+### Core Projects
+
+```
+/cgit/* @YongDo-Hyun
+/cgit/contrib/* @YongDo-Hyun
+/cgit/contrib/hooks/ @YongDo-Hyun
+/cgit/filters/ @YongDo-Hyun
+/cgit/tests/ @YongDo-Hyun
+
+/cmark/* @YongDo-Hyun
+/cmark/api_test/ @YongDo-Hyun
+/cmark/bench/ @YongDo-Hyun
+/cmark/cmake/ @YongDo-Hyun
+/cmark/data/ @YongDo-Hyun
+/cmark/fuzz/ @YongDo-Hyun
+/cmark/man/ @YongDo-Hyun
+/cmark/src/ @YongDo-Hyun
+/cmark/test/ @YongDo-Hyun
+/cmark/tools/ @YongDo-Hyun
+/cmark/wrappers/ @YongDo-Hyun
+```
+
+### Corebinutils (every utility individually owned)
+
+```
+/corebinutils/* @YongDo-Hyun
+/corebinutils/cat/ @YongDo-Hyun
+/corebinutils/chflags/ @YongDo-Hyun
+/corebinutils/chmod/ @YongDo-Hyun
+/corebinutils/contrib/* @YongDo-Hyun
+/corebinutils/contrib/libc-vis/ @YongDo-Hyun
+/corebinutils/contrib/libedit/ @YongDo-Hyun
+/corebinutils/contrib/printf/ @YongDo-Hyun
+/corebinutils/cp/ @YongDo-Hyun
+...
+/corebinutils/uuidgen/ @YongDo-Hyun
+```
+
+### Other Projects
+
+```
+/forgewrapper/* @YongDo-Hyun
+/forgewrapper/gradle/ @YongDo-Hyun
+/forgewrapper/jigsaw/ @YongDo-Hyun
+/forgewrapper/src/ @YongDo-Hyun
+
+/genqrcode/* @YongDo-Hyun
+/genqrcode/cmake/ @YongDo-Hyun
+/genqrcode/tests/ @YongDo-Hyun
+/genqrcode/use/ @YongDo-Hyun
+
+/hooks/ @YongDo-Hyun
+/images4docker/ @YongDo-Hyun
+
+/json4cpp/* @YongDo-Hyun
+/json4cpp/.reuse/ @YongDo-Hyun
+/json4cpp/cmake/ @YongDo-Hyun
+/json4cpp/docs/ @YongDo-Hyun
+/json4cpp/include/* @YongDo-Hyun
+...
+
+/libnbtplusplus/* @YongDo-Hyun
+/libnbtplusplus/include/* @YongDo-Hyun
+...
+
+/LICENSES/ @YongDo-Hyun
+
+/meshmc/* @YongDo-Hyun
+/meshmc/branding/ @YongDo-Hyun
+/meshmc/buildconfig/ @YongDo-Hyun
+/meshmc/cmake/* @YongDo-Hyun
+/meshmc/launcher/* @YongDo-Hyun
+...
+```
+
+---
+
+## Pattern Syntax
+
+### Glob Rules
+
+| Pattern | Matches |
+|---------------|------------------------------------------------------|
+| `/path/` | All files directly under `path/` |
+| `/path/*` | All files directly under `path/` (explicit) |
+| `/path/**` | All files recursively under `path/` |
+| `*.js` | All `.js` files everywhere |
+| `/path/*.md` | All `.md` files directly under `path/` |
+
+### Ownership Resolution
+
+When multiple patterns match a file, the **last matching rule** wins (just like
+Git's `.gitignore` and GitHub's native CODEOWNERS):
+
+```
+/meshmc/* @teamA # Matches all direct files
+/meshmc/launcher/* @teamB # More specific — wins for launcher files
+```
+
+A PR modifying `meshmc/launcher/main.cpp` would require review from `@teamB`.
+
+### Explicit Directory Listing
+
+The OWNERS file explicitly lists individual subdirectories rather than using `**`
+recursive globs. This is intentional:
+
+1. **Precision** — Each directory has explicit ownership
+2. **Validation** — The codeowners-validator checks that each listed path exists
+3. **Documentation** — The file serves as a directory map of the monorepo
+
+---
+
+## Validation
+
+### codeowners-validator
+
+The CI runs a patched version of `codeowners-validator` against the OWNERS file.
+The tool is built from source with Project Tick–specific patches.
+
+#### What It Validates
+
+| Check | Description |
+|-------------------------|------------------------------------------------|
+| **Path existence** | All paths in OWNERS exist in the repository |
+| **User/team existence** | All `@` references are valid GitHub users/teams|
+| **Syntax** | Pattern syntax is valid CODEOWNERS format |
+| **No orphaned patterns** | Patterns match at least one file |
+
+#### Custom Patches
+
+Two patches are applied to the upstream validator:
+
+**1. Custom OWNERS file path** (`owners-file-name.patch`)
+
+```go
+func openCodeownersFile(dir string) (io.Reader, error) {
+ if file, ok := os.LookupEnv("OWNERS_FILE"); ok {
+ return fs.Open(file)
+ }
+ // ... default CODEOWNERS paths
+}
+```
+
+Set `OWNERS_FILE=ci/OWNERS` to validate the custom location.
+
+**2. Removed write-access requirement** (`permissions.patch`)
+
+GitHub's native CODEOWNERS requires that listed users have write access to the
+repository. Project Tick's OWNERS file is used for review routing, not branch
+protection, so this check is removed:
+
+```go
+// Before: required push permission
+if t.Permissions["push"] { return nil }
+return newValidateError("Team cannot review PRs...")
+
+// After: any team membership is sufficient
+return nil
+```
+
+Also removes the `github.ScopeReadOrg` requirement from required OAuth scopes,
+allowing the validator to work with tokens generated for GitHub Apps.
+
+### Running Validation Locally
+
+```bash
+cd ci/
+nix-shell # enters the CI dev shell with codeowners-validator available
+
+# Set the custom OWNERS file path:
+export OWNERS_FILE=ci/OWNERS
+
+# Run validation:
+codeowners-validator
+```
+
+Or build and run directly:
+
+```bash
+nix-build ci/ -A codeownersValidator
+OWNERS_FILE=ci/OWNERS ./result/bin/codeowners-validator
+```
+
+---
+
+## MAINTAINERS File Relationship
+
+In addition to `ci/OWNERS`, individual projects may have a `MAINTAINERS` file
+(e.g., `archived/projt-launcher/MAINTAINERS`):
+
+```
+# MAINTAINERS
+#
+# Fields:
+# - Name: Display name
+# - GitHub: GitHub handle (with @)
+# - Email: Primary contact email
+# - Paths: Comma-separated glob patterns (repo-relative)
+
+[Mehmet Samet Duman]
+GitHub: @YongDo-Hyun
+Email: yongdohyun@mail.projecttick.org
+Paths: **
+```
+
+The `MAINTAINERS` file provides additional metadata (email, display name) that
+`OWNERS` doesn't support. The two files serve complementary purposes:
+
+| File | Purpose | Format |
+|--------------|--------------------------------------|-------------------|
+| `ci/OWNERS` | Automated review routing via CI | CODEOWNERS syntax |
+| `MAINTAINERS`| Human-readable contact information | INI-style blocks |
+
+---
+
+## Review Requirements
+
+### How Reviews Are Triggered
+
+When a PR modifies files matching an OWNERS pattern:
+
+1. The workflow identifies which owners are responsible for the changed paths
+2. Review requests are sent to the matching owners
+3. At least one approving review from a code owner is typically required before merge
+
+### Bot-Managed Reviews
+
+The CI bot (`github-actions[bot]`) manages automated reviews via `ci/github-script/reviews.js`:
+- Reviews are tagged with a `reviewKey` comment for identification
+- When issues are resolved, bot reviews are automatically dismissed or minimized
+- The `CHANGES_REQUESTED` state blocks merge until the review is dismissed
+
+---
+
+## Adding Ownership Entries
+
+### For a New Project Directory
+
+1. Add ownership patterns to `ci/OWNERS`:
+
+```
+/newproject/* @owner-handle
+/newproject/src/ @owner-handle
+/newproject/tests/ @owner-handle
+```
+
+2. List every subdirectory explicitly (not just the top-level with `**`)
+
+3. Run the validator locally:
+
+```bash
+cd ci/
+nix-shell
+OWNERS_FILE=ci/OWNERS codeowners-validator
+```
+
+4. Commit with a CI scope:
+
+```
+ci(repo): add ownership for newproject
+```
+
+### For a New Team or User
+
+Simply reference the new `@handle` in the ownership patterns:
+
+```
+/some/path/ @existing-owner @new-owner
+```
+
+The validator will check that `@new-owner` exists in the GitHub organization.
+
+---
+
+## Limitations
+
+### No Recursive Globs in Current File
+
+The current OWNERS file uses explicit directory listings rather than `/**` recursive
+globs. This means:
+- New subdirectories must be manually added to OWNERS
+- Deeply nested directories need their own entries
+- The file can grow large for projects with many subdirectories
+
+### Single Organization Scope
+
+All `@` references must be members of the repository's GitHub organization,
+or GitHub users with access to the repository.
+
+### No Per-File Patterns
+
+The file doesn't currently use file-level patterns (e.g., `*.nix @nix-team`).
+Ownership is assigned at the directory level.