Skip to content

Commit 0378891

Browse files
committed
restructure claim schema
1 parent abc648e commit 0378891

File tree

8 files changed

+85
-107
lines changed

8 files changed

+85
-107
lines changed

lib/algora/bounties/bounties.ex

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -121,28 +121,31 @@ defmodule Algora.Bounties do
121121
|> Oban.insert()
122122
end
123123

124-
@spec do_claim_bounty(%{user: User.t(), ticket: Ticket.t(), pull_request: map()}) ::
124+
@spec do_claim_bounty(%{
125+
user: User.t(),
126+
target: Ticket.t(),
127+
source: Ticket.t(),
128+
status: :pending | :approved | :rejected | :paid,
129+
type: :pull_request | :review | :video | :design | :article
130+
}) ::
125131
{:ok, Claim.t()} | {:error, atom()}
126-
defp do_claim_bounty(%{user: user, ticket: ticket, pull_request: pull_request}) do
132+
defp do_claim_bounty(%{user: user, target: target, source: source, status: status, type: type}) do
127133
# TODO: ensure user is pull request author
128134
changeset =
129135
Claim.changeset(%Claim{}, %{
130-
ticket_id: ticket.id,
136+
target_id: target.id,
137+
source_id: source.id,
131138
user_id: user.id,
132-
provider: "github",
133-
provider_id: to_string(pull_request["id"]),
134-
provider_meta: Util.normalize_struct(pull_request),
135-
type: :pull_request,
136-
title: pull_request["title"],
137-
url: pull_request["html_url"],
138-
merged_at: Util.to_date(pull_request["merged_at"])
139+
type: type,
140+
status: status,
141+
url: source.url
139142
})
140143

141144
case Repo.insert(changeset) do
142145
{:ok, claim} ->
143146
{:ok, claim}
144147

145-
{:error, %{errors: [ticket_id: {_, [constraint: :unique, constraint_name: _]}]}} ->
148+
{:error, %{errors: [target_id: {_, [constraint: :unique, constraint_name: _]}]}} ->
146149
{:error, :already_exists}
147150

148151
{:error, _changeset} = error ->
@@ -153,17 +156,21 @@ defmodule Algora.Bounties do
153156
@spec claim_bounty(
154157
%{
155158
user: User.t(),
156-
ticket_ref: %{owner: String.t(), repo: String.t(), number: integer()},
157-
pull_request: map()
159+
target_ticket_ref: %{owner: String.t(), repo: String.t(), number: integer()},
160+
source_ticket_ref: %{owner: String.t(), repo: String.t(), number: integer()},
161+
status: :pending | :approved | :rejected | :paid,
162+
type: :pull_request | :review | :video | :design | :article
158163
},
159164
opts :: [installation_id: integer()]
160165
) ::
161166
{:ok, Bounty.t()} | {:error, atom()}
162167
def claim_bounty(
163168
%{
164169
user: user,
165-
ticket_ref: %{owner: repo_owner, repo: repo_name, number: number} = ticket_ref,
166-
pull_request: pull_request
170+
target_ticket_ref: %{owner: target_repo_owner, repo: target_repo_name, number: target_number},
171+
source_ticket_ref: %{owner: source_repo_owner, repo: source_repo_name, number: source_number},
172+
status: status,
173+
type: type
167174
},
168175
opts \\ []
169176
) do
@@ -176,8 +183,9 @@ defmodule Algora.Bounties do
176183

177184
Repo.transact(fn ->
178185
with {:ok, token} <- token_res,
179-
{:ok, ticket} <- Workspace.ensure_ticket(token, repo_owner, repo_name, number),
180-
{:ok, claim} <- do_claim_bounty(%{user: user, ticket: ticket, pull_request: pull_request}),
186+
{:ok, target} <- Workspace.ensure_ticket(token, target_repo_owner, target_repo_name, target_number),
187+
{:ok, source} <- Workspace.ensure_ticket(token, source_repo_owner, source_repo_name, source_number),
188+
{:ok, claim} <- do_claim_bounty(%{user: user, target: target, source: source, status: status, type: type}),
181189
{:ok, _job} <- notify_claim(%{claim: claim}, installation_id: installation_id) do
182190
broadcast()
183191
{:ok, claim}

lib/algora/bounties/jobs/notify_claim.ex

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ defmodule Algora.Bounties.Jobs.NotifyClaim do
1717
def perform(%Oban.Job{args: %{"claim_id" => claim_id, "installation_id" => installation_id}}) do
1818
with {:ok, token} <- Github.get_installation_token(installation_id),
1919
{:ok, claim} <- Repo.fetch(Claim, claim_id),
20-
claim = Repo.preload(claim, ticket: [repository: [:user]], user: []),
20+
claim = Repo.preload(claim, source: [repository: [:user]], target: [repository: [:user]], user: []),
2121
{:ok, _} <- maybe_add_labels(token, claim),
2222
{:ok, _} <- add_comment(token, claim) do
2323
:ok
@@ -27,21 +27,21 @@ defmodule Algora.Bounties.Jobs.NotifyClaim do
2727
defp add_comment(token, claim) do
2828
Github.create_issue_comment(
2929
token,
30-
claim.ticket.repository.user.provider_login,
31-
claim.ticket.repository.name,
32-
claim.ticket.number,
30+
claim.target.repository.user.provider_login,
31+
claim.target.repository.name,
32+
claim.target.number,
3333
"💡 @#{claim.user.provider_login} submitted [#{Claim.type_label(claim.type)}](#{claim.url}) that claims the bounty. You can visit [Algora](#{Claim.reward_url(claim)}) to reward."
3434
)
3535
end
3636

37-
defp maybe_add_labels(token, %Claim{type: :pull_request} = claim) do
37+
defp maybe_add_labels(token, %Claim{source: source} = claim) when not is_nil(source) do
3838
Github.add_labels(
3939
token,
40-
claim.provider_meta["base"]["repo"]["owner"]["login"],
41-
claim.provider_meta["base"]["repo"]["name"],
42-
claim.provider_meta["number"],
43-
["🙋 Bounty claim"])
44-
40+
claim.source.repository.user.provider_login,
41+
claim.source.repository.name,
42+
claim.source.number,
43+
["🙋 Bounty claim"]
44+
)
4545
end
4646

4747
defp maybe_add_labels(_token, _claim), do: {:ok, nil}

lib/algora/bounties/schemas/claim.ex

Lines changed: 9 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,16 @@ defmodule Algora.Bounties.Claim do
33
use Algora.Schema
44

55
alias Algora.Bounties.Claim
6+
alias Algora.Workspace.Ticket
67

7-
@derive {Inspect, except: [:provider_meta]}
88
typed_schema "claims" do
9-
field :provider, :string, null: false
10-
field :provider_id, :string, null: false
11-
field :provider_meta, :map, null: false
12-
9+
field :status, Ecto.Enum, values: [:pending, :approved, :rejected, :paid], null: false
1310
field :type, Ecto.Enum, values: [:pull_request, :review, :video, :design, :article]
14-
15-
field :merged_at, :utc_datetime_usec
16-
field :approved_at, :utc_datetime_usec
17-
field :rejected_at, :utc_datetime_usec
18-
field :charged_at, :utc_datetime_usec
19-
field :paid_at, :utc_datetime_usec
20-
21-
field :title, :string, null: false
22-
field :description, :string
2311
field :url, :string, null: false
2412
field :group_id, :string, null: false
2513

26-
belongs_to :ticket, Algora.Workspace.Ticket, null: false
14+
belongs_to :source, Ticket
15+
belongs_to :target, Ticket, null: false
2716
belongs_to :user, Algora.Accounts.User, null: false
2817
# has_one :transaction, Algora.Payments.Transaction
2918

@@ -32,37 +21,14 @@ defmodule Algora.Bounties.Claim do
3221

3322
def changeset(claim, attrs) do
3423
claim
35-
|> cast(attrs, [
36-
:ticket_id,
37-
:user_id,
38-
:provider,
39-
:provider_id,
40-
:provider_meta,
41-
:merged_at,
42-
:approved_at,
43-
:rejected_at,
44-
:charged_at,
45-
:paid_at,
46-
:type,
47-
:title,
48-
:description,
49-
:url,
50-
:group_id
51-
])
52-
|> validate_required([
53-
:ticket_id,
54-
:user_id,
55-
:provider,
56-
:provider_id,
57-
:provider_meta,
58-
:title,
59-
:url
60-
])
24+
|> cast(attrs, [:source_id, :target_id, :user_id, :status, :type, :url, :group_id])
25+
|> validate_required([:target_id, :user_id, :status, :type, :url])
6126
|> generate_id()
6227
|> put_group_id()
63-
|> foreign_key_constraint(:ticket_id)
28+
|> foreign_key_constraint(:source_id)
29+
|> foreign_key_constraint(:target_id)
6430
|> foreign_key_constraint(:user_id)
65-
|> unique_constraint([:ticket_id, :user_id])
31+
|> unique_constraint([:target_id, :user_id])
6632
end
6733

6834
def put_group_id(changeset) do

lib/algora/workspace/schemas/ticket.ex

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ defmodule Algora.Workspace.Ticket do
1818

1919
belongs_to :repository, Algora.Workspace.Repository
2020
has_many :bounties, Algora.Bounties.Bounty
21-
has_many :claims, Algora.Bounties.Claim
2221

2322
timestamps()
2423
end

lib/algora_web/controllers/webhooks/github_controller.ex

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,19 +117,28 @@ defmodule AlgoraWeb.Webhooks.GithubController do
117117
pull_request = params["pull_request"]
118118
repo = params["repository"]
119119

120-
ticket_ref = %{
121-
owner: args[:ticket_ref][:owner] || repo["owner"]["login"],
122-
repo: args[:ticket_ref][:repo] || repo["name"],
123-
number: args[:ticket_ref][:number]
120+
source_ticket_ref = %{
121+
owner: repo["owner"]["login"],
122+
repo: repo["name"],
123+
number: pull_request["number"]
124124
}
125125

126+
target_ticket_ref =
127+
%{
128+
owner: args[:ticket_ref][:owner] || source_ticket_ref.owner,
129+
repo: args[:ticket_ref][:repo] || source_ticket_ref.repo,
130+
number: args[:ticket_ref][:number]
131+
}
132+
126133
with {:ok, token} <- Github.get_installation_token(installation_id),
127134
{:ok, user} <- Workspace.ensure_user(token, author["login"]) do
128135
Bounties.claim_bounty(
129136
%{
130137
user: user,
131-
ticket_ref: ticket_ref,
132-
pull_request: pull_request
138+
target_ticket_ref: target_ticket_ref,
139+
source_ticket_ref: source_ticket_ref,
140+
status: if(pull_request["merged_at"], do: :approved, else: :pending),
141+
type: :pull_request
133142
},
134143
installation_id: installation_id
135144
)

priv/repo/migrations/20250112164132_recreate_claims.exs

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,37 +7,28 @@ defmodule Algora.Repo.Migrations.RecreateClaims do
77
drop table(:claims)
88

99
create table(:claims) do
10-
add :provider, :string, null: false
11-
add :provider_id, :string, null: false
12-
add :provider_meta, :map, null: false
13-
14-
add :opened_at, :utc_datetime_usec
15-
add :merged_at, :utc_datetime_usec
16-
add :approved_at, :utc_datetime_usec
17-
add :rejected_at, :utc_datetime_usec
18-
add :charged_at, :utc_datetime_usec
19-
add :paid_at, :utc_datetime_usec
20-
10+
add :status, :string, null: false
2111
add :type, :string, null: false
22-
add :title, :string, null: false
23-
add :description, :string
2412
add :url, :string, null: false
2513
add :group_id, :string, null: false
2614

27-
add :ticket_id, references(:tickets, on_delete: :nothing), null: false
15+
add :source_id, references(:tickets, on_delete: :nothing), null: false
16+
add :target_id, references(:tickets, on_delete: :nothing), null: false
2817
add :user_id, references(:users, on_delete: :nothing), null: false
2918

3019
timestamps()
3120
end
3221

33-
create unique_index(:claims, [:ticket_id, :user_id])
34-
create index(:claims, [:ticket_id])
22+
create unique_index(:claims, [:target_id, :user_id])
23+
create index(:claims, [:source_id])
24+
create index(:claims, [:target_id])
3525
create index(:claims, [:user_id])
3626
end
3727

3828
def down do
39-
drop unique_index(:claims, [:ticket_id, :user_id])
40-
drop index(:claims, [:ticket_id])
29+
drop unique_index(:claims, [:target_id, :user_id])
30+
drop index(:claims, [:source_id])
31+
drop index(:claims, [:target_id])
4132
drop index(:claims, [:user_id])
4233
drop table(:claims)
4334

priv/repo/seeds.exs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ for {repo_name, issues} <- repos do
355355
})
356356

357357
for {issue_title, index} <- Enum.with_index(issues, 1) do
358-
ticket =
358+
issue =
359359
insert!(:ticket, %{
360360
repository_id: repo.id,
361361
title: issue_title,
@@ -371,7 +371,7 @@ for {repo_name, issues} <- repos do
371371

372372
bounty =
373373
insert!(:bounty, %{
374-
ticket_id: ticket.id,
374+
ticket_id: issue.id,
375375
owner_id: pied_piper.id,
376376
creator_id: richard.id,
377377
amount: amount,
@@ -385,7 +385,7 @@ for {repo_name, issues} <- repos do
385385
amount = Money.new!(Enum.random([500, 1000, 1500, 2000]), :USD)
386386

387387
insert!(:bounty, %{
388-
ticket_id: ticket.id,
388+
ticket_id: issue.id,
389389
owner_id: member.id,
390390
creator_id: member.id,
391391
amount: amount,
@@ -395,15 +395,24 @@ for {repo_name, issues} <- repos do
395395
end
396396

397397
if claimed do
398-
claim =
399-
insert!(:claim, %{
400-
bounty_id: bounty.id,
398+
pull_request =
399+
insert!(:ticket, %{
401400
user_id: carver.id,
402401
title: "Implementation for #{issue_title}",
403402
description: "Here's my solution to this issue.",
404403
url: "https://github.com/piedpiper/#{repo_name}/pull/#{index}"
405404
})
406405

406+
claim =
407+
insert!(:claim, %{
408+
user_id: carver.id,
409+
target_id: pull_request.id,
410+
source_id: issue.id,
411+
type: :pull_request,
412+
status: if(paid, do: :paid, else: :pending),
413+
url: "https://github.com/piedpiper/#{repo_name}/pull/#{index}"
414+
})
415+
407416
# Create transaction pairs for paid claims
408417
if paid do
409418
debit_id = Nanoid.generate()

test/support/factory.ex

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -197,12 +197,8 @@ defmodule Algora.Factory do
197197
def claim_factory do
198198
%Algora.Bounties.Claim{
199199
id: Nanoid.generate(),
200-
provider: "github",
201-
provider_id: sequence(:provider_id, &"#{&1}"),
202-
title: "Implemented compression optimization",
203-
description: "Added parallel processing for large files",
204-
url: "https://github.com/piedpiper/middle-out/pull/2",
205-
provider_meta: %{}
200+
type: :pull_request,
201+
status: :pending
206202
}
207203
end
208204

0 commit comments

Comments
 (0)