Skip to content

Commit 1365d9a

Browse files
committed
move project atd bindings into separate files based on use case
state types are in `state.atd`; config options (both repo + secret) are in `config.atd`; rule-related types are in `rule.atd`
1 parent 3eb8b8d commit 1365d9a

File tree

11 files changed

+164
-131
lines changed

11 files changed

+164
-131
lines changed

lib/action.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ open Devkit
22
open Printf
33
open Base
44
open Slack
5-
open Notabot_t
5+
open Config_t
6+
open Rule_t
67
open Config
78
open Common
89
open Github_j
@@ -15,7 +16,7 @@ type prefix_match =
1516

1617
let chan_of_prefix_rule (r : prefix_rule) = r.channel_name
1718

18-
let touching_prefix (rule : Notabot_t.prefix_rule) name =
19+
let touching_prefix (rule : prefix_rule) name =
1920
let match_lengths filename prefixes =
2021
List.filter_map
2122
~f:(fun prefix -> if String.is_prefix filename ~prefix then Some (String.length prefix) else None)

lib/config.atd

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
type status_state <ocaml from="Rule"> = abstract
2+
type prefix_rule <ocaml from="Rule"> = abstract
3+
type label_rule <ocaml from="Rule"> = abstract
4+
5+
(* This type of rule is used for CI build notifications. *)
6+
type status_rules = {
7+
?allowed_pipelines: string list option; (* keep only status events with a title matching this list *)
8+
rules: status_state;
9+
}
10+
11+
(* This type of rule is used for CI build notifications. *)
12+
type prefix_rules = {
13+
?default_channel: string nullable; (* if none of the rules is matching *)
14+
rules: prefix_rule list;
15+
}
16+
17+
(* This type of rule is used for events that must be routed based on the
18+
files they are related to. *)
19+
type label_rules = {
20+
?default_channel: string nullable; (* if none of the rules is matching *)
21+
rules: label_rule list;
22+
}
23+
24+
(* This is the structure of the repository configuration file. It should be at the
25+
root of the monorepo, on the main branch. *)
26+
type config = {
27+
prefix_rules : prefix_rules;
28+
label_rules : label_rules;
29+
status_rules : status_rules;
30+
?main_branch_name: string option; (* used to filter out notifications about merges of main branch into other branches *)
31+
?offline: string option; (* where to find github api data when http calls are not allowed *)
32+
}
33+
34+
(* This specifies the Slack webhook to query to post to the channel with the given name *)
35+
type webhook = {
36+
url : string; (* url to call to send the message *)
37+
channel : string; (* name of the channel where the message will be posted *)
38+
}
39+
40+
(* This is the structure of the secrets file which stores sensitive information, and
41+
shouldn't be checked into version control. *)
42+
type secrets = {
43+
slack_hooks : webhook list;
44+
?gh_token: string option; (* must not be specified for public repositories *)
45+
?gh_webhook_secret: string option; (* if not specified - signatures will not be checked *)
46+
}

lib/config.ml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,35 +13,35 @@ type status_rules = {
1313

1414
type t = {
1515
chans : string Chan_map.t;
16-
prefix_rules : Notabot_t.prefix_rules;
17-
label_rules : Notabot_t.label_rules;
16+
prefix_rules : Config_t.prefix_rules;
17+
label_rules : Config_t.label_rules;
1818
gh_webhook_secret : string option;
1919
main_branch_name : string option;
2020
gh_token : string option;
2121
offline : string option;
2222
status_rules : status_rules;
2323
}
2424

25-
let make (json_config : Notabot_t.config) (secrets : Notabot_t.secrets) =
25+
let make (json_config : Config_t.config) (secrets : Config_t.secrets) =
2626
let chans =
2727
List.fold_left
28-
(fun acc (webhook : Notabot_t.webhook) ->
28+
(fun acc (webhook : Config_t.webhook) ->
2929
match Chan_map.find_opt webhook.channel acc with
3030
| None -> Chan_map.add webhook.channel webhook.url acc
3131
| Some c -> Exn.fail "chan %s is defined multiple time in the config" c)
3232
Chan_map.empty secrets.slack_hooks
3333
in
3434
let () =
3535
List.iteri
36-
(fun i ({ channel_name; _ } : Notabot_t.prefix_rule) ->
36+
(fun i ({ channel_name; _ } : Config_t.prefix_rule) ->
3737
match Chan_map.find_opt channel_name chans with
3838
| None -> Exn.fail "chan %s in prefix_rules %d is missing from slack_hooks" channel_name i
3939
| Some _ -> ())
4040
json_config.prefix_rules.rules
4141
in
4242
let () =
4343
List.iteri
44-
(fun i ({ channel_name; _ } : Notabot_t.label_rule) ->
44+
(fun i ({ channel_name; _ } : Config_t.label_rule) ->
4545
match Chan_map.find_opt channel_name chans with
4646
| None -> Exn.fail "chan %s in labels_rules %d is missing from slack_hooks" channel_name i
4747
| Some _ -> ())
@@ -96,9 +96,9 @@ let make (json_config : Notabot_t.config) (secrets : Notabot_t.secrets) =
9696
status_rules;
9797
}
9898

99-
let load_config_file ~config_path = Notabot_j.config_of_string @@ Stdio.In_channel.read_all config_path
99+
let load_config_file ~config_path = Config_j.config_of_string @@ Stdio.In_channel.read_all config_path
100100

101-
let load_secrets_file ~secrets_path = Notabot_j.secrets_of_string @@ Stdio.In_channel.read_all secrets_path
101+
let load_secrets_file ~secrets_path = Config_j.secrets_of_string @@ Stdio.In_channel.read_all secrets_path
102102

103103
let load ~config_path ~secrets_path =
104104
let config = load_config_file ~config_path in

lib/context.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ type data = {
2323
}
2424

2525
type t = {
26-
mutable state : Notabot_t.state;
26+
mutable state : State_t.state;
2727
mutable cfg : Config.t;
28-
secrets : Notabot_t.secrets;
28+
secrets : Config_t.secrets;
2929
data : data;
3030
}
3131

3232
type context_thunk = {
33-
secrets : Notabot_j.secrets;
33+
secrets : Config_t.secrets;
3434
thunk : ?req:Github.t -> unit -> t Lwt.t;
3535
mutable ctx : t option;
3636
}
@@ -86,7 +86,7 @@ let update_and_get_state ctx event =
8686
update_state ctx event;
8787
ctx.state
8888

89-
let make_with_secrets ~state_path ~cfg_args ~secrets_path ~(secrets : Notabot_t.secrets) ?(disable_write = false)
89+
let make_with_secrets ~state_path ~cfg_args ~secrets_path ~(secrets : Config_t.secrets) ?(disable_write = false)
9090
?(cfg_action_after_refresh = fun _ -> ()) ()
9191
=
9292
let data_cfg_path, cfg_source, cfg_json, cfg_filename =

lib/context.mli

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,14 @@ type data = {
1919
}
2020

2121
type t = {
22-
mutable state : Notabot_t.state;
22+
mutable state : State_t.state;
2323
mutable cfg : Config.t;
24-
secrets : Notabot_t.secrets;
24+
secrets : Config_t.secrets;
2525
data : data;
2626
}
2727

2828
type context_thunk = {
29-
secrets : Notabot_j.secrets;
29+
secrets : Config_t.secrets;
3030
thunk : ?req:Github.t -> unit -> t Lwt.t;
3131
mutable ctx : t option;
3232
}
@@ -39,17 +39,17 @@ val change_remote_url : string -> t -> Github.t -> unit Lwt.t
3939

4040
val refresh_state : t -> unit
4141

42-
val refresh_and_get_state : t -> Notabot_t.state
42+
val refresh_and_get_state : t -> State_t.state
4343

4444
val update_state : t -> Github.t -> unit
4545

46-
val update_and_get_state : t -> Github.t -> Notabot_t.state
46+
val update_and_get_state : t -> Github.t -> State_t.state
4747

4848
val make_with_secrets
4949
: state_path:string ->
5050
cfg_args:cfg_make_args ->
5151
secrets_path:string ->
52-
secrets:Notabot_t.secrets ->
52+
secrets:Config_t.secrets ->
5353
?disable_write:bool ->
5454
?cfg_action_after_refresh:(Config.t -> unit) ->
5555
unit ->

lib/dune

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,37 @@
3131
(run atdgen -j -j-std %{deps})))
3232

3333
(rule
34-
(targets notabot_t.ml notabot_t.mli)
35-
(deps notabot.atd)
34+
(targets rule_t.ml rule_t.mli)
35+
(deps rule.atd)
3636
(action
3737
(run atdgen -t %{deps})))
3838

3939
(rule
40-
(targets notabot_j.ml notabot_j.mli)
41-
(deps notabot.atd)
40+
(targets rule_j.ml rule_j.mli)
41+
(deps rule.atd)
42+
(action
43+
(run atdgen -j -j-std %{deps})))
44+
45+
(rule
46+
(targets config_t.ml config_t.mli)
47+
(deps config.atd)
48+
(action
49+
(run atdgen -t %{deps})))
50+
51+
(rule
52+
(targets config_j.ml config_j.mli)
53+
(deps config.atd)
54+
(action
55+
(run atdgen -j -j-std %{deps})))
56+
57+
(rule
58+
(targets state_t.ml state_t.mli)
59+
(deps state.atd)
60+
(action
61+
(run atdgen -t %{deps})))
62+
63+
(rule
64+
(targets state_j.ml state_j.mli)
65+
(deps state.atd)
4266
(action
4367
(run atdgen -j -j-std %{deps})))

lib/github.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ let config_of_content_api_response response =
8989
match response.encoding with
9090
| "base64" ->
9191
Lwt.return
92-
@@ Notabot_j.config_of_string
92+
@@ Config_j.config_of_string
9393
@@ decode_string_pad
9494
@@ String.concat
9595
@@ String.split_lines

lib/notabot.atd

Lines changed: 0 additions & 95 deletions
This file was deleted.

lib/rule.atd

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
type tristate = [ True | False | Once <json name="once"> ] <ocaml repr="classic"> <json adapter.ocaml="Common.Tristate">
2+
3+
type status_state = {
4+
success: tristate;
5+
failure: bool;
6+
pending: bool;
7+
error: bool;
8+
?cancelled: string option; (* if specified, it will use the string as regex to match the description from the payload to determine if the status_state is cancelled *)
9+
}
10+
11+
(* A filename matches a prefix rule with the channel name if it isn't in the ignore
12+
list and it is in the allow list. If multiple prefix rules match for a given
13+
file, the one to match with the longest prefix is used.
14+
15+
If a commit affects 3 files:
16+
- some/dir/a
17+
- some/dir/b
18+
- some/other/dir/c
19+
20+
And we are only interested by commits affecting files in some/dir
21+
22+
allow should be ["some/dir"]
23+
24+
or
25+
26+
ignore should be ["some/other"]
27+
*)
28+
type prefix_rule = {
29+
allow : string list; (* empty list means match any *)
30+
~ignore : string list;
31+
channel_name <json name="channel"> : string;
32+
}
33+
34+
(* A payload matches a label rule with a channel name if absent from the ignore list
35+
and present in the allow list. *)
36+
type label_rule = {
37+
allow : string list;
38+
~ignore : string list;
39+
channel_name <json name="channel"> : string;
40+
}

lib/state.atd

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
type build_state = [
2+
| Success
3+
| Failure
4+
] <ocaml repr="classic">
5+
6+
type branch_info = {
7+
last_build_state : build_state; (* if unknown or not built before, set to 'Failure' *)
8+
updated_at : string;
9+
}
10+
11+
(* The serializable runtime state of the bot *)
12+
type state = {
13+
pipeline_statuses : (string * branch_info) list;
14+
}

0 commit comments

Comments
 (0)