Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
65 changes: 61 additions & 4 deletions lib/algora/workspace/workspace.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
defmodule Algora.Workspace do
@moduledoc false
import Ecto.Changeset
import Ecto.Query

alias Algora.Accounts.User
Expand Down Expand Up @@ -92,10 +93,33 @@ defmodule Algora.Workspace do

def create_repository_from_github(token, owner, repo) do
with {:ok, repository} <- Github.get_repository(token, owner, repo),
{:ok, user} <- ensure_user(token, owner) do
repository
|> Repository.github_changeset(user)
|> Repo.insert()
{:ok, user} <- ensure_user_by_repo(token, repository, owner),
{:ok, user} <- sync_user(user, repository, owner, repo),
{:ok, repo} <- repository |> Repository.github_changeset(user) |> Repo.insert() do
{:ok, repo}
else
{:error,
%Ecto.Changeset{
errors: [provider: {_, [constraint: :unique, constraint_name: "repositories_provider_provider_id_index"]}]
} = changeset} ->
Repo.fetch_by(Repository, provider: "github", provider_id: changeset.changes.provider_id)

{:error, _reason} = error ->
error
end
end

def ensure_user_by_repo(token, repository, owner) do
case Repo.get_by(User, provider: "github", provider_id: to_string(repository["owner"]["id"])) do
%User{} = user ->
{:ok, user}

nil ->
if repository["owner"]["login"] != owner do
Logger.warning("might need to rename #{owner} -> #{repository["owner"]["login"]}")
end

ensure_user(token, repository["owner"]["login"])
end
end

Expand All @@ -106,6 +130,39 @@ defmodule Algora.Workspace do
end
end

def sync_user(user, repository, owner, repo) do
github_user = repository["owner"]

if github_user["login"] == user.provider_login and not is_nil(user.provider_id) do
{:ok, user}
else
if github_user["login"] != user.provider_login do
Logger.warning(
"renaming #{user.provider_login} -> #{github_user["login"]} (reason: #{owner}/#{repo} moved to #{repository["full_name"]})"
)
end

res =
user
|> change(%{
provider_id: to_string(github_user["id"]),
provider_login: github_user["login"],
provider_meta: Util.normalize_struct(github_user)
})
|> unique_constraint([:provider, :provider_id])
|> Repo.update()

case res do
{:ok, user} ->
{:ok, user}

error ->
Logger.error("#{owner}/#{repo} | failed to remap #{user.provider_login} -> #{github_user["login"]}")
error
end
end
end

def create_user_from_github(token, owner) do
with {:ok, user_data} <- Github.get_user_by_username(token, owner) do
user_data
Expand Down
19 changes: 16 additions & 3 deletions test/support/github_mock.ex
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,27 @@ defmodule Algora.Support.GithubMock do
%{
"id" => random_id(),
"name" => repo,
"html_url" => "https://github.com/#{owner}/#{repo}"
"html_url" => "https://github.com/#{owner}/#{repo}",
"owner" => %{
"login" => owner
}
}}
end

@impl true
def get_repository(_access_token, id) do
name = "repo_#{id}"
{:ok, %{"id" => id, "name" => name, "html_url" => "https://github.com/owner_#{random_id()}/#{name}"}}
owner = "owner_#{random_id()}"
name = "repo_#{random_id()}"

{:ok,
%{
"id" => id,
"name" => name,
"html_url" => "https://github.com/#{owner}/#{name}",
"owner" => %{
"login" => owner
}
}}
end

@impl true
Expand Down