Skip to content

Commit ff4b714

Browse files
committed
cfg: allow repo-specific configuration of gh_token and gh_hook_token
Define custom getters for retrieving GH secret values. As the getter for each token type defaults to looking for a global value if a repo-specific vaue isn't found, existing deployments don't need to change.
1 parent d512d05 commit ff4b714

File tree

4 files changed

+37
-14
lines changed

4 files changed

+37
-14
lines changed

lib/action.ml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,16 +211,17 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) = struct
211211
| _ -> Lwt.return @@ Ok ()
212212

213213
let process_github_notification (ctx : Context.t) headers body =
214-
let validate_signature secrets =
215-
let signing_key = secrets.gh_hook_token in
214+
let validate_signature secrets payload =
215+
let repo = Github.repo_of_notification payload in
216+
let signing_key = Context.gh_hook_token_of_secrets secrets repo.url in
216217
Github.validate_signature ?signing_key ~headers body
217218
in
218219
try%lwt
219220
let secrets = Context.get_secrets_exn ctx in
220221
match Github.parse_exn headers body with
221222
| exception exn -> Exn_lwt.fail ~exn "failed to parse payload"
222223
| payload ->
223-
match validate_signature secrets with
224+
match validate_signature secrets payload with
224225
| Error e -> action_error e
225226
| Ok () ->
226227
( match%lwt refresh_repo_config ctx payload with

lib/api_remote.ml

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ module Github : Api.Github = struct
2323
let get_config ~(ctx : Context.t) ~repo =
2424
let secrets = Context.get_secrets_exn ctx in
2525
let url = contents_url ~repo ~path:ctx.config_filename in
26-
let headers = build_headers ?token:secrets.gh_token () in
26+
let token = Context.gh_token_of_secrets secrets repo.url in
27+
let headers = build_headers ?token () in
2728
match%lwt http_request ~headers `GET url with
2829
| Error e -> Lwt.return @@ fmt_error "error while querying remote: %s\nfailed to get config from file %s" e url
2930
| Ok res ->
@@ -44,23 +45,23 @@ module Github : Api.Github = struct
4445
@@ fmt_error "unexpected encoding '%s' in Github response\nfailed to get config from file %s" encoding url
4546
)
4647

47-
let get_resource (ctx : Context.t) url =
48-
let secrets = Context.get_secrets_exn ctx in
49-
let headers = build_headers ?token:secrets.gh_token () in
48+
let get_resource secrets repo_url url =
49+
let token = Context.gh_token_of_secrets secrets repo_url in
50+
let headers = build_headers ?token () in
5051
match%lwt http_request ~headers `GET url with
5152
| Ok res -> Lwt.return @@ Ok res
5253
| Error e -> Lwt.return @@ fmt_error "error while querying remote: %s\nfailed to get resource from %s" e url
5354

54-
let get_api_commit ~(ctx : Context.t) ~repo ~sha =
55-
let%lwt res = commits_url ~repo ~sha |> get_resource ctx in
55+
let get_api_commit ~(ctx : Context.t) ~(repo : Github_t.repository) ~sha =
56+
let%lwt res = commits_url ~repo ~sha |> get_resource (Context.get_secrets_exn ctx) repo.url in
5657
Lwt.return @@ Result.map res ~f:Github_j.api_commit_of_string
5758

58-
let get_pull_request ~(ctx : Context.t) ~repo ~number =
59-
let%lwt res = pulls_url ~repo ~number |> get_resource ctx in
59+
let get_pull_request ~(ctx : Context.t) ~(repo : Github_t.repository) ~number =
60+
let%lwt res = pulls_url ~repo ~number |> get_resource (Context.get_secrets_exn ctx) repo.url in
6061
Lwt.return @@ Result.map res ~f:Github_j.pull_request_of_string
6162

62-
let get_issue ~(ctx : Context.t) ~repo ~number =
63-
let%lwt res = issues_url ~repo ~number |> get_resource ctx in
63+
let get_issue ~(ctx : Context.t) ~(repo : Github_t.repository) ~number =
64+
let%lwt res = issues_url ~repo ~number |> get_resource (Context.get_secrets_exn ctx) repo.url in
6465
Lwt.return @@ Result.map res ~f:Github_j.issue_of_string
6566
end
6667

lib/config.atd

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
type status_rule <ocaml from="Rule"> = abstract
22
type prefix_rule <ocaml from="Rule"> = abstract
33
type label_rule <ocaml from="Rule"> = abstract
4+
type 'v map_as_object <ocaml from="Common"> = abstract
45

56
(* This type of rule is used for CI build notifications. *)
67
type status_rules = {
@@ -37,9 +38,18 @@ type webhook = {
3738
channel : string; (* name of the Slack channel to post the message *)
3839
}
3940

41+
type gh_repo_secrets = {
42+
(* GitHub personal access token, if repo access requires it *)
43+
?gh_token : string nullable;
44+
(* GitHub webhook token to secure the webhook *)
45+
?gh_hook_token : string nullable;
46+
}
47+
4048
(* This is the structure of the secrets file which stores sensitive information, and
4149
shouldn't be checked into version control. *)
4250
type secrets = {
51+
(* repo-specific secrets; overrides global values if defined for a given repo *)
52+
~repo_secrets <ocaml default="Common.StringMap.empty"> : gh_repo_secrets map_as_object;
4353
(* GitHub personal access token, if repo access requires it *)
4454
?gh_token : string nullable;
4555
(* GitHub webhook token to secure the webhook *)

lib/context.ml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@ let find_repo_config_exn ctx repo_url =
4343

4444
let set_repo_config ctx repo_url config = Stringtbl.set ctx.config ~key:repo_url ~data:config
4545

46+
let gh_token_of_secrets (secrets : Config_t.secrets) repo_url =
47+
match Map.find secrets.repo_secrets repo_url with
48+
| None -> secrets.gh_token
49+
| Some repo_secrets -> repo_secrets.gh_token
50+
51+
let gh_hook_token_of_secrets (secrets : Config_t.secrets) repo_url =
52+
match Map.find secrets.repo_secrets repo_url with
53+
| None -> secrets.gh_hook_token
54+
| Some repo_secrets -> repo_secrets.gh_hook_token
55+
4656
let hook_of_channel ctx channel_name =
4757
let secrets = get_secrets_exn ctx in
4858
match List.find secrets.slack_hooks ~f:(fun webhook -> String.equal webhook.channel channel_name) with
@@ -93,8 +103,9 @@ let refresh_state ctx =
93103
let print_config ctx repo_url =
94104
let cfg = find_repo_config_exn ctx repo_url in
95105
let secrets = get_secrets_exn ctx in
106+
let token = gh_hook_token_of_secrets secrets repo_url in
96107
log#info "using prefix routing:";
97108
Rule.Prefix.print_prefix_routing cfg.prefix_rules.rules;
98109
log#info "using label routing:";
99110
Rule.Label.print_label_routing cfg.label_rules.rules;
100-
log#info "signature checking %s" (if Option.is_some secrets.gh_hook_token then "enabled" else "disabled")
111+
log#info "signature checking %s" (if Option.is_some token then "enabled" else "disabled")

0 commit comments

Comments
 (0)