diff --git a/documentation/config_docs.md b/documentation/config_docs.md index e109bb17..99534c47 100644 --- a/documentation/config_docs.md +++ b/documentation/config_docs.md @@ -1,5 +1,4 @@ # Repository Configuration -TODO add docs for dev_notifications A repository configuration file specifies how notifications should be handled for a given repository. It should be at the root of your monorepo in the main branch. The bot will look for a `.monorobot.json` file by default, but you can change this behavior with the `--config` flag. @@ -23,6 +22,15 @@ Refer [here](https://docs.github.com/en/free-pro-team@latest/developers/webhooks "git.user@gitemail.com": "user1@slackemail.com", "gh-handle": "user2@slackemail.com" }, + "notifications_configs": { + "dm_for_failing_build": { + "user1@slackemail.com": false, + "user2@slackemail.com": false + }, + "dm_after_failed_build": { + "user1@slackemail.com": true + } + }, "prefix_rules": { ... }, @@ -47,8 +55,11 @@ Refer [here](https://docs.github.com/en/free-pro-team@latest/developers/webhooks | `project_owners` | project owners config object | no project owners are defined | | `ignored_users` | list of users to be ignored on all notifications | no user is ignored | | `user_mappings` | list of mappings from git email and/or GitHub handle to Slack email | no mapping defined +| `notifications_configs` | list of configs for certain types of notifications | dm_for_failing_build defaults to true and dm_after_failed_build to false + +Note that `notifications_configs` expects to match against the email used in slack. It will respect the `user_mappings` rules and then use the resulting slack email to find the correct user id and @mention. If you are not using the `user_mappings` feature, you can directly use the slack email in the `notifications_configs` field. -Note that in `user_mappings`, git email to Slack email mappings are used for status DMs, while GitHub handle to Slack email mappings are used to get Slack mentions in comment notifications. +Also note that in `user_mappings`, git email to Slack email mappings are used for status DMs, while GitHub handle to Slack email mappings are used to get Slack mentions in comment notifications. The reason for these two separate Slack email matching schemes is that in the case of commits, the git email is available in the GitHub payload and can be used to directly match with Slack emails for status DMs (`user_mappings` can be used to manually override if there is a known mismatch between git email and Slack email). However, for actions done on GitHub itself (e.g. opening PRs, commenting, etc.), usually the only thing available is the GitHub username. To get the email in these cases, a user will have to go to settings and set their email to public, which is (1) hard to enforce if there are many working on the monorepo, and (2) might be undesirable for privacy reasons. diff --git a/lib/action.ml b/lib/action.ml index 30a12105..9df06e71 100644 --- a/lib/action.ml +++ b/lib/action.ml @@ -164,15 +164,16 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) = struct | Ok res -> let is_failing_build = Util.Build.is_failing_build n in let is_failed_build = Util.Build.is_failed_build n in - (* Check if config holds Github to Slack email mapping for the commit author *) + (* Check if config holds Github to Slack email mapping for the commit author. The user id we get from slack + is not an email, so we need to see if we can map the commit author email to a slack user's email. *) let author = List.assoc_opt email cfg.user_mappings |> Option.default email in let dm_after_failed_build = - List.assoc_opt author cfg.dev_notifications.dm_after_failed_build + List.assoc_opt author cfg.notifications_configs.dm_after_failed_build |> (* dm_after_failed_build is opt in *) Option.default false in let dm_for_failing_build = - List.assoc_opt author cfg.dev_notifications.dm_for_failing_build + List.assoc_opt author cfg.notifications_configs.dm_for_failing_build |> (* dm_for_failing_build is opt out *) Option.default true in @@ -180,9 +181,8 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) = struct | true -> (* if we send a dm for a failing build and we want another dm after the build is finished, we don't set the pipeline commit immediately. Otherwise, we wouldn't be able to notify later *) - if (is_failing_build && not dm_after_failed_build) || is_failed_build (* TODO: test double opt in *) then + if (is_failing_build && not dm_after_failed_build) || is_failed_build then State.set_repo_pipeline_commit ctx.state n; - (* To send a DM, channel parameter is set to the user id of the recipient *) Lwt.return [ Status_notification.User res.user.id ] | false -> Lwt.return []) | Error e -> diff --git a/lib/config.atd b/lib/config.atd index b5130e53..68903f61 100644 --- a/lib/config.atd +++ b/lib/config.atd @@ -35,7 +35,7 @@ type project_owners = { rules: project_owners_rule list; } -type dev_notifications = { +type notifications_configs = { ~dm_for_failing_build : (string * bool) list ; ~dm_after_failed_build : (string * bool) list } @@ -50,7 +50,7 @@ type config = { ~ignored_users : string list; (* list of ignored users *) ?main_branch_name : string nullable; (* the name of the main branch; used to filter out notifications about merges of main branch into other branches *) ~user_mappings : (string * string) list ; (* list of github to slack profile mappings *) - ~dev_notifications : dev_notifications; + ~notifications_configs : notifications_configs; } (* This specifies the Slack webhook to query to post to the channel with the given name *) diff --git a/lib/slack.ml b/lib/slack.ml index ec9fc828..1da56400 100644 --- a/lib/slack.ml +++ b/lib/slack.ml @@ -401,7 +401,6 @@ let generate_status_notification ~(ctx : Context.t) ?slack_user_id (cfg : Config match Build.is_failed_build notification && (is_failed_builds_channel || Status_notification.is_user channel) with | false -> [] | true -> - (* TODO: don't send @mention on DM notification for failed builds *) let repo_state = State.find_or_add_repo ctx.state repository.url in let pipeline = notification.context in let slack_step_link (s : State_t.failed_step) =