Skip to content

Commit e138991

Browse files
authored
Merge pull request #1075 from code-corps/928-add-info-to-github-issue-when-codecorps-user-created-via-bot
Add info to GitHub issue when codecorps user created via bot
2 parents 4ea97ae + 4cb7ad2 commit e138991

26 files changed

+278
-170
lines changed

lib/code_corps/comment/service.ex

+17-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,23 @@ defmodule CodeCorps.Comment.Service do
1717

1818
require Logger
1919

20-
@preloads [:user, :github_comment, task: [:github_issue, github_repo: :github_app_installation]]
20+
# :user, :github_issue and :github_repo are required for connecting to github
21+
# :project and :organization are required in order to add a header to the
22+
# github comment body when the user themselves are not connected to github,
23+
# but the parent task is
24+
#
25+
# Right now, all of these preloads are loaded at once. If there are
26+
# performance issues, we can split them up according the the information
27+
# provided here.
28+
@preloads [
29+
:github_comment,
30+
:user,
31+
task: [
32+
:github_issue,
33+
[github_repo: :github_app_installation],
34+
[project: :organization]
35+
]
36+
]
2137

2238
@doc ~S"""
2339
Creates a `Comment` record using the provided parameters
@@ -55,8 +71,6 @@ defmodule CodeCorps.Comment.Service do
5571
{:error, :github}
5672
end
5773

58-
@preloads [task: [:github_issue, github_repo: :github_app_installation]]
59-
6074
@spec create_on_github(Comment.t) :: {:ok, Comment.t} :: {:error, GitHub.api_error_struct}
6175
defp create_on_github(%Comment{task: %Task{github_issue_id: nil}} = comment), do: {:ok, comment}
6276
defp create_on_github(%Comment{task: %Task{github_issue: github_issue}} = comment) do

lib/code_corps/emails/forgot_password_email.ex

+2-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ defmodule CodeCorps.Emails.ForgotPasswordEmail do
22
import Bamboo.Email
33
import Bamboo.PostmarkHelper
44

5-
alias CodeCorps.Emails.BaseEmail
5+
alias CodeCorps.{Emails.BaseEmail, WebClient}
66

77
def create(user, token) do
88
BaseEmail.create
@@ -13,8 +13,7 @@ defmodule CodeCorps.Emails.ForgotPasswordEmail do
1313
defp template_id, do: Application.get_env(:code_corps, :postmark_forgot_password_template)
1414

1515
defp link(token) do
16-
:code_corps
17-
|> Application.get_env(:site_url)
16+
WebClient.url()
1817
|> URI.merge("password/reset?token=#{token}")
1918
|> URI.to_string
2019
end

lib/code_corps/emails/organization_invite_email.ex

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ defmodule CodeCorps.Emails.OrganizationInviteEmail do
22
import Bamboo.Email
33
import Bamboo.PostmarkHelper
44

5-
alias CodeCorps.{Emails.BaseEmail, OrganizationInvite}
5+
alias CodeCorps.{Emails.BaseEmail, OrganizationInvite, WebClient}
66

77
def create(%OrganizationInvite{} = invite) do
88
BaseEmail.create
@@ -19,7 +19,7 @@ defmodule CodeCorps.Emails.OrganizationInviteEmail do
1919
end
2020

2121
defp invite_url(code, organization_name) do
22-
Application.get_env(:code_corps, :site_url)
22+
WebClient.url()
2323
|> URI.merge("/invites/organization" <> "?" <> set_params(code, organization_name))
2424
|> URI.to_string
2525
end

lib/code_corps/emails/project_user_acceptance_email.ex

+2-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ defmodule CodeCorps.Emails.ProjectUserAcceptanceEmail do
22
import Bamboo.Email
33
import Bamboo.PostmarkHelper
44

5-
alias CodeCorps.{Project, ProjectUser, Repo, User}
5+
alias CodeCorps.{Project, ProjectUser, Repo, User, WebClient}
66
alias CodeCorps.Emails.BaseEmail
77
alias CodeCorps.Presenters.ImagePresenter
88

@@ -26,8 +26,7 @@ defmodule CodeCorps.Emails.ProjectUserAcceptanceEmail do
2626
defp preload(%Project{} = project), do: project |> Repo.preload(:organization)
2727

2828
defp url(project) do
29-
:code_corps
30-
|> Application.get_env(:site_url)
29+
WebClient.url()
3130
|> URI.merge(project.organization.slug <> "/" <> project.slug)
3231
|> URI.to_string
3332
end

lib/code_corps/emails/receipt_email.ex

+2-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ defmodule CodeCorps.Emails.ReceiptEmail do
33
import Bamboo.PostmarkHelper
44

55
alias CodeCorps.Emails.BaseEmail
6-
alias CodeCorps.{DonationGoal, Project, Repo, StripeConnectCharge, StripeConnectSubscription}
6+
alias CodeCorps.{DonationGoal, Project, Repo, StripeConnectCharge, StripeConnectSubscription, WebClient}
77

88
def create(%StripeConnectCharge{} = charge, %Stripe.Invoice{} = invoice) do
99
with %StripeConnectCharge{} = charge <- preload(charge),
@@ -77,8 +77,7 @@ defmodule CodeCorps.Emails.ReceiptEmail do
7777
end
7878

7979
defp url(project) do
80-
:code_corps
81-
|> Application.get_env(:site_url)
80+
WebClient.url()
8281
|> URI.merge(project.organization.slug <> "/" <> project.slug)
8382
|> URI.to_string
8483
end
+31-19
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
defmodule CodeCorps.GitHub.Adapters.Comment do
2-
@moduledoc """
3-
Adapts a GitHub payload into attributes for creating or updating a
4-
`CodeCorps.GithubComment` record.
2+
@moduledoc ~S"""
3+
Used to convert between GitHub data which represents a GitHub Issue Comment
4+
and `CodeCorps.Comment` as well as `CodeCorps.GithubComment` attributes.
55
"""
66

77
alias CodeCorps.{
88
Adapter.MapTransformer,
9-
Comment
9+
Comment,
10+
GitHub.Adapters.Utils.BodyDecorator
1011
}
1112

1213
@mapping [
@@ -15,19 +16,15 @@ defmodule CodeCorps.GitHub.Adapters.Comment do
1516
{:modified_at, ["updated_at"]}
1617
]
1718

18-
@spec from_api(map) :: map
19-
def from_api(%{} = payload) do
20-
payload |> MapTransformer.transform(@mapping)
21-
end
22-
23-
@autogenerated_github_keys ~w(created_at id updated_at)
24-
25-
@spec to_api(Comment.t) :: map
26-
def to_api(%Comment{} = comment) do
27-
comment
28-
|> Map.from_struct
29-
|> MapTransformer.transform_inverse(@mapping)
30-
|> Map.drop(@autogenerated_github_keys)
19+
@doc ~S"""
20+
Converts a Github Issue Comment payload into a set of attributes suitable to
21+
create or update a `CodeCorps.Comment`
22+
"""
23+
@spec to_comment(map) :: map
24+
def to_comment(%{} = payload) do
25+
payload
26+
|> BodyDecorator.remove_code_corps_header()
27+
|> MapTransformer.transform(@mapping)
3128
end
3229

3330
@github_comment_mapping [
@@ -40,11 +37,26 @@ defmodule CodeCorps.GitHub.Adapters.Comment do
4037
]
4138

4239
@doc ~S"""
43-
Adapts the GitHub payload into attributes for creating or updating a
44-
`CodeCorps.GithubComment` record.
40+
Converts a GitHub Issue Comment payload into a set of attributes suitable for
41+
creating or updating a `CodeCorps.GithubComment`
4542
"""
4643
@spec to_github_comment(map) :: map
4744
def to_github_comment(%{} = payload) do
4845
payload |> MapTransformer.transform(@github_comment_mapping)
4946
end
47+
48+
@autogenerated_github_keys ~w(created_at id updated_at)
49+
50+
@doc ~S"""
51+
Converts a `CodeCorps.Comment` into a set of attributes suitable to create or
52+
update an GitHub Issue Comment through the GitHub API.
53+
"""
54+
@spec to_api(Comment.t) :: map
55+
def to_api(%Comment{} = comment) do
56+
comment
57+
|> Map.from_struct
58+
|> MapTransformer.transform_inverse(@mapping)
59+
|> Map.drop(@autogenerated_github_keys)
60+
|> BodyDecorator.add_code_corps_header(comment)
61+
end
5062
end

lib/code_corps/github/adapters/issue.ex

+38-11
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ defmodule CodeCorps.GitHub.Adapters.Issue do
66

77
alias CodeCorps.{
88
Adapter.MapTransformer,
9-
GithubIssue
9+
GitHub.Adapters.Utils.BodyDecorator,
10+
GithubIssue,
11+
Task
1012
}
1113

12-
@mapping [
14+
@issue_mapping [
1315
{:body, ["body"]},
1416
{:closed_at, ["closed_at"]},
1517
{:comments_url, ["comments_url"]},
@@ -27,25 +29,50 @@ defmodule CodeCorps.GitHub.Adapters.Issue do
2729
]
2830

2931
@doc ~S"""
30-
Converts a GitHub Issue payload into a set of attributes used to update or
31-
create a `GithubIssue` record.
32+
Converts a GitHub Issue payload into a set of attributes used to create or
33+
update a `GithubIssue` record.
3234
"""
33-
@spec from_api(map) :: map
34-
def from_api(%{} = payload) do
35-
payload |> MapTransformer.transform(@mapping)
35+
@spec to_issue(map) :: map
36+
def to_issue(%{} = payload) do
37+
payload |> MapTransformer.transform(@issue_mapping)
38+
end
39+
40+
@task_mapping [
41+
{:created_at, ["created_at"]},
42+
{:markdown, ["body"]},
43+
{:modified_at, ["updated_at"]},
44+
{:status, ["state"]},
45+
{:title, ["title"]}
46+
]
47+
48+
@doc ~S"""
49+
Converts a GitHub Issue payload into a set of attributes used to create or
50+
update a `Task` record.
51+
"""
52+
@spec to_task(map) :: map
53+
def to_task(%{} = payload) do
54+
payload |> MapTransformer.transform(@task_mapping)
3655
end
3756

3857
@autogenerated_github_keys ~w(closed_at comments_url created_at events_url html_url id labels_url number updated_at url)
3958

4059
@doc ~S"""
41-
Converts a `GithubIssue` into a set of attributes used to update or create an
42-
associated GitHub Issue.
60+
Converts a `GithubIssue` or `Task` into a set of attributes used to create or
61+
update an associated GitHub Issue on the GitHub API.
4362
"""
44-
@spec to_api(GithubIssue.t) :: map
63+
@spec to_api(GithubIssue.t | Task.t) :: map
4564
def to_api(%GithubIssue{} = github_issue) do
4665
github_issue
4766
|> Map.from_struct
48-
|> MapTransformer.transform_inverse(@mapping)
67+
|> MapTransformer.transform_inverse(@issue_mapping)
68+
|> Map.drop(@autogenerated_github_keys)
69+
|> BodyDecorator.add_code_corps_header(github_issue)
70+
end
71+
def to_api(%Task{} = task) do
72+
task
73+
|> Map.from_struct
74+
|> MapTransformer.transform_inverse(@task_mapping)
4975
|> Map.drop(@autogenerated_github_keys)
76+
|> BodyDecorator.add_code_corps_header(task)
5077
end
5178
end

lib/code_corps/github/adapters/task.ex

-43
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
defmodule CodeCorps.GitHub.Adapters.Utils.BodyDecorator do
2+
@moduledoc ~S"""
3+
Decorates and undecorates the body of GitHub issues and comments as needed.
4+
"""
5+
6+
alias CodeCorps.{
7+
Comment,
8+
Task,
9+
User,
10+
WebClient
11+
}
12+
13+
@separator "\r\n\r\n[//]: # (Please type your edits below this line)\r\n\r\n---"
14+
@linebreak "\r\n\r\n"
15+
16+
@spec add_code_corps_header(map, Comment.t | Task.t) :: map
17+
def add_code_corps_header(%{"body" => body} = attrs, %Comment{user: %User{github_id: nil}} = comment) do
18+
modified_body = build_header(comment) <> @separator <> @linebreak <> body
19+
attrs |> Map.put("body", modified_body)
20+
end
21+
def add_code_corps_header(%{"body" => body} = attrs, %Task{user: %User{github_id: nil}} = task) do
22+
modified_body = build_header(task) <> @separator <> @linebreak <> body
23+
attrs |> Map.put("body", modified_body)
24+
end
25+
def add_code_corps_header(%{} = attrs, _), do: attrs
26+
27+
@spec build_header(Comment.t | Task.t) :: String.t
28+
defp build_header(%Comment{task: %Task{} = task, user: %User{} = user}), do: do_build_header(task, user)
29+
defp build_header(%Task{user: %User{} = user} = task), do: do_build_header(task, user)
30+
31+
32+
@spec do_build_header(Task.t, User.t) :: String.t
33+
defp do_build_header(%Task{} = task, %User{username: username} = user) do
34+
"Posted by [**#{username}**](#{user |> WebClient.url}) from [Code Corps](#{task |> WebClient.url})"
35+
end
36+
37+
@spec remove_code_corps_header(map) :: map
38+
def remove_code_corps_header(%{"body" => body} = attrs) when is_binary(body) do
39+
clean_body = case body |> String.split(@separator) do
40+
["Posted by" <> _rest | tail] -> tail |> Enum.join |> String.trim_leading
41+
_ -> body
42+
end
43+
attrs |> Map.put("body", clean_body)
44+
end
45+
def remove_code_corps_header(%{} = attrs), do: attrs
46+
end

lib/code_corps/github/event/issue_comment/changeset_builder.ex

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ defmodule CodeCorps.GitHub.Event.IssueComment.ChangesetBuilder do
4343
%User{} = user) do
4444

4545
comment
46-
|> Changeset.cast(CommentAdapter.from_api(attrs), @create_attrs)
46+
|> Changeset.cast(CommentAdapter.to_comment(attrs), @create_attrs)
4747
|> MarkdownRendererService.render_markdown_to_html(:markdown, :body)
4848
|> Changeset.put_change(:created_from, "github")
4949
|> Changeset.put_change(:modified_from, "github")
@@ -57,7 +57,7 @@ defmodule CodeCorps.GitHub.Event.IssueComment.ChangesetBuilder do
5757
@spec update_changeset(Comment.t, map) :: Changeset.t
5858
defp update_changeset(%Comment{} = comment, %{} = attrs) do
5959
comment
60-
|> Changeset.cast(CommentAdapter.from_api(attrs), @update_attrs)
60+
|> Changeset.cast(CommentAdapter.to_comment(attrs), @update_attrs)
6161
|> MarkdownRendererService.render_markdown_to_html(:markdown, :body)
6262
|> Changeset.put_change(:modified_from, "github")
6363
|> TimeValidator.validate_time_after(:modified_at)

lib/code_corps/github/event/issues/changeset_builder.ex

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ defmodule CodeCorps.GitHub.Event.Issues.ChangesetBuilder do
1414
User,
1515
Validators.TimeValidator
1616
}
17-
alias CodeCorps.GitHub.Adapters.Task, as: TaskAdapter
17+
alias CodeCorps.GitHub.Adapters.Issue, as: IssueAdapter
1818
alias Ecto.Changeset
1919

2020
@doc ~S"""
@@ -50,7 +50,7 @@ defmodule CodeCorps.GitHub.Event.Issues.ChangesetBuilder do
5050
TaskList |> Repo.get_by(project_id: project_id, inbox: true)
5151

5252
task
53-
|> Changeset.cast(TaskAdapter.from_api(issue_attrs), @create_attrs)
53+
|> Changeset.cast(IssueAdapter.to_task(issue_attrs), @create_attrs)
5454
|> MarkdownRendererService.render_markdown_to_html(:markdown, :body)
5555
|> Changeset.put_change(:created_from, "github")
5656
|> Changeset.put_change(:modified_from, "github")
@@ -71,7 +71,7 @@ defmodule CodeCorps.GitHub.Event.Issues.ChangesetBuilder do
7171
@spec update_changeset(Task.t, map) :: Changeset.t
7272
defp update_changeset(%Task{} = task, %{} = issue_attrs) do
7373
task
74-
|> Changeset.cast(TaskAdapter.from_api(issue_attrs), @update_attrs)
74+
|> Changeset.cast(IssueAdapter.to_task(issue_attrs), @update_attrs)
7575
|> MarkdownRendererService.render_markdown_to_html(:markdown, :body)
7676
|> Changeset.put_change(:modified_from, "github")
7777
|> TimeValidator.validate_time_after(:modified_at)

0 commit comments

Comments
 (0)