Skip to content

Commit cc32884

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 0a81d7f commit cc32884

File tree

4 files changed

+37
-15
lines changed

4 files changed

+37
-15
lines changed

lib/action.ml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) = struct
106106
| false -> Lwt.return default
107107
| true ->
108108
let sha = n.commit.sha in
109-
let repo = n.repository in
110109
( match%lwt Github_api.get_api_commit ~ctx ~repo ~sha with
111110
| Error e -> action_error e
112111
| Ok commit -> Lwt.return @@ partition_commit cfg commit.files
@@ -206,16 +205,17 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) = struct
206205
| _ -> Lwt.return @@ Ok ()
207206

208207
let process_github_notification (ctx : Context.t) headers body =
209-
let validate_signature secrets =
210-
let signing_key = secrets.gh_hook_token in
208+
let validate_signature secrets payload =
209+
let repo = Github.repo_of_notification payload in
210+
let signing_key = Context.gh_hook_token_of_secrets secrets repo.url in
211211
Github.validate_signature ?signing_key ~headers body
212212
in
213213
try%lwt
214214
let secrets = Context.get_secrets_exn ctx in
215215
match Github.parse_exn headers body with
216216
| exception exn -> Exn_lwt.fail ~exn "failed to parse payload"
217217
| payload ->
218-
match validate_signature secrets with
218+
match validate_signature secrets payload with
219219
| Error e -> action_error e
220220
| Ok () ->
221221
( 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 = {
@@ -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
@@ -43,6 +43,16 @@ let find_repo_config_exn ctx repo_url =
4343

4444
let set_repo_config ctx repo_url config = Hashtbl.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.repos 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.repos 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
@@ -94,8 +104,9 @@ let refresh_state ctx =
94104
let print_config ctx repo_url =
95105
let cfg = find_repo_config_exn ctx repo_url in
96106
let secrets = get_secrets_exn ctx in
107+
let token = gh_hook_token_of_secrets secrets repo_url in
97108
log#info "using prefix routing:";
98109
Rule.Prefix.print_prefix_routing cfg.prefix_rules.rules;
99110
log#info "using label routing:";
100111
Rule.Label.print_label_routing cfg.label_rules.rules;
101-
log#info "signature checking %s" (if Option.is_some secrets.gh_hook_token then "enabled" else "disabled")
112+
log#info "signature checking %s" (if Option.is_some token then "enabled" else "disabled")

0 commit comments

Comments
 (0)