diff --git a/documentation/secret_docs.md b/documentation/secret_docs.md index 75f25a33..028f3452 100644 --- a/documentation/secret_docs.md +++ b/documentation/secret_docs.md @@ -17,8 +17,7 @@ A secrets file stores sensitive information. Unlike the repository configuration |-|-|-|-| | `gh_token` | specify to grant the bot access to private repositories; omit for public repositories | Yes | - | | `gh_hook_token` | specify to ensure the bot only receives GitHub notifications from pre-approved repositories | Yes | - | -| `repos` | an object mapping repository URLs to repository-specific GitHub secrets | Yes | - | -| `allowed_repos` | a whitelist of repository URLs to process payloads for | Yes | all incoming payloads are processed | +| `repos` | specify to use Monorobot in multiple repositories (with support for overriding secrets) | Yes | - | | `slack_access_token` | slack bot access token to enable message posting to the workspace | Yes | try to use webhooks defined in `slack_hooks` instead | | `slack_hooks` | list of channel names and their corresponding webhook endpoint | Yes | try to use token defined in `slack_access_token` instead | | `slack_signing_secret` | specify to verify incoming slack requests | Yes | - | @@ -39,28 +38,26 @@ Refer [here](https://docs.github.com/en/free-pro-team@latest/developers/webhooks ## `repos` -If you're using Monorobot for multiple repositories that need different secrets (e.g., one on github.com and another on GitHub Enterprise), you can provide them as an object. Secrets defined here will take precedence over those defined at the top level of the secrets file. +Specifies which repositories to accept events from, along with any repository-specific overrides to secrets. If omitted, assumes all notifications come from a single repository and accepts all events. + +Secrets defined here take precedence over those defined at the top level of the secrets file. Repository URLs should be fully qualified (include the protocol), with no trailing backslash. ```json -{ - "https://github.com/ahrefs/runner" : { +[ + { + "url": "https://github.com/ahrefs/runner", "gh_token": "XXX" }, - "https://git.ahrefs.com/ahrefs/coyote" : { + { + "url": "https://git.ahrefs.com/ahrefs/coyote", "gh_token": "XXX", "gh_hook_token": "XXX" } -} +] ``` -## `allowed_repos` - -Use this option to restrict incoming notifications from GitHub to approved repository URLs. - -Repository URLs should be fully qualified (include the protocol), with no trailing backslash. - ## `slack_access_token` Required for: diff --git a/lib/action.ml b/lib/action.ml index bc25147c..744e2161 100644 --- a/lib/action.ml +++ b/lib/action.ml @@ -239,8 +239,7 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) = struct in let repo_is_allowed secrets payload = let repo = Github.repo_of_notification payload in - let allowed_repos = secrets.allowed_repos in - List.is_empty allowed_repos || List.exists allowed_repos ~f:(String.equal repo.url) + List.is_empty secrets.repos || List.exists secrets.repos ~f:(fun r -> String.equal r.url repo.url) in try%lwt let secrets = Context.get_secrets_exn ctx in diff --git a/lib/config.atd b/lib/config.atd index da8f21ff..b256a087 100644 --- a/lib/config.atd +++ b/lib/config.atd @@ -2,7 +2,6 @@ type status_rule = abstract type prefix_rule = abstract type label_rule = abstract type project_owners_rule = abstract -type 'v map_as_object = abstract (* This type of rule is used for CI build notifications. *) type status_rules = { @@ -45,24 +44,24 @@ type webhook = { channel : string; (* name of the Slack channel to post the message *) } -type gh_repo_secrets = { +type gh_secrets = { (* GitHub personal access token, if repo access requires it *) ?gh_token : string nullable; (* GitHub webhook token to secure the webhook *) ?gh_hook_token : string nullable; } +type repo_config = { + url : string; + inherit gh_secrets; +} + (* This is the structure of the secrets file which stores sensitive information, and shouldn't be checked into version control. *) type secrets = { + inherit gh_secrets; (* repo-specific secrets; overrides global values if defined for a given repo *) - ~repo_secrets : gh_repo_secrets map_as_object; - (* whitelist of repository URLs to handle notifications for *) - ~allowed_repos : string list; - (* GitHub personal access token, if repo access requires it *) - ?gh_token : string nullable; - (* GitHub webhook token to secure the webhook *) - ?gh_hook_token : string nullable; + ~repos : repo_config list; (* list of Slack webhook & channel name pairs *) ~slack_hooks : webhook list; (* Slack bot token (`xoxb-XXXX`), giving the bot capabilities to interact with the workspace *) diff --git a/lib/context.ml b/lib/context.ml index bfc345a1..d3b94cde 100644 --- a/lib/context.ml +++ b/lib/context.ml @@ -16,7 +16,6 @@ type t = { } let default_config_filename = "monorobot.json" - let default_secrets_filepath = "secrets.json" let make ?config_filename ?secrets_filepath ?state_filepath () = @@ -44,14 +43,14 @@ let find_repo_config_exn ctx repo_url = let set_repo_config ctx repo_url config = Stringtbl.set ctx.config ~key:repo_url ~data:config let gh_token_of_secrets (secrets : Config_t.secrets) repo_url = - match Map.find secrets.repo_secrets repo_url with + match List.find secrets.repos ~f:(fun r -> String.equal r.Config_t.url repo_url) with | None -> secrets.gh_token - | Some repo_secrets -> repo_secrets.gh_token + | Some repos -> repos.gh_token let gh_hook_token_of_secrets (secrets : Config_t.secrets) repo_url = - match Map.find secrets.repo_secrets repo_url with + match List.find secrets.repos ~f:(fun r -> String.equal r.Config_t.url repo_url) with | None -> secrets.gh_hook_token - | Some repo_secrets -> repo_secrets.gh_hook_token + | Some repos -> repos.gh_hook_token let hook_of_channel ctx channel_name = let secrets = get_secrets_exn ctx in