diff --git a/lib/algora/admin/admin.ex b/lib/algora/admin/admin.ex index beeddb8e9..2c2216e54 100644 --- a/lib/algora/admin/admin.ex +++ b/lib/algora/admin/admin.ex @@ -3,6 +3,8 @@ defmodule Algora.Admin do import Ecto.Query alias Algora.Accounts.User + alias Algora.Bounties.Claim + alias Algora.Parser alias Algora.Payments alias Algora.Repo alias Algora.Workspace @@ -54,6 +56,28 @@ defmodule Algora.Admin do :ok end + def backfill_claims! do + query = + from(t in Claim, + where: fragment("? ilike ?", t.url, "%//github.com/%"), + distinct: t.url, + select: t.url + ) + + {success, failure} = + query + |> Repo.all() + |> Task.async_stream(&backfill_claim/1, max_concurrency: 1, timeout: :infinity) + |> Enum.reduce({0, 0}, fn + {:ok, {:ok, _}}, {s, f} -> {s + 1, f} + {:ok, {:error, _}}, {s, f} -> {s, f + 1} + {:exit, _}, {s, f} -> {s, f + 1} + end) + + IO.puts("Claim backfill complete: #{success} succeeded, #{failure} failed") + :ok + end + def backfill_repo(url) do with %URI{host: "api.github.com", path: "/repos/" <> path} <- URI.parse(url), [owner, repo] <- String.split(path, "/", trim: true), @@ -70,6 +94,25 @@ defmodule Algora.Admin do end end + def backfill_claim(url) do + with {:ok, [ticket_ref: [owner: owner, repo: repo, type: _type, number: number]], _, _, _, _} <- + Parser.full_ticket_ref(url), + {:ok, ticket} <- Workspace.ensure_ticket(token!(), owner, repo, number), + :ok <- update_claims(url, ticket.id) do + {:ok, ticket} + else + {:error, "404 Not Found"} = error -> + error + + {:error, %Postgrex.Error{postgres: %{constraint: "claims_user_id_source_id_target_id_index"}}} = error -> + error + + error -> + Logger.error("Failed to backfill claim #{url}: #{inspect(error)}") + {:error, error} + end + end + def make_admin!(user_handle, is_admin) when is_boolean(is_admin) do user_handle |> Algora.Accounts.get_user_by_handle() @@ -92,5 +135,15 @@ defmodule Algora.Admin do ) :ok + rescue + error -> {:error, error} + end + + defp update_claims(url, source_id) do + Repo.update_all(from(t in Claim, where: t.url == ^url), set: [source_id: source_id]) + + :ok + rescue + error -> {:error, error} end end diff --git a/scripts/database_migration.exs b/scripts/database_migration.exs index a593878ed..d3bd4bae4 100644 --- a/scripts/database_migration.exs +++ b/scripts/database_migration.exs @@ -427,7 +427,6 @@ defmodule DatabaseMigration do bounty = find_by_index(db, "Bounty", "id", row["bounty_id"]) task = find_by_index(db, "Task", "id", bounty["task_id"]) github_user = find_by_index(db, "GithubUser", "id", row["github_user_id"]) - github_pull_request = find_by_index(db, "GithubPullRequest", "id", row["github_pull_request_id"]) user_id = or_else(github_user["user_id"], github_user["id"]) @@ -455,7 +454,7 @@ defmodule DatabaseMigration do "url" => or_else(row["github_url"], "https://algora.io"), "group_id" => row["id"], "group_share" => nil, - "source_id" => github_pull_request["task_id"], + "source_id" => nil, "target_id" => task["id"], "user_id" => user_id, "inserted_at" => row["created_at"], @@ -1354,6 +1353,7 @@ defmodule DatabaseMigration do :ok = time_step("Clearing tables", fn -> clear_tables!() end) {:ok, _} = time_step("Importing new data", fn -> psql(["-f", output_file]) end) :ok = time_step("Backfilling repositories", fn -> Algora.Admin.backfill_repos!() end) + :ok = time_step("Backfilling claims", fn -> Algora.Admin.backfill_claims!() end) end) IO.puts("✅ Migration completed successfully in #{total_time / 1_000_000} seconds")