1
1
defmodule Algora.Bounties.Jobs.NotifyBounty do
2
2
@ moduledoc false
3
- use Oban.Worker , queue: :notify_bounty
3
+ use Oban.Worker ,
4
+ queue: :notify_bounty ,
5
+ max_attempts: 1
4
6
5
- alias Algora.Accounts
6
7
alias Algora.Accounts.User
8
+ alias Algora.Bounties
7
9
alias Algora.Github
10
+ alias Algora.Repo
11
+ alias Algora.Util
8
12
alias Algora.Workspace
13
+ alias Algora.Workspace.CommandResponse
9
14
10
15
require Logger
11
16
12
17
@ impl Oban.Worker
13
18
def perform ( % Oban.Job {
14
- args: % { "owner_login" => owner_login , "amount" => amount , "ticket_ref" => ticket_ref , "installation_id" => nil }
19
+ args: % {
20
+ "owner_login" => owner_login ,
21
+ "amount" => amount ,
22
+ "ticket_ref" => ticket_ref ,
23
+ "installation_id" => nil ,
24
+ "command_id" => command_id ,
25
+ "command_source" => command_source
26
+ }
15
27
} ) do
16
28
body = """
17
29
💎 **#{ owner_login } ** is offering a **#{ amount } ** bounty for this issue
@@ -20,13 +32,19 @@ defmodule Algora.Bounties.Jobs.NotifyBounty do
20
32
"""
21
33
22
34
if Github . pat_enabled ( ) do
23
- Github . create_issue_comment (
24
- Github . pat ( ) ,
25
- ticket_ref [ "owner" ] ,
26
- ticket_ref [ "repo" ] ,
27
- ticket_ref [ "number" ] ,
28
- body
29
- )
35
+ with { :ok , response } <-
36
+ Github . create_issue_comment (
37
+ Github . pat ( ) ,
38
+ ticket_ref [ "owner" ] ,
39
+ ticket_ref [ "repo" ] ,
40
+ ticket_ref [ "number" ] ,
41
+ body
42
+ ) ,
43
+ { :ok , ticket } <-
44
+ Workspace . ensure_ticket ( Github . pat ( ) , ticket_ref [ "owner" ] , ticket_ref [ "repo" ] , ticket_ref [ "number" ] ) do
45
+ # TODO: update existing command response if it exists
46
+ create_command_response ( response , command_source , command_id , ticket . id )
47
+ end
30
48
else
31
49
Logger . info ( """
32
50
Github.create_issue_comment(Github.pat(), "#{ ticket_ref [ "owner" ] } ", "#{ ticket_ref [ "repo" ] } ", #{ ticket_ref [ "number" ] } ,
@@ -38,14 +56,26 @@ defmodule Algora.Bounties.Jobs.NotifyBounty do
38
56
end
39
57
40
58
@ impl Oban.Worker
41
- def perform ( % Oban.Job { args: % { "amount" => amount , "ticket_ref" => ticket_ref , "installation_id" => installation_id } } ) do
59
+ def perform ( % Oban.Job {
60
+ args: % {
61
+ "amount" => _amount ,
62
+ "ticket_ref" => ticket_ref ,
63
+ "installation_id" => installation_id ,
64
+ "command_id" => command_id ,
65
+ "command_source" => command_source
66
+ }
67
+ } ) do
42
68
with { :ok , token } <- Github . get_installation_token ( installation_id ) ,
43
- { :ok , installation } <-
44
- Workspace . fetch_installation_by ( provider: "github" , provider_id: to_string ( installation_id ) ) ,
45
- { :ok , owner } <- Accounts . fetch_user_by ( id: installation . connected_user_id ) ,
69
+ { :ok , ticket } <- Workspace . ensure_ticket ( token , ticket_ref [ "owner" ] , ticket_ref [ "repo" ] , ticket_ref [ "number" ] ) ,
70
+ bounties when bounties != [ ] <- Bounties . list_bounties ( ticket_id: ticket . id ) ,
46
71
{ :ok , _ } <- Github . add_labels ( token , ticket_ref [ "owner" ] , ticket_ref [ "repo" ] , ticket_ref [ "number" ] , [ "💎 Bounty" ] ) do
72
+ header =
73
+ Enum . map_join ( bounties , "\n " , fn bounty ->
74
+ "## 💎 #{ bounty . amount } bounty [• #{ bounty . owner . name } ](#{ User . url ( bounty . owner ) } )"
75
+ end )
76
+
47
77
body = """
48
- ## 💎 #{ amount } bounty [• #{ owner . name } ]( #{ User . url ( owner ) } )
78
+ #{ header }
49
79
### Steps to solve:
50
80
1. **Start working**: Comment `/attempt ##{ ticket_ref [ "number" ] } ` with your implementation plan
51
81
2. **Submit work**: Create a pull request including `/claim ##{ ticket_ref [ "number" ] } ` in the PR body to claim the bounty
@@ -54,13 +84,69 @@ defmodule Algora.Bounties.Jobs.NotifyBounty do
54
84
Thank you for contributing to #{ ticket_ref [ "owner" ] } /#{ ticket_ref [ "repo" ] } !
55
85
"""
56
86
57
- Github . create_issue_comment (
58
- token ,
59
- ticket_ref [ "owner" ] ,
60
- ticket_ref [ "repo" ] ,
61
- ticket_ref [ "number" ] ,
62
- body
63
- )
87
+ ensure_command_response ( token , ticket_ref , command_id , command_source , ticket , body )
88
+ end
89
+ end
90
+
91
+ defp ensure_command_response ( token , ticket_ref , command_id , command_source , ticket , body ) do
92
+ case Workspace . fetch_command_response ( ticket . id , :bounty ) do
93
+ { :ok , response } ->
94
+ case Github . update_issue_comment (
95
+ token ,
96
+ ticket_ref [ "owner" ] ,
97
+ ticket_ref [ "repo" ] ,
98
+ response . provider_response_id ,
99
+ body
100
+ ) do
101
+ { :ok , comment } ->
102
+ try_update_command_response ( response , comment )
103
+
104
+ { :error , "404 Not Found" } ->
105
+ with { :ok , _ } <- Workspace . delete_command_response ( response . id ) do
106
+ post_response ( token , ticket_ref , command_id , command_source , ticket , body )
107
+ end
108
+
109
+ { :error , reason } ->
110
+ Logger . error ( "Failed to update command response #{ response . id } : #{ inspect ( reason ) } " )
111
+ { :error , reason }
112
+ end
113
+
114
+ { :error , _reason } ->
115
+ post_response ( token , ticket_ref , command_id , command_source , ticket , body )
116
+ end
117
+ end
118
+
119
+ defp post_response ( token , ticket_ref , command_id , command_source , ticket , body ) do
120
+ with { :ok , comment } <-
121
+ Github . create_issue_comment ( token , ticket_ref [ "owner" ] , ticket_ref [ "repo" ] , ticket_ref [ "number" ] , body ) do
122
+ create_command_response ( comment , command_source , command_id , ticket . id )
123
+ end
124
+ end
125
+
126
+ defp create_command_response ( comment , command_source , command_id , ticket_id ) do
127
+ % CommandResponse { }
128
+ |> CommandResponse . changeset ( % {
129
+ provider: "github" ,
130
+ provider_meta: Util . normalize_struct ( comment ) ,
131
+ provider_command_id: to_string ( command_id ) ,
132
+ provider_response_id: to_string ( comment [ "id" ] ) ,
133
+ command_source: command_source ,
134
+ command_type: :bounty ,
135
+ ticket_id: ticket_id
136
+ } )
137
+ |> Repo . insert ( )
138
+ end
139
+
140
+ defp try_update_command_response ( command_response , body ) do
141
+ case command_response
142
+ |> CommandResponse . changeset ( % { provider_meta: Util . normalize_struct ( body ) } )
143
+ |> Repo . update ( ) do
144
+ { :ok , command_response } ->
145
+ { :ok , command_response }
146
+
147
+ { :error , reason } ->
148
+ Logger . error ( "Failed to update command response #{ command_response . id } : #{ inspect ( reason ) } " )
149
+ { :ok , command_response }
64
150
end
65
151
end
66
152
end
0 commit comments