Skip to content

Commit 65ebe94

Browse files
authored
Merge pull request #1225 from code-corps/1217-eliminate-duplicative-logic-in-github-sync-issue-github-issue
Deduplicate Sync.Issue.GithubIssue, clean up
2 parents f023b00 + b8ea7a9 commit 65ebe94

File tree

9 files changed

+196
-218
lines changed

9 files changed

+196
-218
lines changed
Lines changed: 22 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
defmodule CodeCorps.GitHub.Sync.Issue.GithubIssue do
22
@moduledoc ~S"""
3-
In charge of finding a `CodeCorps.GithubIssue` to link with a
4-
`CodeCorps.Issue` when processing a GitHub Issue payload.
3+
In charge of finding or creating a `CodeCorps.GithubIssue` to link with a
4+
`CodeCorps.Task` when processing a GitHub Issue payload.
55
66
The only entry point is `create_or_update_issue/2`.
77
"""
@@ -17,93 +17,38 @@ defmodule CodeCorps.GitHub.Sync.Issue.GithubIssue do
1717
}
1818

1919
alias Ecto.Changeset
20-
alias Sync.User.GithubUser, as: GithubUserSyncer
2120

2221
@typep linking_result :: {:ok, GithubIssue.t} | {:error, Changeset.t}
2322

2423
@doc ~S"""
25-
Finds or creates a `CodeCorps.GithubIssue` using the data in a GitHub Issue
26-
payload.
24+
Creates or updates a `CodeCorps.GithubIssue` from a github issue API payload.
2725
28-
The process is as follows:
29-
- Search for the issue in our database with the payload data.
30-
- If found, update it with payload data
31-
- If not found, create it from payload data
26+
The created record is associated to the provided `CodeCorps.GithubRepo` and, optionaly,
27+
to a provided `CodeCorps.GithubPullRequest`.
3228
33-
`CodeCorps.GitHub.AdaptersIssue.to_issue/1` is used to adapt the payload data.
29+
The created record is also associated with a matched `CodeCorps.GithubUser`, which is
30+
created if necessary.
3431
"""
35-
@spec create_or_update_issue({GithubRepo.t, GithubPullRequest.t | nil}, map) :: linking_result
36-
def create_or_update_issue({github_repo, github_pull_request}, %{"id" => github_issue_id} = attrs) do
37-
params = to_params(attrs, github_repo, github_pull_request)
38-
case Repo.get_by(GithubIssue, github_id: github_issue_id) do
39-
nil -> create_issue(params)
40-
%GithubIssue{} = issue -> update_issue(issue, params)
41-
end
42-
end
43-
44-
@doc ~S"""
45-
Creates a `CodeCorps.GithubIssue` for the provided `CodeCorps.GithubRepo`
46-
using specified attributes.
47-
48-
Links to existing `CodeCorps.GithubPullRequest` if matched by
49-
`github_repo_id` and `number`.
50-
"""
51-
@spec create_or_update_issue(GithubRepo.t, map) :: linking_result
52-
def create_or_update_issue(%GithubRepo{} = repo, attrs) do
53-
with {:ok, %GithubUser{} = github_user} <- GithubUserSyncer.create_or_update_github_user(attrs),
54-
{:ok, %GithubIssue{} = github_issue} <- do_create_or_update_issue(repo, attrs, github_user)
55-
do
56-
{:ok, github_issue}
32+
@spec create_or_update_issue(map, GithubRepo.t, GithubPullRequest.t | nil) :: linking_result
33+
def create_or_update_issue(%{} = payload, %GithubRepo{} = github_repo, github_pull_request \\ nil) do
34+
with {:ok, %GithubUser{} = github_user} <- Sync.User.GithubUser.create_or_update_github_user(payload) do
35+
payload
36+
|> find_or_init()
37+
|> GithubIssue.changeset(payload |> Adapters.Issue.to_issue)
38+
|> Changeset.put_assoc(:github_user, github_user)
39+
|> Changeset.put_assoc(:github_repo, github_repo)
40+
|> Changeset.put_assoc(:github_pull_request, github_pull_request)
41+
|> Repo.insert_or_update
5742
else
5843
{:error, error} -> {:error, error}
5944
end
6045
end
6146

62-
defp do_create_or_update_issue(
63-
%GithubRepo{id: repo_id} = repo,
64-
%{"id" => github_id, "number" => number} = attrs,
65-
%GithubUser{} = github_user) do
66-
67-
case Repo.get_by(GithubIssue, github_id: github_id) |> Repo.preload([:github_pull_request, :github_user]) do
68-
nil ->
69-
%GithubIssue{}
70-
|> GithubIssue.create_changeset(attrs |> Adapters.Issue.to_issue)
71-
|> Changeset.put_assoc(:github_pull_request, GithubPullRequest |> Repo.get_by(github_repo_id: repo_id, number: number))
72-
|> Changeset.put_assoc(:github_repo, repo)
73-
|> Changeset.put_assoc(:github_user, github_user)
74-
|> Repo.insert
75-
%GithubIssue{} = issue ->
76-
issue
77-
|> GithubIssue.update_changeset(attrs |> Adapters.Issue.to_issue)
78-
|> Changeset.put_assoc(:github_pull_request, GithubPullRequest |> Repo.get_by(github_repo_id: repo_id, number: number))
79-
|> Changeset.put_assoc(:github_user, github_user)
80-
|> Repo.update
47+
@spec find_or_init(map) :: GithubIssue.t
48+
defp find_or_init(%{"id" => github_id}) do
49+
case GithubIssue |> Repo.get_by(github_id: github_id) |> Repo.preload([:github_user, :github_repo, :github_pull_request]) do
50+
nil -> %GithubIssue{}
51+
%GithubIssue{} = github_issue -> github_issue
8152
end
8253
end
83-
84-
@spec create_issue(map) :: linking_result
85-
defp create_issue(params) do
86-
%GithubIssue{}
87-
|> GithubIssue.create_changeset(params)
88-
|> Repo.insert
89-
end
90-
91-
@spec update_issue(GithubIssue.t, map) :: linking_result
92-
defp update_issue(%GithubIssue{} = github_issue, params) do
93-
github_issue
94-
|> GithubIssue.update_changeset(params)
95-
|> Repo.update
96-
end
97-
98-
defp to_params(attrs, %GithubRepo{id: github_repo_id}, %GithubPullRequest{id: github_pull_request_id}) do
99-
attrs
100-
|> Adapters.Issue.to_issue()
101-
|> Map.put(:github_repo_id, github_repo_id)
102-
|> Map.put(:github_pull_request_id, github_pull_request_id)
103-
end
104-
defp to_params(attrs, %GithubRepo{id: github_repo_id}, _) do
105-
attrs
106-
|> Adapters.Issue.to_issue()
107-
|> Map.put(:github_repo_id, github_repo_id)
108-
end
10954
end
Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,38 @@
11
defmodule CodeCorps.GitHub.Sync.Issue do
2-
alias CodeCorps.{GitHub, GithubIssue, GithubPullRequest, GithubRepo}
3-
alias GitHub.Sync.Issue.GithubIssue, as: IssueGithubIssueSyncer
4-
alias GitHub.Sync.Issue.Task, as: IssueTaskSyncer
5-
alias GitHub.Sync.User.RecordLinker, as: UserRecordLinker
2+
alias CodeCorps.{
3+
GithubPullRequest,
4+
GithubRepo,
5+
GitHub.Sync
6+
}
67
alias Ecto.Multi
78

89
@doc ~S"""
9-
Syncs a GitHub issue API payload with our data.
10+
Performs sync of a github issue payload related to a repo and a pull request.
1011
11-
The process is as follows:
12-
13-
- match with `CodeCorps.User` using `CodeCorps.GitHub.Sync.User.RecordLinker`
14-
- create or update the `CodeCorps.Task` for the `CodeCorps.Project` in the
15-
matched `CodeCorps.GithubRepo`
16-
17-
If the sync succeeds, it will return an `:ok` tuple with the created or
18-
updated task.
19-
20-
If the sync fails, it will return an `:error` tuple, where the second element
21-
is the atom indicating a reason.
12+
Performs work identical to `sync/2`, with the adition of associating the
13+
resulting `CodeCorps.GithubIssue` with the specified `CodeCorps.GithubPullRequest`.
2214
"""
23-
@spec sync((map -> Multi.t), map) :: Multi.t
24-
def sync(%{fetch_issue: issue} = changes, _payload) do
25-
sync_multi(changes, issue)
26-
end
27-
def sync(changes, payload) do
28-
sync_multi(changes, payload)
15+
@spec sync(map, GithubRepo.t, GithubPullRequest.t) :: Multi.t
16+
def sync(%{} = payload, %GithubRepo{} = github_repo, %GithubPullRequest{} = github_pull_request) do
17+
Multi.new
18+
|> Multi.run(:github_issue, fn _ -> payload |> Sync.Issue.GithubIssue.create_or_update_issue(github_repo, github_pull_request) end)
19+
|> Multi.run(:issue_user, fn %{github_issue: github_issue} -> Sync.User.RecordLinker.link_to(github_issue, payload) end)
20+
|> Multi.run(:task, fn %{github_issue: github_issue, issue_user: user} -> github_issue |> Sync.Issue.Task.sync_github_issue(user) end)
2921
end
3022

31-
@spec sync_multi(map, map) :: Multi.t
32-
defp sync_multi(%{repo: github_repo, github_pull_request: github_pull_request}, payload) do
33-
do_sync_multi({github_repo, github_pull_request}, payload)
34-
end
35-
defp sync_multi(%{repo: github_repo}, payload) do
36-
do_sync_multi({github_repo, nil}, payload)
37-
end
23+
@doc ~S"""
24+
Performs sync of a github issue payload related to a repo.
3825
39-
defp do_sync_multi({github_repo, github_pull_request}, payload) do
26+
Creates or updates a `CodeCorps.GithubIssue`
27+
- a `CodeCorps.GithubUser` is created or updated as part of the process and associated to `CodeCorps.GithubIssue`
28+
- the record is associated to the `CodeCorps.GithubRepo`
29+
- an 'unregistered' `CodeCorps.User` is created if no record with matching `:github_id` is found
30+
"""
31+
@spec sync(map, GithubRepo.t) :: Multi.t
32+
def sync(%{} = payload, %GithubRepo{} = github_repo) do
4033
Multi.new
41-
|> Multi.run(:github_issue, fn _ -> IssueGithubIssueSyncer.create_or_update_issue({github_repo, github_pull_request}, payload) end)
42-
|> Multi.run(:issue_user, fn %{github_issue: github_issue} -> UserRecordLinker.link_to(github_issue, payload) end)
43-
|> Multi.run(:task, fn %{github_issue: github_issue, issue_user: user} -> github_issue |> IssueTaskSyncer.sync_github_issue(user) end)
34+
|> Multi.run(:github_issue, fn _ -> payload |> Sync.Issue.GithubIssue.create_or_update_issue(github_repo) end)
35+
|> Multi.run(:issue_user, fn %{github_issue: github_issue} -> Sync.User.RecordLinker.link_to(github_issue, payload) end)
36+
|> Multi.run(:task, fn %{github_issue: github_issue, issue_user: user} -> github_issue |> Sync.Issue.Task.sync_github_issue(user) end)
4437
end
4538
end

0 commit comments

Comments
 (0)