Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CI status updates sent as direct message to author of commit #134

Merged
merged 7 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion lib/action.ml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,13 @@ module Action (Github_api : Api.Github) (Slack_api : Api.Slack) = struct
let current_status = n.state in
let rules = cfg.status_rules.rules in
let action_on_match (branches : branch list) =
let default = Option.to_list cfg.prefix_rules.default_channel in
let%lwt default =
match%lwt Slack_api.lookup_user ~ctx ~email:n.commit.commit.author.email with
(* To send a DM, channel parameter is set to the user id of the recipient *)
| Ok res -> Lwt.return [ res.user.id ]
| Error e -> log#error "%s: nowhere to send status update" e;
Lwt.return []
in
let%lwt () = State.set_repo_pipeline_status ctx.state repo.url ~pipeline ~branches ~status:current_status in
match List.is_empty branches with
| true -> Lwt.return []
Expand Down
2 changes: 2 additions & 0 deletions lib/api.ml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ module type Github = sig
end

module type Slack = sig
val lookup_user : ctx:Context.t -> email:string -> lookup_user_res slack_response Lwt.t

val send_notification : ctx:Context.t -> msg:post_message_req -> unit slack_response Lwt.t

val send_chat_unfurl
Expand Down
10 changes: 10 additions & 0 deletions lib/api_local.ml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ end

(** The base implementation for local check payload debugging and mocking tests *)
module Slack_base : Api.Slack = struct
let lookup_user ~ctx:_ ~email:_ = Lwt.return @@ Error "undefined for local setup"
let send_notification ~ctx:_ ~msg:_ = Lwt.return @@ Error "undefined for local setup"
let send_chat_unfurl ~ctx:_ ~channel:_ ~ts:_ ~unfurls:_ () = Lwt.return @@ Error "undefined for local setup"
let send_auth_test ~ctx:_ () = Lwt.return @@ Error "undefined for local setup"
Expand All @@ -61,6 +62,15 @@ end
module Slack : Api.Slack = struct
include Slack_base

let lookup_user ~ctx:_ ~email =
let msg = {Slack_t.email = email} in
let json = msg |> Slack_j.string_of_lookup_user_req |> Yojson.Basic.from_string |> Yojson.Basic.pretty_to_string in
Stdio.printf "looking up slack user by email %s\n" email;
Stdio.printf "%s\n" json;
let mock_user = {Slack_t.id = "mock_id"; name="mock_name"; real_name="mock_real_name"} in
let mock_response = {Slack_t.user = mock_user} in
Lwt.return @@ Ok mock_response

let send_notification ~ctx:_ ~msg =
let json = msg |> Slack_j.string_of_post_message_req |> Yojson.Basic.from_string |> Yojson.Basic.pretty_to_string in
Stdio.printf "will notify #%s\n" msg.channel;
Expand Down
17 changes: 17 additions & 0 deletions lib/api_remote.ml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,23 @@ module Slack : Api.Slack = struct
(* must read whole response to update lexer state *)
ignore (Slack_j.read_ok_res s l)

(** [lookup_user ctx email] queries slack for a user profile with [email] *)
let lookup_user ~(ctx: Context.t) ~email =
log#info "looking up %s\n" email;
let build_error e = fmt_error "%s\nfailed to lookup Slack user" e in
let secrets = Context.get_secrets_exn ctx in
match secrets.slack_access_token with
| None -> Lwt.return @@ build_error @@ sprintf "no token configured to lookup user email %s" email
| Some access_token ->
let headers = [ bearer_token_header access_token ] in
let data = {Slack_t.email = email} |> Slack_j.string_of_lookup_user_req in
let body = `Raw ("application/json", data) in
let url ="https://slack.com/api/users.lookupByEmail" in
log#info "data: %s" data;
match%lwt slack_api_request ~body ~headers `GET url Slack_j.read_lookup_user_res with
| Ok res -> Lwt.return @@ Ok res
| Error e -> Lwt.return @@ build_error e

(** [send_notification ctx msg] notifies [msg.channel] with the payload [msg];
uses web API with access token if available, or with webhook otherwise *)
let send_notification ~(ctx : Context.t) ~(msg : Slack_t.post_message_req) =
Expand Down
14 changes: 14 additions & 0 deletions lib/slack.atd
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,20 @@ type post_message_res = {
channel: string;
}

type lookup_user_req = {
email: string;
}

type lookup_user_res = {
user: user;
}

type user = {
id: string;
name: string;
real_name: string;
}

type link_shared_link = {
domain: string;
url: string;
Expand Down
22 changes: 16 additions & 6 deletions test/slack_payloads.expected
Original file line number Diff line number Diff line change
Expand Up @@ -497,9 +497,11 @@ will notify #longest-a1
}
===== file ../mock_payloads/status.cancelled_test.json =====
===== file ../mock_payloads/status.failure_test.json =====
will notify #default
looking up slack user by email [email protected]
{ "email": "[email protected]" }
will notify #mock_id
{
"channel": "default",
"channel": "mock_id",
"text": "<https://github.com/ahrefs/monorepo|[ahrefs/monorepo]> CI Build Status notification for <https://buildkite.com/org/pipeline2/builds/2|buildkite/pipeline2>: failure",
"attachments": [
{
Expand All @@ -518,11 +520,15 @@ will notify #default
===== file ../mock_payloads/status.merge_develop.json =====
===== file ../mock_payloads/status.pending_test.json =====
===== file ../mock_payloads/status.state_hide_success_test.json =====
looking up slack user by email [email protected]
{ "email": "[email protected]" }
===== file ../mock_payloads/status.state_hide_success_test_disallowed_pipeline.json =====
===== file ../mock_payloads/status.success_public_repo_no_buildkite.json =====
will notify #default
looking up slack user by email [email protected]
{ "email": "[email protected]" }
will notify #mock_id
{
"channel": "default",
"channel": "mock_id",
"text": "<https://github.com/Codertocat/Hello-World|[Codertocat/Hello-World]> CI Build Status notification: success",
"attachments": [
{
Expand All @@ -538,6 +544,8 @@ will notify #default
]
}
===== file ../mock_payloads/status.success_test_main_branch.json =====
looking up slack user by email [email protected]
{ "email": "[email protected]" }
will notify #all-push-events
{
"channel": "all-push-events",
Expand All @@ -557,9 +565,11 @@ will notify #all-push-events
]
}
===== file ../mock_payloads/status.success_test_non_main_branch.json =====
will notify #default
looking up slack user by email [email protected]
{ "email": "[email protected]" }
will notify #mock_id
{
"channel": "default",
"channel": "mock_id",
"text": "<https://github.com/ahrefs/monorepo|[ahrefs/monorepo]> CI Build Status notification for <https://buildkite.com/org/pipeline2/builds/2|buildkite/pipeline2>: success",
"attachments": [
{
Expand Down