@@ -7,117 +7,45 @@ defmodule CodeCorps.GitHub.Event.IssueComment do
77 @ behaviour CodeCorps.GitHub.Event.Handler
88
99 alias CodeCorps . {
10- Comment ,
1110 GitHub ,
12- GithubComment ,
13- GithubRepo ,
14- GitHub.Event.Common.RepoFinder ,
15- GitHub.Event.IssueComment.CommentDeleter ,
16- GitHub.Event.IssueComment.Validator ,
17- Repo
11+ GitHub.Event.IssueComment.Validator
1812 }
19- alias GitHub.Sync.Comment.Comment , as: CommentCommentSyncer
20- alias GitHub.Sync.Comment.GithubComment , as: CommentGithubCommentSyncer
21- alias GitHub.Sync.Issue.GithubIssue , as: IssueGithubIssueSyncer
22- alias GitHub.Sync.Issue.Task , as: IssueTaskSyncer
23- alias GitHub.Sync.User.RecordLinker , as: UserRecordLinker
24- alias Ecto.Multi
13+ alias GitHub.Sync.Comment , as: CommentSyncer
2514
26- @ type outcome :: { :ok , list ( Comment . t ) } |
27- { :error , :unexpected_action } |
28- { :error , :unexpected_payload } |
29- { :error , :repository_not_found } |
30- { :error , :validation_error_on_inserting_issue_for_task } |
31- { :error , :validation_error_on_inserting_github_comment } |
32- { :error , :validation_error_on_inserting_user_for_task } |
33- { :error , :multiple_github_users_matched_same_cc_user_for_task } |
34- { :error , :validation_error_on_inserting_user_for_comment } |
35- { :error , :multiple_github_users_matched_same_cc_user_for_comment } |
36- { :error , :validation_error_on_syncing_tasks } |
37- { :error , :validation_error_on_syncing_comments } |
38- { :error , :unexpected_transaction_outcome }
15+ @ type outcome :: CommentSyncer . outcome
16+ | { :error , :unexpected_action }
17+ | { :error , :unexpected_payload }
3918
4019 @ doc ~S"""
4120 Handles the "IssueComment" GitHub webhook
4221
43- The process is as follows
22+ The process is as follows:
23+
4424 - validate the payload is structured as expected
4525 - validate the action is properly supported
46- - match payload with affected `CodeCorps.GithubRepo` record using `CodeCorps.GitHub.Event.Common.RepoFinder`
47- - match issue part of the payload with a `CodeCorps.User` using `CodeCorps.GitHub.Event.Issues.UserLinker`
48- - match comment part of the payload with a `CodeCorps.User` using `CodeCorps.GitHub.Event.IssueComment.UserLinker`
49- - for each `CodeCorps.ProjectGithubRepo` belonging to matched repo
50- - match and update, or create a `CodeCorps.Task` on the associated `CodeCorps.Project`
51- - match and update, or create a `CodeCorps.Comment` associated to `CodeCorps.Task`
52-
53- If the process runs all the way through, the function will return an `:ok`
54- tuple with a list of affected (created or updated) comments.
55-
56- If it fails, it will instead return an `:error` tuple, where the second
57- element is the atom indicating a reason.
26+ - sync the comment using `CodeCorps.GitHub.Sync.Comment`
5827 """
5928 @ spec handle ( map ) :: outcome
6029 def handle ( payload ) do
61- Multi . new
62- |> Multi . run ( :payload , fn _ -> payload |> validate_payload ( ) end )
63- |> Multi . run ( :action , fn _ -> payload |> validate_action ( ) end )
64- |> Multi . append ( payload |> operational_multi ( ) )
65- |> Repo . transaction
66- |> marshall_result ( )
67- end
68-
69- @ spec operational_multi ( map ) :: Multi . t
70- defp operational_multi ( % { "action" => action , "issue" => _ , "comment" => _ } = payload ) when action in ~w( created edited) do
71- Multi . new
72- |> Multi . run ( :repo , fn _ -> RepoFinder . find_repo ( payload ) end )
73- |> Multi . run ( :github_issue , fn % { repo: github_repo } -> github_repo |> link_issue ( payload ) end )
74- |> Multi . run ( :github_comment , fn % { github_issue: github_issue } -> github_issue |> sync_comment ( payload ) end )
75- |> Multi . run ( :issue_user , fn % { github_issue: github_issue } -> UserRecordLinker . link_to ( github_issue , payload ) end )
76- |> Multi . run ( :comment_user , fn % { github_comment: github_comment } -> UserRecordLinker . link_to ( github_comment , payload ) end )
77- |> Multi . run ( :tasks , fn % { github_issue: github_issue , issue_user: user } -> github_issue |> IssueTaskSyncer . sync_all ( user , payload ) end )
78- |> Multi . run ( :comments , fn % { github_comment: github_comment , tasks: tasks , comment_user: user } -> CommentCommentSyncer . sync_all ( tasks , github_comment , user , payload ) end )
79- end
80- defp operational_multi ( % { "action" => "deleted" } = payload ) do
81- Multi . new
82- |> Multi . run ( :comments , fn _ -> CommentDeleter . delete_all ( payload ) end )
83- end
84- defp operational_multi ( % { } ) , do: Multi . new
85-
86- @ spec link_issue ( GithubRepo . t , map ) :: { :ok , GithubIssue . t } | { :error , Ecto.Changeset . t }
87- defp link_issue ( github_repo , % { "issue" => attrs } ) do
88- IssueGithubIssueSyncer . create_or_update_issue ( github_repo , attrs )
89- end
90-
91- @ spec sync_comment ( GithubIssue . t , map ) :: { :ok , GithubComment . t } | { :error , Ecto.Changeset . t }
92- defp sync_comment ( github_issue , % { "comment" => attrs } ) do
93- CommentGithubCommentSyncer . create_or_update_comment ( github_issue , attrs )
30+ with { :ok , :valid } <- validate_payload ( payload ) ,
31+ { :ok , :implemented } <- validate_action ( payload ) do
32+ CommentSyncer . sync ( payload )
33+ else
34+ { :error , error } -> { :error , error }
35+ end
9436 end
9537
96- @ spec marshall_result ( tuple ) :: tuple
97- defp marshall_result ( { :ok , % { comments: comments } } ) , do: { :ok , comments }
98- defp marshall_result ( { :error , :payload , :invalid , _steps } ) , do: { :error , :unexpected_payload }
99- defp marshall_result ( { :error , :action , :unexpected_action , _steps } ) , do: { :error , :unexpected_action }
100- defp marshall_result ( { :error , :repo , :unmatched_project , _steps } ) , do: { :ok , [ ] }
101- defp marshall_result ( { :error , :repo , :unmatched_repository , _steps } ) , do: { :error , :repository_not_found }
102- defp marshall_result ( { :error , :github_issue , % Ecto.Changeset { } , _steps } ) , do: { :error , :validation_error_on_inserting_issue_for_task }
103- defp marshall_result ( { :error , :github_comment , % Ecto.Changeset { } , _steps } ) , do: { :error , :validation_error_on_inserting_github_comment }
104- defp marshall_result ( { :error , :issue_user , % Ecto.Changeset { } , _steps } ) , do: { :error , :validation_error_on_inserting_user_for_task }
105- defp marshall_result ( { :error , :issue_user , :multiple_users , _steps } ) , do: { :error , :multiple_github_users_matched_same_cc_user_for_task }
106- defp marshall_result ( { :error , :comment_user , % Ecto.Changeset { } , _steps } ) , do: { :error , :validation_error_on_inserting_user_for_comment }
107- defp marshall_result ( { :error , :comment_user , :multiple_users , _steps } ) , do: { :error , :multiple_github_users_matched_same_cc_user_for_comment }
108- defp marshall_result ( { :error , :tasks , { _tasks , _errors } , _steps } ) , do: { :error , :validation_error_on_syncing_tasks }
109- defp marshall_result ( { :error , :comments , { _comments , _errors } , _steps } ) , do: { :error , :validation_error_on_syncing_comments }
110- defp marshall_result ( { :error , _errored_step , _error_response , _steps } ) , do: { :error , :unexpected_transaction_outcome }
111-
112- @ spec validate_payload ( map ) :: { :ok , :valid } | { :error , :invalid }
38+ @ spec validate_payload ( map ) :: { :ok , :valid }
39+ | { :error , :unexpected_payload }
11340 defp validate_payload ( % { } = payload ) do
11441 case payload |> Validator . valid? do
11542 true -> { :ok , :valid }
116- false -> { :error , :invalid }
43+ false -> { :error , :unexpected_payload }
11744 end
11845 end
11946
12047 @ implemented_actions ~w( created edited deleted)
48+
12149 @ spec validate_action ( map ) :: { :ok , :implemented } | { :error , :unexpected_action }
12250 defp validate_action ( % { "action" => action } ) when action in @ implemented_actions , do: { :ok , :implemented }
12351 defp validate_action ( % { } ) , do: { :error , :unexpected_action }
0 commit comments