Sync assignees from GitHub
Problem
When an issues is assigned/unassigned a user from GitHub, we need to sync that assignment to our assigned user on Code Corps.
In the short-term, we can just accept a single assignee (if no one is assigned on Code Corps yet) and ignore any other assignees.
When getting assignees from GitHub, we should:
- Create or delete
GithubIssueAssigneerecords - If there's already a
UserTaskfor theTask, do nothing - If there is no
UserTask, assign theUserthat relates to theGithubIssueAssigneeto theTaskthat relates to theGithubIssue
We'll need to, given the issue payload from the API:
- Grab the
"assignees"array - Extract all the GitHub
idvalues for the assignees - Find or create GithubUsers for each assignee
- In a transaction
- Fetch all the existing
GithubIssueAssigneerecords for theGithubIssue - Delete all the
GithubIssueAssigneerecords that do not match theGithubUserrecords for the extracted IDs - Create new
GithubIssueAssigneerecords for any remainingGithubUserrecords that match
- Fetch all the existing
Looking into this, we do not currently respond to specific changes on a record during any github webhook event. Instead, we simply sync the entire record at once.
To elaborate, we don't really look at the changes map in the payload. We just take the main record map, in this case, issue, and use the data in it to sync our information.
In the case of assigned/unassigned, the payload will have
-
action->assignedorunassigned -
assignee-> the specific github user that was assigned or unassigned -
issue, containingassignees, which is a list of users currently assigned
If we want to follow our current convention, we would ignore the assignee and instead just look at assignees, then follow a process similar to the initial repo sync which is part of handling an installation created event - look at this assignees list as master list and delete/insert what does not match locally.
That means that, in the least optimized scenario, or current Sync.issues_event simply adds another couple of steps:
def issue_event(%{"issue" => issue_payload}) do
Multi.new
|> Multi.run(:repo, fn _ -> RepoFinder.find_repo(payload) end)
|> Multi.run(fn %{github_repo: github_repo} -> issue_payload |> Sync.Issue.sync(github_repo) end)
# this one
|> Multi.run(:github_issue_assignees, fn %{github_issue: github_issue} -> github_issue |> Sync.GiuthubIssueAssignee.sync(issue_payload) end)
|> Multi.run(:task_user, fn %{github_issue_assignees: assignees} -> assignees |> Sync.TaskUser.sync end)
|> Repo.transaction()
|> marshall_result()
end
A more optimized scenario adds the above function as a separate clause, matching against the "action" key in the payload