Skip to content

Commit

Permalink
Merge pull request #1365 from code-corps/reorganize-github-modules
Browse files Browse the repository at this point in the history
Reorganize GitHub modules
  • Loading branch information
joshsmith authored Jan 11, 2018
2 parents b479f22 + 17749ad commit 9f2e3b6
Show file tree
Hide file tree
Showing 44 changed files with 1,436 additions and 1,229 deletions.
5 changes: 4 additions & 1 deletion lib/code_corps/github/event.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ defmodule CodeCorps.GitHub.Event do
end

@type error :: atom | Changeset.t
@type result :: {:ok, any} | {:error, atom, any}
@type result :: {:ok, any} | {:error, atom} | {:error, atom, any}

@doc ~S"""
Sets record status to "processing", marking it as being processed at this
Expand All @@ -44,6 +44,9 @@ defmodule CodeCorps.GitHub.Event do
|> Changeset.change(%{status: "processed"})
|> Repo.update()
end
def stop_processing({:error, reason}, %GithubEvent{} = event) do
stop_processing({:error, reason, %{}}, event)
end
def stop_processing({:error, reason, error}, %GithubEvent{} = event) do
%GitHubEventError{reason: error}
|> CodeCorps.Sentry.capture_exception([stacktrace: System.stacktrace()])
Expand Down
2 changes: 1 addition & 1 deletion lib/code_corps/github/event/handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ defmodule CodeCorps.GitHub.Event.Handler do
successful, or an `:error` tuple, where the second element is an atom, if it
failed.
"""
@callback handle(map) :: {:ok, any} | {:error, atom}
@callback handle(map) :: {:ok, any} | {:error, atom} | {:error, atom, any}
end
58 changes: 0 additions & 58 deletions lib/code_corps/github/event/installation/changeset_builder.ex

This file was deleted.

86 changes: 11 additions & 75 deletions lib/code_corps/github/event/installation/installation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,91 +6,27 @@ defmodule CodeCorps.GitHub.Event.Installation do

@behaviour CodeCorps.GitHub.Event.Handler

alias CodeCorps.{
GithubAppInstallation,
GitHub.Event.Installation,
Repo,
User
}
alias CodeCorps.{GitHub.Sync, GitHub.Event.Installation}

alias Ecto.{Changeset, Multi}

@type outcome :: {:ok, GithubAppInstallation.t} |
{:error, :unexpected_payload} |
{:error, :validation_error_on_syncing_installation} |
{:error, :multiple_unprocessed_installations_found} |
{:error, :github_api_error_on_syncing_repos} |
{:error, :validation_error_on_deleting_removed_repos} |
{:error, :validation_error_on_syncing_existing_repos} |
{:error, :validation_error_on_marking_installation_processed}

@doc """
Handles the "Installation" GitHub Webhook event.
The event could be of subtype `created` or `deleted`. Only the `created`
variant is handled at the moment.
The process of handling the "created" event subtype is as follows
- try to match the sender with an existing `CodeCorps.User`
- call specific matching module depending on the user being matched or not
- `CodeCorps.GitHub.Event.Installation.MatchedUser.handle/2`
- `CodeCorps.GitHub.Event.Installation.UnmatchedUser.handle/1`
- sync installation repositories using a third modules
- `CodeCorps.GitHub.Event.Installation.Repos.process/1`
If everything goes as expected, an `:ok` tuple will be returned, with a
`CodeCorps.GithubAppInstallation`, marked as "processed".
This is done by first validating the payload is in the format the system
expects, followed by piping it into
If a step in the process failes, an `:error` tuple will be returned, where the
second element is an atom indicating which step of the process failed.
`CodeCorps.GitHub.Sync.installation_event/1`
"""
@spec handle(map) :: outcome
@spec handle(map) ::
Sync.installation_event_outcome() | {:error, :unexpected_payload}
def handle(payload) do
Multi.new
|> Multi.run(:payload, fn _ -> payload |> validate_payload() end)
|> Multi.run(:user, fn _ -> payload |> find_user() end)
|> Multi.run(:installation, fn %{user: user} -> install_for_user(user, payload) end)
|> Multi.merge(&process_repos/1)
|> Repo.transaction
|> marshall_result()
end

@spec find_user(map) :: {:ok, User.t} | {:ok, nil} | {:error, :unexpected_user_payload}
defp find_user(%{"sender" => %{"id" => github_id}}) do
user = Repo.get_by(User, github_id: github_id)
{:ok, user}
end
defp find_user(_), do: {:error, :unexpected_user_payload}

@spec install_for_user(User.t, map) :: outcome
defp install_for_user(%User{} = user, payload) do
Installation.MatchedUser.handle(user, payload)
end
defp install_for_user(nil, payload) do
Installation.UnmatchedUser.handle(payload)
end

@spec process_repos(%{installation: GithubAppInstallation.t}) :: Multi.t
defp process_repos(%{installation: %GithubAppInstallation{} = installation}) do
installation
|> Repo.preload(:github_repos)
|> Installation.Repos.process
with {:ok, :valid} <- payload |> validate_payload() do
Sync.installation_event(payload)
else
{:error, :invalid} -> {:error, :unexpected_payload}
end
end

@spec marshall_result(tuple) :: tuple
defp marshall_result({:ok, %{processed_installation: installation}}), do: {:ok, installation}
defp marshall_result({:error, :payload, :invalid, _steps}), do: {:error, :unexpected_payload}
defp marshall_result({:error, :user, :unexpected_user_payload, _steps}), do: {:error, :unexpected_payload}
defp marshall_result({:error, :installation, :unexpected_installation_payload, _steps}), do: {:error, :unexpected_payload}
defp marshall_result({:error, :installation, %Changeset{}, _steps}), do: {:error, :validation_error_on_syncing_installation}
defp marshall_result({:error, :installation, :too_many_unprocessed_installations, _steps}), do: {:error, :multiple_unprocessed_installations_found}
defp marshall_result({:error, :api_response, %CodeCorps.GitHub.API.Errors.PaginationError{}, _steps}), do: {:error, :github_api_error_on_syncing_repos}
defp marshall_result({:error, :deleted_repos, {_results, _changesets}, _steps}), do: {:error, :validation_error_on_deleting_removed_repos}
defp marshall_result({:error, :synced_repos, {_results, _changesets}, _steps}), do: {:error, :validation_error_on_syncing_existing_repos}
defp marshall_result({:error, :processed_installation, %Changeset{}, _steps}), do: {:error, :validation_error_on_marking_installation_processed}
defp marshall_result({:error, _errored_step, _error_response, _steps}), do: {:error, :unexpected_transaction_outcome}

@spec validate_payload(map) :: {:ok, :valid} | {:error, :invalid}
defp validate_payload(%{} = payload) do
case payload |> Installation.Validator.valid? do
Expand Down
64 changes: 0 additions & 64 deletions lib/code_corps/github/event/installation/matched_user.ex

This file was deleted.

124 changes: 0 additions & 124 deletions lib/code_corps/github/event/installation/repos.ex

This file was deleted.

Loading

0 comments on commit 9f2e3b6

Please sign in to comment.