Skip to content

Commit 958e29f

Browse files
committed
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 9488332 commit 958e29f

File tree

4 files changed

+36
-8
lines changed

4 files changed

+36
-8
lines changed

lib/action.ml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,17 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) = struct
206206
| _ -> Lwt.return @@ Ok ()
207207

208208
let process_github_notification (ctx : Context.t) headers body =
209+
let validate_signature secrets payload =
210+
let repo = Github.repo_of_notification payload in
211+
let signing_key = Context.gh_hook_token_of_secrets secrets repo.url in
212+
Github.validate_signature ?signing_key ~headers body
213+
in
209214
try%lwt
210215
let secrets = Context.get_secrets_exn ctx in
211216
match Github.parse_exn headers body with
212217
| exception exn -> Exn_lwt.fail ~exn "failed to parse payload"
213218
| payload ->
214-
match Github.validate_signature ?signing_key:secrets.gh_hook_token ~headers body with
219+
match validate_signature secrets payload with
215220
| Error e -> action_error e
216221
| Ok () ->
217222
( match%lwt refresh_repo_config ctx payload with

lib/api_remote.ml

Lines changed: 8 additions & 6 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,24 @@ 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 get_resource (ctx : Context.t) ~(repo : Github_t.repository) url =
4849
let secrets = Context.get_secrets_exn ctx in
49-
let headers = build_headers ?token:secrets.gh_token () in
50+
let token = Context.gh_token_of_secrets secrets repo.url in
51+
let headers = build_headers ?token () in
5052
match%lwt http_request ~headers `GET url with
5153
| Ok res -> Lwt.return @@ Ok res
5254
| Error e -> Lwt.return @@ fmt_error "error while querying remote: %s\nfailed to get resource from %s" e url
5355

5456
let get_api_commit ~(ctx : Context.t) ~repo ~sha =
55-
let%lwt res = commits_url ~repo ~sha |> get_resource ctx in
57+
let%lwt res = commits_url ~repo ~sha |> get_resource ~repo ctx in
5658
Lwt.return @@ Result.map res ~f:Github_j.api_commit_of_string
5759

5860
let get_pull_request ~(ctx : Context.t) ~repo ~number =
59-
let%lwt res = pulls_url ~repo ~number |> get_resource ctx in
61+
let%lwt res = pulls_url ~repo ~number |> get_resource ~repo ctx in
6062
Lwt.return @@ Result.map res ~f:Github_j.pull_request_of_string
6163

6264
let get_issue ~(ctx : Context.t) ~repo ~number =
63-
let%lwt res = issues_url ~repo ~number |> get_resource ctx in
65+
let%lwt res = issues_url ~repo ~number |> get_resource ~repo ctx in
6466
Lwt.return @@ Result.map res ~f:Github_j.issue_of_string
6567
end
6668

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 = {
@@ -36,9 +37,18 @@ type webhook = {
3637
channel : string; (* name of the Slack channel to post the message *)
3738
}
3839

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

lib/context.ml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,16 @@ let get_secrets_exn ctx =
3434
| None -> context_error "secrets is uninitialized"
3535
| Some secrets -> secrets
3636

37+
let gh_token_of_secrets (secrets : Config_t.secrets) repo_url =
38+
match Map.find secrets.repos repo_url with
39+
| None -> secrets.gh_token
40+
| Some repo_secrets -> repo_secrets.gh_token
41+
42+
let gh_hook_token_of_secrets (secrets : Config_t.secrets) repo_url =
43+
match Map.find secrets.repos repo_url with
44+
| None -> secrets.gh_hook_token
45+
| Some repo_secrets -> repo_secrets.gh_hook_token
46+
3747
let hook_of_channel ctx channel_name =
3848
let secrets = get_secrets_exn ctx in
3949
match List.find secrets.slack_hooks ~f:(fun webhook -> String.equal webhook.channel channel_name) with
@@ -73,8 +83,9 @@ let refresh_state ctx =
7383
let print_config ctx repo_url =
7484
let cfg = State.find_repo_config_exn ctx.state repo_url in
7585
let secrets = get_secrets_exn ctx in
86+
let token = gh_hook_token_of_secrets secrets repo_url in
7687
log#info "using prefix routing:";
7788
Rule.Prefix.print_prefix_routing cfg.prefix_rules.rules;
7889
log#info "using label routing:";
7990
Rule.Label.print_label_routing cfg.label_rules.rules;
80-
log#info "signature checking %s" (if Option.is_some secrets.gh_hook_token then "enabled" else "disabled")
91+
log#info "signature checking %s" (if Option.is_some token then "enabled" else "disabled")

0 commit comments

Comments
 (0)