Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

88 linesCodeBlameRaw
1/**
2 * CODEOWNERS: who owns which paths of a repository, read from the branch a
3 * pull request merges into. Mirrors `crates/contracts/src/codeowners.rs`,
4 * which holds the parser and the rules.
5 */
6
7/** Where the file is looked for, first found wins. */
8export const CODEOWNERS_LOCATIONS = [".g1t/CODEOWNERS", ".github/CODEOWNERS", "CODEOWNERS", "docs/CODEOWNERS", ".gitlab/CODEOWNERS"] as const;
9
10/** Whether `path` is one of the places a CODEOWNERS file is read from. */
11export function isCodeownersPath(path: string): boolean {
12 return (CODEOWNERS_LOCATIONS as readonly string[]).includes(path);
13}
14
15export type CodeownersErrorKind =
16 | "too_large"
17 | "negation"
18 | "character_range"
19 | "bad_pattern"
20 | "bad_owner"
21 | "bad_section"
22 | "unknown_user"
23 | "unknown_team"
24 | "unknown_email"
25 | "no_write_access"
26 | "team_no_access";
27
28/** One problem with a CODEOWNERS file, on a line (0 for the whole file). */
29export type CodeownersError = {
30 line: number;
31 kind: CodeownersErrorKind;
32 /** The owner or pattern at fault, as written. */
33 token: string | null;
34 message: string;
35};
36
37/** A CODEOWNERS file at one branch, checked like a linter. */
38export type CodeownersReport = {
39 /** Where it was found; null when there is none. */
40 path: string | null;
41 ref: string;
42 size: number;
43 rules: number;
44 sections: string[];
45 errors: CodeownersError[];
46};
47
48/** Where one rule's review stands on a pull request. */
49export type OwnerReview = {
50 /** The section's name; null for rules before any section. */
51 section: string | null;
52 line: number;
53 pattern: string;
54 /** Owners as written: `@ana`, `@acme/backend`, `ana@example.com`. */
55 owners: string[];
56 files: string[];
57 optional: boolean;
58 required: number;
59 approved_by: string[];
60 changes_requested_by: string[];
61 satisfied: boolean;
62};
63
64/** Who owns what a pull request changes, and whose approval is still needed. */
65export type PullCodeOwners = {
66 path: string;
67 /** Whether branch protection requires code owners' approval. */
68 required: boolean;
69 reviews: OwnerReview[];
70 /** What still stands in the way; null when nothing does. */
71 missing: string | null;
72 errors: number;
73};
74
75/** A short label for an error kind, for the errors view. */
76export const CODEOWNERS_ERROR_LABELS: Record<CodeownersErrorKind, string> = {
77 too_large: "Too large",
78 negation: "Negation",
79 character_range: "Character range",
80 bad_pattern: "Bad pattern",
81 bad_owner: "Bad owner",
82 bad_section: "Bad section",
83 unknown_user: "Unknown user",
84 unknown_team: "Unknown team",
85 unknown_email: "Unknown email",
86 no_write_access: "No write access",
87 team_no_access: "Team without access",
88};