Skip to content

Commit 4764879

Browse files
authored
Merge pull request #1190 from code-corps/restrict-github-repo-to-single-project
Restrict GithubRepo to connect to single project
2 parents 302e89a + a7d1d3d commit 4764879

34 files changed

+485
-576
lines changed

Diff for: config/prod.exs

-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ config :code_corps, :stripe_env, :prod
5555
config :sentry,
5656
environment_name: Mix.env || :prod
5757

58-
# TODO: Replace with actual adapter
5958
config :code_corps, CodeCorps.Mailer,
6059
adapter: Bamboo.PostmarkAdapter,
6160
api_key: System.get_env("POSTMARK_API_KEY")

Diff for: lib/code_corps/github/adapters/comment.ex

+19-23
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,19 @@ defmodule CodeCorps.GitHub.Adapters.Comment do
1111
GitHub.Adapters.Utils.BodyDecorator
1212
}
1313

14-
@mapping [
14+
@github_comment_to_comment_mapping [
15+
{:created_at, [:github_created_at]},
16+
{:markdown, [:body]},
17+
{:modified_at, [:github_updated_at]}
18+
]
19+
20+
@github_payload_to_comment_mapping [
1521
{:created_at, ["created_at"]},
1622
{:markdown, ["body"]},
1723
{:modified_at, ["updated_at"]}
1824
]
1925

20-
@doc ~S"""
21-
Converts a Github Issue Comment payload into a set of attributes suitable for
22-
creating or updating a `CodeCorps.Comment`
23-
"""
24-
@spec to_comment(map) :: map
25-
def to_comment(%{} = payload) do
26-
payload
27-
|> BodyDecorator.remove_code_corps_header()
28-
|> MapTransformer.transform(@mapping)
29-
end
30-
31-
@github_comment_mapping [
26+
@github_payload_to_github_comment_mapping [
3227
{:body, ["body"]},
3328
{:github_created_at, ["created_at"]},
3429
{:github_id, ["id"]},
@@ -38,14 +33,15 @@ defmodule CodeCorps.GitHub.Adapters.Comment do
3833
]
3934

4035
@doc ~S"""
41-
Converts a `GithubComment` record into attributes with the same keys as the
42-
GitHub API's Issue Comment
36+
Converts a `CodeCorps.GithubComment` into a set of attributes suitable for
37+
creating or updating a `CodeCorps.Comment`
4338
"""
44-
@spec to_comment_attrs(GithubComment.t) :: map
45-
def to_comment_attrs(%GithubComment{} = github_comment) do
39+
@spec to_comment(GithubComment.t) :: map
40+
def to_comment(%GithubComment{} = github_comment) do
4641
github_comment
47-
|> Map.from_struct
48-
|> MapTransformer.transform_inverse(@github_comment_mapping)
42+
|> Map.from_struct()
43+
|> BodyDecorator.remove_code_corps_header()
44+
|> MapTransformer.transform(@github_comment_to_comment_mapping)
4945
end
5046

5147
@doc ~S"""
@@ -54,20 +50,20 @@ defmodule CodeCorps.GitHub.Adapters.Comment do
5450
"""
5551
@spec to_github_comment(map) :: map
5652
def to_github_comment(%{} = payload) do
57-
payload |> MapTransformer.transform(@github_comment_mapping)
53+
payload |> MapTransformer.transform(@github_payload_to_github_comment_mapping)
5854
end
5955

6056
@autogenerated_github_keys ~w(created_at id updated_at)
6157

6258
@doc ~S"""
63-
Converts a `CodeCorps.Comment` into a set of attributes suitable to create or
64-
update an GitHub Issue Comment through the GitHub API.
59+
Converts a `CodeCorps.Comment` into a set of attributes suitable for creating
60+
or updating an GitHub Issue Comment through the GitHub API.
6561
"""
6662
@spec to_api(Comment.t) :: map
6763
def to_api(%Comment{} = comment) do
6864
comment
6965
|> Map.from_struct
70-
|> MapTransformer.transform_inverse(@mapping)
66+
|> MapTransformer.transform_inverse(@github_payload_to_comment_mapping)
7167
|> Map.drop(@autogenerated_github_keys)
7268
|> BodyDecorator.add_code_corps_header(comment)
7369
end

Diff for: lib/code_corps/github/adapters/utils/body_decorator.ex

+11-7
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,16 @@ defmodule CodeCorps.GitHub.Adapters.Utils.BodyDecorator do
3636
end
3737

3838
@spec remove_code_corps_header(map) :: map
39-
def remove_code_corps_header(%{"body" => body} = attrs) when is_binary(body) do
40-
clean_body = case body |> String.split(@separator) do
41-
["Posted by" <> _rest | tail] -> tail |> Enum.join |> String.trim_leading
42-
_ -> body
43-
end
44-
attrs |> Map.put("body", clean_body)
39+
def remove_code_corps_header(%{body: _} = attrs) do
40+
attrs |> Map.update(:body, nil, &clean_body/1)
4541
end
46-
def remove_code_corps_header(%{} = attrs), do: attrs
42+
43+
@spec clean_body(String.t | nil) :: String.t | nil
44+
defp clean_body("Posted by " <> @separator <> _rest = body) do
45+
body
46+
|> String.split(@separator)
47+
|> Enum.drop(1) |> Enum.join
48+
|> String.trim_leading
49+
end
50+
defp clean_body(body), do: body
4751
end

Diff for: lib/code_corps/github/sync/comment/comment.ex

+23-33
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,39 @@
11
defmodule CodeCorps.GitHub.Sync.Comment do
2-
alias CodeCorps.{
3-
GitHub,
4-
GithubComment,
5-
GithubIssue
6-
}
7-
alias GitHub.Sync.Comment.Comment, as: CommentCommentSyncer
8-
alias GitHub.Sync.Comment.GithubComment, as: CommentGithubCommentSyncer
9-
alias GitHub.Sync.User.RecordLinker, as: UserRecordLinker
2+
alias CodeCorps.GitHub.Sync
103
alias Ecto.Multi
114

125
@doc ~S"""
13-
Syncs a GitHub comment API payload with our data.
6+
Creates an `Ecto.Multi` intended to process a GitHub issue comment related API
7+
payload.
148
15-
Expects a `CodeCorps.GithubIssue` record and a list of `CodeCorps.Task`
16-
records passed in with the changes.
9+
Expects a partial transaction outcome with `:github_issue` and :task keys.
1710
18-
The process is as follows:
11+
Returns an `Ecto.Multi` with the follwing steps
1912
20-
- create a `CodeCorps.GithubComment` related to the `CodeCorps.GithubIssue`
21-
- match the comment payload with a `CodeCorps.User` using
22-
`CodeCorps.GitHub.Sync.User.RecordLinker`
23-
- for each `CodeCorps.Task`:
24-
- create or update `CodeCorps.Comment` for the `CodeCorps.Task`
13+
- create or update a `CodeCorps.GithubComment` from the
14+
provided `CodeCorps.GithubIssue` and API payload
15+
- match the `CodeCorps.GithubComment` with a new or existing `CodeCorps.User`
16+
- create or update a `CodeCorps.Comment` using the created
17+
`CodeCorps.GithubComment`, related to the matched `CodeCorps.User` and the
18+
provided `CodeCorps.Task`
2519
"""
2620
@spec sync(map, map) :: Multi.t
27-
def sync(%{github_issue: github_issue, tasks: tasks}, payload) do
21+
def sync(%{github_issue: github_issue, task: task}, %{} = payload) do
2822
Multi.new
29-
|> Multi.run(:github_comment, fn _ -> sync_github_comment(github_issue, payload) end)
30-
|> Multi.run(:comment_user, fn %{github_comment: github_comment} -> UserRecordLinker.link_to(github_comment, payload) end)
31-
|> Multi.run(:comments, fn %{github_comment: github_comment, comment_user: user} -> CommentCommentSyncer.sync_all(tasks, github_comment, user, payload) end)
23+
|> Multi.run(:github_comment, fn _ -> Sync.Comment.GithubComment.create_or_update_comment(github_issue, payload) end)
24+
|> Multi.run(:comment_user, fn %{github_comment: github_comment} -> Sync.User.RecordLinker.link_to(github_comment, payload) end)
25+
|> Multi.run(:comment, fn %{github_comment: github_comment, comment_user: user} -> Sync.Comment.Comment.sync(task, github_comment, user) end)
3226
end
3327

34-
@doc """
35-
When provided a GitHub API payload, it deletes each `Comment` associated to
36-
the specified `IssueComment` and then deletes the `GithubComment`.
28+
@doc ~S"""
29+
Creates an `Ecto.Multi` intended to delete a `CodeCorps.GithubComment`
30+
specified by `github_id`, as well as 0 to 1 `CodeCorps.Comment` records
31+
associated to `CodeCorps.GithubComment`
3732
"""
38-
@spec delete(map, map) :: Multi.t
39-
def delete(_, %{"id" => github_id}) do
33+
@spec delete(map) :: Multi.t
34+
def delete(%{"id" => github_id}) do
4035
Multi.new
41-
|> Multi.run(:deleted_comments, fn _ -> CommentCommentSyncer.delete_all(github_id) end)
42-
|> Multi.run(:deleted_github_comment, fn _ -> CommentGithubCommentSyncer.delete(github_id) end)
43-
end
44-
45-
@spec sync_github_comment(GithubIssue.t, map) :: {:ok, GithubComment.t} | {:error, Ecto.Changeset.t}
46-
defp sync_github_comment(github_issue, attrs) do
47-
CommentGithubCommentSyncer.create_or_update_comment(github_issue, attrs)
36+
|> Multi.run(:deleted_comments, fn _ -> Sync.Comment.Comment.delete(github_id) end)
37+
|> Multi.run(:deleted_github_comment, fn _ -> Sync.Comment.GithubComment.delete(github_id) end)
4838
end
4939
end

Diff for: lib/code_corps/github/sync/comment/comment/changeset.ex

+13-42
Original file line numberDiff line numberDiff line change
@@ -7,59 +7,30 @@ defmodule CodeCorps.GitHub.Sync.Comment.Comment.Changeset do
77
alias CodeCorps.{
88
Comment,
99
GithubComment,
10+
GitHub.Adapters,
1011
Services.MarkdownRendererService,
1112
Task,
1213
User,
1314
Validators.TimeValidator
1415
}
15-
alias CodeCorps.GitHub.Adapters.Comment, as: CommentAdapter
1616
alias Ecto.Changeset
1717

18+
@create_attrs ~w(created_at markdown modified_at)a
19+
@update_attrs ~w(markdown modified_at)a
20+
1821
@doc ~S"""
1922
Constructs a changeset for syncing a task from a GitHub API Comment payload.
20-
"""
21-
@spec build_changeset(Comment.t, map, GithubComment.t, Task.t, User.t) :: Changeset.t
22-
def build_changeset(
23-
%Comment{id: nil} = comment,
24-
%{} = attrs,
25-
%GithubComment{} = github_comment,
26-
%Task{} = task,
27-
%User{} = user) do
2823
29-
comment |> create_changeset(attrs, github_comment, task, user)
30-
end
31-
def build_changeset(%Comment{} = comment, attrs, %GithubComment{}, %Task{}, %User{}) do
32-
comment |> update_changeset(attrs)
33-
end
34-
35-
@doc ~S"""
36-
Constructs a changeset for syncing a task from a `GithubComment` record.
24+
The function detects if the `CodeCorps.Comment` is to be inserted or updated
25+
and acts accordingly.
3726
"""
3827
@spec build_changeset(Comment.t, GithubComment.t, Task.t, User.t) :: Changeset.t
3928
def build_changeset(
40-
%Comment{id: comment_id} = comment,
41-
%GithubComment{} = github_comment,
42-
%Task{} = task,
43-
%User{} = user) do
44-
45-
comment_attrs = github_comment |> CommentAdapter.to_comment_attrs()
46-
case is_nil(comment_id) do
47-
true -> create_changeset(comment, comment_attrs, github_comment, task, user)
48-
false -> update_changeset(comment, comment_attrs)
49-
end
50-
end
51-
52-
@create_attrs ~w(created_at markdown modified_at)a
53-
@spec create_changeset(Comment.t, map, GithubComment.t, Task.t, User.t) :: Changeset.t
54-
defp create_changeset(
55-
%Comment{} = comment,
56-
%{} = attrs,
57-
%GithubComment{} = github_comment,
58-
%Task{} = task,
59-
%User{} = user) do
29+
%Comment{id: nil} = comment,
30+
%GithubComment{} = github_comment, %Task{} = task, %User{} = user) do
6031

6132
comment
62-
|> Changeset.cast(CommentAdapter.to_comment(attrs), @create_attrs)
33+
|> Changeset.cast(github_comment |> Adapters.Comment.to_comment, @create_attrs)
6334
|> MarkdownRendererService.render_markdown_to_html(:markdown, :body)
6435
|> Changeset.put_change(:created_from, "github")
6536
|> Changeset.put_change(:modified_from, "github")
@@ -68,12 +39,12 @@ defmodule CodeCorps.GitHub.Sync.Comment.Comment.Changeset do
6839
|> Changeset.put_change(:user, user)
6940
|> Changeset.validate_required([:markdown, :body])
7041
end
42+
def build_changeset(
43+
%Comment{} = comment,
44+
%GithubComment{} = github_comment, %Task{}, %User{}) do
7145

72-
@update_attrs ~w(markdown modified_at)a
73-
@spec update_changeset(Comment.t, map) :: Changeset.t
74-
defp update_changeset(%Comment{} = comment, %{} = attrs) do
7546
comment
76-
|> Changeset.cast(CommentAdapter.to_comment(attrs), @update_attrs)
47+
|> Changeset.cast(github_comment |> Adapters.Comment.to_comment, @update_attrs)
7748
|> MarkdownRendererService.render_markdown_to_html(:markdown, :body)
7849
|> Changeset.put_change(:modified_from, "github")
7950
|> TimeValidator.validate_time_not_before(:modified_at)

0 commit comments

Comments
 (0)