Skip to content

Commit ead0550

Browse files
committed
allow multiple labels in project owner rule
1 parent 93ccfca commit ead0550

File tree

4 files changed

+27
-8
lines changed

4 files changed

+27
-8
lines changed

documentation/config_docs.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ You can optionally provide a **status condition** to specify additional requirem
251251

252252
In GitHub, ["code owners"](https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners) are the users/teams whose review is automatically requested when a PR modifying code in a given directory is opened. **Project owners** behave similarly, with two differences.
253253

254-
- Owners are defined _per PR label_, instead of _per directory_ (or directory pattern)
254+
- Owners are defined _per PR label (or set of labels)_, instead of _per directory_ (or directory pattern)
255255
- Definitions should be placed in the per-repo Monorobot configuration file, instead of a `CODEOWNERS` file
256256

257257
Draft PR behavior is similar to code owners. From GitHub documentation:
@@ -272,7 +272,7 @@ Note that the owner of the personal access token cannot be a project owner, as G
272272
"owners": ["user1", "user2", "org/team1"]
273273
},
274274
{
275-
"label": "Label 2",
275+
"labels": ["Label 2", "Label 3"], # rule matches if PR has all labels in the list
276276
"owners": ["org/team2", "user3"]
277277
}
278278
]

lib/github.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ let gh_link_of_string url_str =
163163
| _ | (exception Re2.Exceptions.Regex_match_failed _) -> None
164164

165165
let get_project_owners (pr : pull_request) ({ rules } : Config_t.project_owners) =
166-
List.fold_left pr.labels ~init:[] ~f:(fun acc l -> List.rev_append (Rule.Project_owners.match_rules l ~rules) acc)
166+
Rule.Project_owners.match_rules pr.labels rules
167167
|> List.dedup_and_sort ~compare:String.compare
168168
|> List.partition_map ~f:(fun reviewer ->
169169
try

lib/rule.atd

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ type label_rule = {
8686
- teams: "org/team"
8787
*)
8888
type project_owners_rule = {
89-
label: string;
89+
?label: string option;
90+
~labels <ocaml default="[]">: string list;
9091
owners: string list;
9192
}

lib/rule.ml

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,26 @@ module Label = struct
127127
end
128128

129129
module Project_owners = struct
130-
let match_rules (l : Github_t.label) ~rules =
131-
match List.find rules ~f:(fun { label; _ } -> String.equal label l.name) with
132-
| Some { owners = []; _ } | None -> []
133-
| Some { owners; _ } -> owners
130+
module SS = Caml.Set.Make (String)
131+
132+
let match_rules pr_labels rules =
133+
match pr_labels with
134+
| [] -> []
135+
| _ :: _ ->
136+
let pr_labels_set = List.map ~f:(fun (l : Github_t.label) -> l.name) pr_labels |> SS.of_list in
137+
let do_match { label; labels; owners } =
138+
let labels =
139+
match labels with
140+
| [] -> Option.value_map label ~f:(fun l -> [ l ]) ~default:[]
141+
| labels -> labels
142+
in
143+
match owners with
144+
| [] -> false
145+
| _ :: _ ->
146+
match labels with
147+
| [] -> false
148+
| [ label ] -> SS.mem label pr_labels_set
149+
| labels -> SS.subset (SS.of_list labels) pr_labels_set
150+
in
151+
List.find ~f:do_match rules |> Option.value_map ~default:[] ~f:(fun l -> l.owners)
134152
end

0 commit comments

Comments
 (0)