diff --git a/lib/code_corps/analytics/segment_traits_builder.ex b/lib/code_corps/analytics/segment_traits_builder.ex index 95efccecb..1c06e559d 100644 --- a/lib/code_corps/analytics/segment_traits_builder.ex +++ b/lib/code_corps/analytics/segment_traits_builder.ex @@ -37,16 +37,22 @@ defmodule CodeCorps.Analytics.SegmentTraitsBuilder do user_id: installation.user_id } end - defp traits(%CodeCorps.ProjectGithubRepo{} = record) do - record = record |> Repo.preload([:project, :github_repo]) + defp traits(%CodeCorps.GithubRepo{} = record) do + project_title = + record + |> Repo.preload([:project]) + |> Map.get(:project) + |> (&(&1 || %{})).() + |> Map.get(:title, "") + %{ - project: record.project.title, - project_id: record.project_id, - github_repo_id: record.github_repo_id, - github_repo_github_account_login: record.github_repo.github_account_login, - github_repo_github_account_type: record.github_repo.github_account_type, - github_repo_github_id: record.github_repo.github_id, - github_repo_name: record.github_repo.name + id: record.id, + github_account_login: record.github_account_login, + github_account_type: record.github_account_type, + github_id: record.github_id, + github_repo_name: record.name, + project: project_title, + project_id: record.project_id } end defp traits(%CodeCorps.ProjectSkill{} = record) do diff --git a/lib/code_corps/github/event/installation_repositories/installation_repositories.ex b/lib/code_corps/github/event/installation_repositories/installation_repositories.ex index 4a8c542ea..03fc4e6b7 100644 --- a/lib/code_corps/github/event/installation_repositories/installation_repositories.ex +++ b/lib/code_corps/github/event/installation_repositories/installation_repositories.ex @@ -38,9 +38,6 @@ defmodule CodeCorps.GitHub.Event.InstallationRepositories do - delete affected `CodeCorps.GithubRepo` records, respecting the rules - if the GitHub payload for a repo is not matched with a record in our database, just skip deleting it - - if the deleted `CodeCorps.GithubRepo` record is associated with - `CodeCorps.ProjectGithubRepo` records, they are deleted automatically, - due to `on_delete: :delete_all` set at the database level. """ @spec handle(map) :: outcome def handle(payload) do diff --git a/lib/code_corps/github/sync/comment/comment/comment.ex b/lib/code_corps/github/sync/comment/comment/comment.ex index e0df3d923..2b0c4d7dc 100644 --- a/lib/code_corps/github/sync/comment/comment/comment.ex +++ b/lib/code_corps/github/sync/comment/comment/comment.ex @@ -18,8 +18,6 @@ defmodule CodeCorps.GitHub.Sync.Comment.Comment do GithubIssue, GithubRepo, GithubUser, - Project, - ProjectGithubRepo, Repo, Task, User @@ -48,29 +46,28 @@ defmodule CodeCorps.GitHub.Sync.Comment.Comment do @doc ~S""" Creates or updates `CodeCorps.Comment` records for the specified - `CodeCorps.ProjectGithubRepo`. + `CodeCorps.GithubRepo`. For each `CodeCorps.GithubComment` record that relates to the - `CodeCorps.GithubRepo` for a given`CodeCorps.ProjectGithubRepo`: + `CodeCorps.GithubRepo` for a given`CodeCorps.GithubRepo`: - Find the related `CodeCorps.Task` record - Create or update the related `CodeCorps.Comment` record - Associate the `CodeCorps.Comment` record with the `CodeCorps.User` that relates to the `CodeCorps.GithubUser` for the `CodeCorps.GithubComment` """ - @spec sync_project_github_repo(ProjectGithubRepo.t) :: outcome - def sync_project_github_repo(%ProjectGithubRepo{github_repo: %GithubRepo{} = _} = project_github_repo) do + @spec sync_github_repo(GithubRepo.t) :: outcome + def sync_github_repo(%GithubRepo{} = github_repo) do preloads = [ - :project, - github_repo: [github_comments: [:github_issue, github_user: [:user]]] + github_comments: [:github_issue, github_user: [:user]] ] - %ProjectGithubRepo{github_repo: %{github_comments: github_comments}} = - project_github_repo |> Repo.preload(preloads) + %GithubRepo{github_comments: github_comments} = + github_repo |> Repo.preload(preloads) github_comments |> Enum.map(fn %GithubComment{github_user: %GithubUser{user: %User{} = user}} = github_comment -> github_comment - |> find_task(project_github_repo) + |> find_task(github_repo) |> sync(github_comment, user) end) |> ResultAggregator.aggregate @@ -78,7 +75,7 @@ defmodule CodeCorps.GitHub.Sync.Comment.Comment do defp find_task( %GithubComment{github_issue: %GithubIssue{id: github_issue_id}}, - %ProjectGithubRepo{project: %Project{id: project_id}}) do + %GithubRepo{project_id: project_id}) do query = from t in Task, where: t.project_id == ^project_id, join: gi in GithubIssue, on: t.github_issue_id == gi.id, where: gi.id == ^github_issue_id diff --git a/lib/code_corps/github/sync/issue/issue.ex b/lib/code_corps/github/sync/issue/issue.ex index 5ea7688cc..aa057dc3e 100644 --- a/lib/code_corps/github/sync/issue/issue.ex +++ b/lib/code_corps/github/sync/issue/issue.ex @@ -10,9 +10,9 @@ defmodule CodeCorps.GitHub.Sync.Issue do The process is as follows: - - match with `User` using `GitHub.Sync.User.RecordLinker` - - for the `ProjectGithubRepo` belonging to the matched repo: - - create or update the `Task` for the `Project` + - match with `CodeCorps.User` using `CodeCorps.GitHub.Sync.User.RecordLinker` + - create or update the `CodeCorps.Task` for the `CodeCorps.Project` in the + matched `CodeCorps.GithubRepo` If the sync succeeds, it will return an `:ok` tuple with the created or updated task. diff --git a/lib/code_corps/github/sync/issue/task/changeset.ex b/lib/code_corps/github/sync/issue/task/changeset.ex index 1926edac0..d09ab1aa6 100644 --- a/lib/code_corps/github/sync/issue/task/changeset.ex +++ b/lib/code_corps/github/sync/issue/task/changeset.ex @@ -6,7 +6,7 @@ defmodule CodeCorps.GitHub.Sync.Issue.Task.Changeset do alias CodeCorps.{ GithubIssue, - ProjectGithubRepo, + GithubRepo, Repo, Services.MarkdownRendererService, Task, @@ -23,25 +23,25 @@ defmodule CodeCorps.GitHub.Sync.Issue.Task.Changeset do The changeset can be used to create or update a `Task` """ - @spec build_changeset(Task.t, GithubIssue.t, ProjectGithubRepo.t, User.t) :: Changeset.t + @spec build_changeset(Task.t, GithubIssue.t, GithubRepo.t, User.t) :: Changeset.t def build_changeset( %Task{id: task_id} = task, %GithubIssue{} = github_issue, - %ProjectGithubRepo{} = project_github_repo, + %GithubRepo{} = github_repo, %User{} = user) do case is_nil(task_id) do - true -> create_changeset(task, github_issue, project_github_repo, user) - false -> update_changeset(task, github_issue, project_github_repo) + true -> create_changeset(task, github_issue, github_repo, user) + false -> update_changeset(task, github_issue, github_repo) end end @create_attrs ~w(created_at markdown modified_at status title)a - @spec create_changeset(Task.t, GithubIssue.t, ProjectGithubRepo.t, User.t) :: Changeset.t + @spec create_changeset(Task.t, GithubIssue.t, GithubRepo.t, User.t) :: Changeset.t defp create_changeset( %Task{} = task, %GithubIssue{id: github_issue_id} = github_issue, - %ProjectGithubRepo{project_id: project_id, github_repo_id: github_repo_id}, + %GithubRepo{id: github_repo_id, project_id: project_id}, %User{id: user_id}) do task @@ -64,11 +64,11 @@ defmodule CodeCorps.GitHub.Sync.Issue.Task.Changeset do end @update_attrs ~w(markdown modified_at status title)a - @spec update_changeset(Task.t, GithubIssue.t, ProjectGithubRepo.t) :: Changeset.t + @spec update_changeset(Task.t, GithubIssue.t, GithubRepo.t) :: Changeset.t defp update_changeset( %Task{} = task, %GithubIssue{} = github_issue, - %ProjectGithubRepo{project_id: project_id}) do + %GithubRepo{project_id: project_id}) do task |> Changeset.cast(github_issue |> IssueAdapter.to_task, @update_attrs) |> MarkdownRendererService.render_markdown_to_html(:markdown, :body) diff --git a/lib/code_corps/github/sync/issue/task/task.ex b/lib/code_corps/github/sync/issue/task/task.ex index 37f0b7155..9afb27f28 100644 --- a/lib/code_corps/github/sync/issue/task/task.ex +++ b/lib/code_corps/github/sync/issue/task/task.ex @@ -1,15 +1,14 @@ defmodule CodeCorps.GitHub.Sync.Issue.Task do alias CodeCorps.{ + GitHub.Sync, GitHub.Utils.ResultAggregator, GithubIssue, GithubRepo, GithubUser, - ProjectGithubRepo, Task, User, Repo } - alias CodeCorps.GitHub.Sync.Issue.Task.Changeset, as: TaskChangeset alias Ecto.Changeset @type outcome :: {:ok, list(Task.t)} | @@ -17,59 +16,56 @@ defmodule CodeCorps.GitHub.Sync.Issue.Task do @doc """ When provided a `CodeCorps.GithubIssue` and a `CodeCorps.User`, for the - `CodeCorps.Project` associated to that `CodeCorps.GithubRepo` via a - `CodeCorps.ProjectGithubRepo`, it creates or updates a `CodeCorps.Task`. + `CodeCorps.Project` associated to that `CodeCorps.GithubRepo`, it creates or + updates a `CodeCorps.Task`. """ @spec sync_github_issue(GithubIssue.t, User.t) :: {:ok, Task.t} def sync_github_issue(%GithubIssue{} = github_issue, %User{} = user) do %GithubIssue{ - github_repo: %GithubRepo{project_github_repo: project_github_repo} - } = github_issue |> Repo.preload(github_repo: :project_github_repo) + github_repo: %GithubRepo{} = github_repo + } = github_issue |> Repo.preload(:github_repo) github_issue - |> sync(project_github_repo, user) + |> sync(github_repo, user) end @doc ~S""" - Creates or updates `CodeCorps.Task` records for the specified - `CodeCorps.ProjectGithubRepo`. - - For each `CodeCorps.GithubIssue` record that relates to the - `CodeCorps.GithubRepo` for a given `CodeCorps.ProjectGithubRepo`: + Creates or updates `CodeCorps.Task` records for each `CodeCorps.GithubIssue` + record that relates to the `CodeCorps.GithubRepo`: - Create or update the `CodeCorps.Task` - Associate the `CodeCorps.Task` record with the `CodeCorps.User` that relates to the `CodeCorps.GithubUser` for the `CodeCorps.GithubIssue` """ - @spec sync_project_github_repo(ProjectGithubRepo.t) :: outcome - def sync_project_github_repo(%ProjectGithubRepo{github_repo: %GithubRepo{} = _} = project_github_repo) do - %ProjectGithubRepo{ - github_repo: %GithubRepo{github_issues: github_issues} - } = project_github_repo |> Repo.preload([:project, github_repo: [github_issues: [github_user: [:user]]]]) + @spec sync_github_repo(GithubRepo.t) :: outcome + def sync_github_repo(%GithubRepo{} = github_repo) do + %GithubRepo{ + github_issues: github_issues + } = github_repo |> Repo.preload([:project, github_issues: [github_user: [:user]]]) github_issues - |> Enum.map(&find_or_create_task(&1, project_github_repo)) + |> Enum.map(&find_or_create_task(&1, github_repo)) |> ResultAggregator.aggregate end defp find_or_create_task( %GithubIssue{github_user: %GithubUser{user: %User{} = user}} = github_issue, - %ProjectGithubRepo{} = project_github_repo) do + %GithubRepo{} = github_repo) do - sync(github_issue, project_github_repo, user) + sync(github_issue, github_repo, user) end - @spec sync(GithubIssue.t, ProjectGithubRepo.t, User.t) :: {:ok, ProjectGithubRepo.t} | {:error, Changeset.t} - defp sync(%GithubIssue{} = github_issue, %ProjectGithubRepo{} = project_github_repo, %User{} = user) do - project_github_repo + @spec sync(GithubIssue.t, GithubRepo.t, User.t) :: {:ok, GithubRepo.t} | {:error, Changeset.t} + defp sync(%GithubIssue{} = github_issue, %GithubRepo{} = github_repo, %User{} = user) do + github_repo |> find_or_init_task(github_issue) - |> TaskChangeset.build_changeset(github_issue, project_github_repo, user) + |> Sync.Issue.Task.Changeset.build_changeset(github_issue, github_repo, user) |> Repo.insert_or_update() end - @spec find_or_init_task(ProjectGithubRepo.t, GithubIssue.t) :: Task.t + @spec find_or_init_task(GithubRepo.t, GithubIssue.t) :: Task.t defp find_or_init_task( - %ProjectGithubRepo{project_id: project_id}, + %GithubRepo{project_id: project_id}, %GithubIssue{id: github_issue_id} ) do case Task |> Repo.get_by(github_issue_id: github_issue_id, project_id: project_id) do diff --git a/lib/code_corps/github/sync/pull_request/pull_request.ex b/lib/code_corps/github/sync/pull_request/pull_request.ex index 420ee426a..7984944d8 100644 --- a/lib/code_corps/github/sync/pull_request/pull_request.ex +++ b/lib/code_corps/github/sync/pull_request/pull_request.ex @@ -13,8 +13,8 @@ defmodule CodeCorps.GitHub.Sync.PullRequest do `CodeCorps.GitHub.Sync.Utils.RepoFinder` - match with `CodeCorps.User` using `CodeCorps.GitHub.Event.PullRequest.UserLinker` - - for each `CodeCorps.ProjectGithubRepo` belonging to matched repo: - - create or update `CodeCorps.Task` for the `CodeCorps.Project` + - create or update each `CodeCorps.Task` for the `CodeCorps.Project` matching + the `CodeCorps.GithubRepo` If the sync succeeds, it will return an `:ok` tuple with a list of created or updated tasks. diff --git a/lib/code_corps/github/sync/sync.ex b/lib/code_corps/github/sync/sync.ex index 017f6cb8e..a606bb3d1 100644 --- a/lib/code_corps/github/sync/sync.ex +++ b/lib/code_corps/github/sync/sync.ex @@ -12,7 +12,6 @@ defmodule CodeCorps.GitHub.Sync do GithubRepo, GitHub.Sync, GitHub.Sync.Utils.RepoFinder, - ProjectGithubRepo, Repo } @@ -134,14 +133,6 @@ defmodule CodeCorps.GitHub.Sync do |> Repo.update end - @spec mark_project_repo(ProjectGithubRepo.t, String.t, Keyword.t) :: {:ok, GithubRepo.t} | {:error, Changeset.t} - defp mark_project_repo(%ProjectGithubRepo{} = project_github_repo, sync_state, opts \\ []) do - params = build_sync_params(sync_state, opts) - project_github_repo - |> ProjectGithubRepo.update_sync_changeset(params) - |> Repo.update - end - @count_fields [ :syncing_comments_count, :syncing_issues_count, @@ -181,9 +172,15 @@ defmodule CodeCorps.GitHub.Sync do - Fetches the comments from the API - Creates or updates `GithubComment` records (and their related `GithubUser` records) + - Creates or updates `User` records for the `GithubUser` records + - Creates or updates `Task` records, and relates them to any related + `GithubIssue` and `User` records created previously + - Creates or updates `Comment` records, and relates them to any related + `GithubComment` and `User` records created previously """ @spec sync_repo(GithubRepo.t) :: {:ok, GithubRepo.t} def sync_repo(%GithubRepo{} = repo) do + repo = preload_github_repo(repo) with {:ok, repo} <- repo |> mark_repo("fetching_pull_requests"), {:ok, pr_payloads} <- repo |> GitHub.API.Repository.pulls |> sync_step(:fetch_pull_requests), {:ok, repo} <- repo |> mark_repo("syncing_github_pull_requests", [syncing_pull_requests_count: pr_payloads |> Enum.count]), @@ -196,7 +193,14 @@ defmodule CodeCorps.GitHub.Sync do {:ok, comment_payloads} <- repo |> GitHub.API.Repository.issue_comments |> sync_step(:fetch_comments), {:ok, repo} <- repo |> mark_repo("syncing_github_comments", [syncing_comments_count: comment_payloads |> Enum.count]), {:ok, _comments} <- comment_payloads |> Enum.map(&Sync.Comment.GithubComment.create_or_update_comment(repo, &1)) |> ResultAggregator.aggregate |> sync_step(:sync_comments), - {:ok, repo} <- repo |> mark_repo("receiving_webhooks") + repo <- Repo.get(GithubRepo, repo.id) |> preload_github_repo(), + {:ok, repo} <- repo |> mark_repo("syncing_users"), + {:ok, _users} <- repo |> Sync.User.User.sync_github_repo() |> sync_step(:sync_users), + {:ok, repo} <- repo |> mark_repo("syncing_tasks"), + {:ok, _tasks} <- repo |> Sync.Issue.Task.sync_github_repo() |> sync_step(:sync_tasks), + {:ok, repo} <- repo |> mark_repo("syncing_comments"), + {:ok, _comments} <- repo |> Sync.Comment.Comment.sync_github_repo() |> sync_step(:sync_comments), + {:ok, repo} <- repo |> mark_repo("synced") do {:ok, repo} else @@ -206,51 +210,20 @@ defmodule CodeCorps.GitHub.Sync do {:error, :sync_issues} -> repo |> mark_repo("errored_syncing_issues") {:error, :fetch_comments} -> repo |> mark_repo("errored_fetching_comments") {:error, :sync_comments} -> repo |> mark_repo("errored_syncing_comments") + {:error, :sync_users} -> repo |> mark_repo("errored_syncing_users") + {:error, :sync_tasks} -> repo |> mark_repo("errored_syncing_tasks") + {:error, :sync_comments} -> repo |> mark_repo("errored_syncing_comments") end end - @doc ~S""" - Syncs a `ProjectGithubRepo` with Code Corps. - - Fetches and syncs records from the GitHub API for a given project's GitHub - repository, marking progress of the sync state along the way. - - - Finds the `GithubRepo` and syncs it with Github using `sync_repo/1` - - Creates or updates `User` records for the `GithubUser` records - - Creates or updates `Task` records, and relates them to any related - `GithubIssue` and `User` records created previously - - Creates or updates `Comment` records, and relates them to any related - `GithubComment` and `User` records created previously - """ - @spec sync_project_github_repo(ProjectGithubRepo.t) :: {:ok, ProjectGithubRepo.t} - def sync_project_github_repo(%ProjectGithubRepo{} = project_github_repo) do - %ProjectGithubRepo{github_repo: %GithubRepo{} = repo} = project_github_repo = - project_github_repo - |> preload_project_github_repo - - with {:ok, project_github_repo} <- project_github_repo |> mark_project_repo("syncing_github_repo"), - {:ok, %GithubRepo{sync_state: "receiving_webhooks"}} <- repo |> sync_repo(), - project_github_repo <- Repo.get(ProjectGithubRepo, project_github_repo.id) |> preload_project_github_repo(), - {:ok, project_github_repo} <- project_github_repo |> mark_project_repo("syncing_users"), - {:ok, _users} <- project_github_repo |> Sync.User.User.sync_project_github_repo() |> sync_step(:sync_users), - {:ok, project_github_repo} <- project_github_repo |> mark_project_repo("syncing_tasks"), - {:ok, _tasks} <- project_github_repo |> Sync.Issue.Task.sync_project_github_repo() |> sync_step(:sync_tasks), - {:ok, project_github_repo} <- project_github_repo |> mark_project_repo("syncing_comments"), - {:ok, _comments} <- project_github_repo |> Sync.Comment.Comment.sync_project_github_repo() |> sync_step(:sync_comments), - {:ok, project_github_repo} <- project_github_repo |> mark_project_repo("synced") - do - {:ok, project_github_repo} - else - {:ok, %GithubRepo{}} -> project_github_repo |> mark_project_repo("errored_syncing_github_repo") - {:error, :sync_users} -> repo |> mark_project_repo("errored_syncing_users") - {:error, :sync_tasks} -> repo |> mark_project_repo("errored_syncing_tasks") - {:error, :sync_comments} -> repo |> mark_project_repo("errored_syncing_comments") - end - end - - defp preload_project_github_repo(%ProjectGithubRepo{} = project_github_repo) do - project_github_repo - |> Repo.preload([:project, github_repo: [:github_app_installation, [github_comments: [:github_issue, :github_user], github_issues: [:github_comments, :github_user]]]]) + defp preload_github_repo(%GithubRepo{} = github_repo) do + github_repo + |> Repo.preload([ + :github_app_installation, + :project, + github_comments: [:github_issue, :github_user], + github_issues: [:github_comments, :github_user] + ]) end @spec marshall_result(tuple) :: tuple diff --git a/lib/code_corps/github/sync/user/user.ex b/lib/code_corps/github/sync/user/user.ex index 5cca9bc01..0e4a068c2 100644 --- a/lib/code_corps/github/sync/user/user.ex +++ b/lib/code_corps/github/sync/user/user.ex @@ -12,18 +12,15 @@ defmodule CodeCorps.GitHub.Sync.User.User do GithubRepo, GithubUser, GitHub.Utils.ResultAggregator, - ProjectGithubRepo, Repo, User } - def sync_project_github_repo(%ProjectGithubRepo{github_repo: %GithubRepo{} = _} = project_github_repo) do - %ProjectGithubRepo{ - github_repo: %GithubRepo{ - github_comments: github_comments, - github_issues: github_issues - } - } = project_github_repo + def sync_github_repo(%GithubRepo{} = github_repo) do + %GithubRepo{ + github_comments: github_comments, + github_issues: github_issues + } = github_repo comment_users = find_users_for_comments(github_comments) issue_users = find_users_for_issues(github_issues) diff --git a/lib/code_corps/github/sync/utils/repo_finder.ex b/lib/code_corps/github/sync/utils/repo_finder.ex index f955cecb3..15ac942f3 100644 --- a/lib/code_corps/github/sync/utils/repo_finder.ex +++ b/lib/code_corps/github/sync/utils/repo_finder.ex @@ -10,8 +10,6 @@ defmodule CodeCorps.GitHub.Sync.Utils.RepoFinder do Returns - `{:ok, GithubRepo.t}` if record was found - `{:error, :unmatched_repository}` if record was not found - - `{:error, :unmatched_project}` if record was found, but has no associated - `ProjectGithubRepo` children """ @spec find_repo(map) :: {:ok, GithubRepo.t} | {:error, :unmatched_repository} def find_repo(%{"repository" => %{"id" => github_id}}) do diff --git a/lib/code_corps/model/github_repo.ex b/lib/code_corps/model/github_repo.ex index e09f56fd4..b06ee26f9 100644 --- a/lib/code_corps/model/github_repo.ex +++ b/lib/code_corps/model/github_repo.ex @@ -1,6 +1,8 @@ defmodule CodeCorps.GithubRepo do use CodeCorps.Model + alias Ecto.Changeset + @type t :: %__MODULE__{} schema "github_repos" do @@ -16,9 +18,9 @@ defmodule CodeCorps.GithubRepo do field :syncing_pull_requests_count, :integer, default: 0 belongs_to :github_app_installation, CodeCorps.GithubAppInstallation + belongs_to :project, CodeCorps.Project has_many :github_comments, CodeCorps.GithubComment has_many :github_issues, CodeCorps.GithubIssue - has_one :project_github_repo, CodeCorps.ProjectGithubRepo timestamps() end @@ -31,7 +33,7 @@ defmodule CodeCorps.GithubRepo do |> cast(params, [ :github_account_id, :github_account_avatar_url, :github_account_login, :github_account_type, :github_app_installation_id, :github_id, :name, - :sync_state, :syncing_comments_count, :syncing_issues_count, + :project_id, :sync_state, :syncing_comments_count, :syncing_issues_count, :syncing_pull_requests_count ]) |> validate_required([ @@ -39,6 +41,15 @@ defmodule CodeCorps.GithubRepo do :github_account_type, :github_id, :name ]) |> assoc_constraint(:github_app_installation) + |> assoc_constraint(:project) + end + + def update_changeset(struct, params \\ {}) do + struct + |> cast(params, [:project_id]) + |> assoc_constraint(:project) + |> maybe_reset_sync_state() + |> validate_inclusion(:sync_state, sync_states()) end def update_sync_changeset(struct, params) do @@ -56,7 +67,17 @@ defmodule CodeCorps.GithubRepo do syncing_github_issues errored_syncing_github_issues fetching_comments errored_fetching_comments syncing_github_comments errored_syncing_github_comments - receiving_webhooks + syncing_users errored_syncing_users + syncing_tasks errored_syncing_tasks + syncing_comments errored_syncing_comments + synced } end + + defp maybe_reset_sync_state(changeset) do + case changeset |> Changeset.get_field(:project_id) do + nil -> changeset |> Changeset.put_change(:sync_state, "unsynced") + _ -> changeset + end + end end diff --git a/lib/code_corps/model/project.ex b/lib/code_corps/model/project.ex index 881ceab05..fbe846eba 100644 --- a/lib/code_corps/model/project.ex +++ b/lib/code_corps/model/project.ex @@ -37,15 +37,14 @@ defmodule CodeCorps.Project do has_one :stripe_connect_plan, CodeCorps.StripeConnectPlan has_many :donation_goals, CodeCorps.DonationGoal + has_many :github_repos, CodeCorps.GithubRepo has_many :project_categories, CodeCorps.ProjectCategory - has_many :project_github_repos, CodeCorps.ProjectGithubRepo has_many :project_skills, CodeCorps.ProjectSkill has_many :project_users, CodeCorps.ProjectUser has_many :task_lists, CodeCorps.TaskList has_many :tasks, CodeCorps.Task has_many :categories, through: [:project_categories, :category] - has_many :github_repos, through: [:project_github_repos, :github_repo] has_many :skills, through: [:project_skills, :skill] has_many :stripe_connect_subscriptions, through: [:stripe_connect_plan, :stripe_connect_subscriptions] diff --git a/lib/code_corps/model/project_github_repo.ex b/lib/code_corps/model/project_github_repo.ex deleted file mode 100644 index c68bdb55b..000000000 --- a/lib/code_corps/model/project_github_repo.ex +++ /dev/null @@ -1,52 +0,0 @@ -defmodule CodeCorps.ProjectGithubRepo do - @moduledoc """ - Represents a link between a Project and a GithubRepo. - """ - - use CodeCorps.Model - - @type t :: %__MODULE__{} - - schema "project_github_repos" do - field :sync_state, :string, default: "unsynced" - - belongs_to :github_repo, CodeCorps.GithubRepo - belongs_to :project, CodeCorps.Project - - timestamps() - end - - @doc """ - Builds a changeset based on the `struct` and `params`. - """ - def create_changeset(struct, params) do - struct - |> changeset(params) - |> assoc_constraint(:github_repo) - |> assoc_constraint(:project) - |> unique_constraint(:github_repo, name: :project_github_repos_github_repo_id_index) - end - - defp changeset(struct, params) do - struct - |> cast(params, [:github_repo_id, :project_id, :sync_state]) - |> validate_required([:github_repo_id, :project_id]) - end - - def update_sync_changeset(struct, params) do - struct - |> changeset(params) - |> validate_inclusion(:sync_state, sync_states()) - end - - def sync_states do - ~w{ - unsynced - syncing_github_repo errored_syncing_github_repo - syncing_users errored_syncing_users - syncing_tasks errored_syncing_tasks - syncing_comments errored_syncing_comments - synced - } - end -end diff --git a/lib/code_corps/policy/github_repo.ex b/lib/code_corps/policy/github_repo.ex new file mode 100644 index 000000000..b75e7a6c4 --- /dev/null +++ b/lib/code_corps/policy/github_repo.ex @@ -0,0 +1,15 @@ +defmodule CodeCorps.Policy.GithubRepo do + @moduledoc """ + Handles `User` authorization of actions on `GithubRepo` records + """ + import CodeCorps.Policy.Helpers, only: [get_project: 1, administered_by?: 2] + + alias CodeCorps.{GithubAppInstallation, GithubRepo, User} + + def update?(%User{} = user, %GithubRepo{project_id: nil}, %{"project_id" => _} = params) do + params |> get_project |> administered_by?(user) + end + def update?(%User{} = user, %GithubRepo{} = github_repo, %{}) do + github_repo |> get_project |> administered_by?(user) + end +end diff --git a/lib/code_corps/policy/helpers.ex b/lib/code_corps/policy/helpers.ex index b0fb4bf2d..198a10fa6 100644 --- a/lib/code_corps/policy/helpers.ex +++ b/lib/code_corps/policy/helpers.ex @@ -60,7 +60,7 @@ defmodule CodeCorps.Policy.Helpers do Returns `CodeCorps.Project` """ @spec get_project(struct | Changeset.t | any) :: Project.t - def get_project(%{"project_id" => id}), do: Project |> Repo.get(id) + def get_project(%{"project_id" => id}), do: Project |> Repo.get(id) def get_project(%{project_id: id}), do: Project |> Repo.get(id) def get_project(%Changeset{changes: %{project_id: id}}), do: Project |> Repo.get(id) def get_project(_), do: nil diff --git a/lib/code_corps/policy/policy.ex b/lib/code_corps/policy/policy.ex index 7ca0b5006..e695c2813 100644 --- a/lib/code_corps/policy/policy.ex +++ b/lib/code_corps/policy/policy.ex @@ -3,7 +3,7 @@ defmodule CodeCorps.Policy do Handles authorization for various API actions performed on objects in the database. """ - alias CodeCorps.{Category, Comment, DonationGoal, GithubAppInstallation, GithubEvent, Organization, OrganizationInvite, OrganizationGithubAppInstallation, Preview, Project, ProjectCategory, ProjectGithubRepo, ProjectSkill, ProjectUser, Role, RoleSkill, Skill, StripeConnectAccount, StripeConnectPlan, StripeConnectSubscription, StripePlatformCard, StripePlatformCustomer, Task, TaskSkill, User, UserCategory, UserRole, UserSkill, UserTask} + alias CodeCorps.{Category, Comment, DonationGoal, GithubAppInstallation, GithubEvent, GithubRepo, Organization, OrganizationInvite, OrganizationGithubAppInstallation, Preview, Project, ProjectCategory, ProjectSkill, ProjectUser, Role, RoleSkill, Skill, StripeConnectAccount, StripeConnectPlan, StripeConnectSubscription, StripePlatformCard, StripePlatformCustomer, Task, TaskSkill, User, UserCategory, UserRole, UserSkill, UserTask} alias CodeCorps.Policy @@ -44,6 +44,9 @@ defmodule CodeCorps.Policy do defp can?(%User{} = current_user, :index, %GithubEvent{}, %{}), do: Policy.GithubEvent.index?(current_user) defp can?(%User{} = current_user, :show, %GithubEvent{}, %{}), do: Policy.GithubEvent.show?(current_user) + # GithubRepo + defp can?(%User{} = current_user, :update, %GithubRepo{} = github_repo, %{} = params), do: Policy.GithubRepo.update?(current_user, github_repo, params) + # Organization defp can?(%User{} = current_user, :create, %Organization{}, %{}), do: Policy.Organization.create?(current_user) defp can?(%User{} = current_user, :update, %Organization{} = organization, %{}), do: Policy.Organization.update?(current_user, organization) @@ -68,11 +71,6 @@ defmodule CodeCorps.Policy do defp can?(%User{} = current_user, :create, %ProjectCategory{}, %{} = params), do: Policy.ProjectCategory.create?(current_user, params) defp can?(%User{} = current_user, :delete, %ProjectCategory{} = project_category, %{}), do: Policy.ProjectCategory.delete?(current_user, project_category) - # ProjectGithubRepo - defp can?(%User{} = current_user, :create, %ProjectGithubRepo{}, %{} = params), do: Policy.ProjectGithubRepo.create?(current_user, params) - defp can?(%User{} = current_user, :delete, %ProjectGithubRepo{} = project_github_repo, %{}), - do: Policy.ProjectGithubRepo.delete?(current_user, project_github_repo) - # ProjectSkill defp can?(%User{} = current_user, :create, %ProjectSkill{}, %{} = params), do: Policy.ProjectSkill.create?(current_user, params) defp can?(%User{} = current_user, :delete, %ProjectSkill{} = project_skill, %{}), do: Policy.ProjectSkill.delete?(current_user, project_skill) diff --git a/lib/code_corps/policy/project_github_repo.ex b/lib/code_corps/policy/project_github_repo.ex deleted file mode 100644 index 37b48a89b..000000000 --- a/lib/code_corps/policy/project_github_repo.ex +++ /dev/null @@ -1,15 +0,0 @@ -defmodule CodeCorps.Policy.ProjectGithubRepo do - import CodeCorps.Policy.Helpers, only: [get_project: 1, administered_by?: 2] - - alias CodeCorps.{ProjectGithubRepo, User} - - @spec create?(User.t, map) :: boolean - def create?(%User{} = user, %{} = params) do - params |> get_project |> administered_by?(user) - end - - @spec delete?(User.t, ProjectGithubRepo.t) :: boolean - def delete?(%User{} = user, %ProjectGithubRepo{} = project_github_repo) do - project_github_repo |> get_project |> administered_by?(user) - end -end diff --git a/lib/code_corps_web/controllers/github_repo_controller.ex b/lib/code_corps_web/controllers/github_repo_controller.ex index 3a3157c54..8781484e3 100644 --- a/lib/code_corps_web/controllers/github_repo_controller.ex +++ b/lib/code_corps_web/controllers/github_repo_controller.ex @@ -2,7 +2,13 @@ defmodule CodeCorpsWeb.GithubRepoController do @moduledoc false use CodeCorpsWeb, :controller - alias CodeCorps.{GithubRepo, Helpers.Query} + alias CodeCorps.{ + Analytics.SegmentTracker, + GithubRepo, + Helpers.Query, + Processor, + User + } action_fallback CodeCorpsWeb.FallbackController plug CodeCorpsWeb.Plug.DataToAttributes @@ -10,23 +16,42 @@ defmodule CodeCorpsWeb.GithubRepoController do @spec index(Conn.t, map) :: Conn.t def index(%Conn{} = conn, %{} = params) do - with github_repos <- GithubRepo |> Query.id_filter(params) |> Repo.all |> preload() do + with github_repos <- GithubRepo |> Query.id_filter(params) |> Repo.all do conn |> render("index.json-api", data: github_repos) end end @spec show(Conn.t, map) :: Conn.t def show(%Conn{} = conn, %{"id" => id}) do - with %GithubRepo{} = github_repo <- GithubRepo |> Repo.get(id) |> preload() do + with %GithubRepo{} = github_repo <- GithubRepo |> Repo.get(id) do conn |> render("show.json-api", data: github_repo) end end - @preloads [ - :project_github_repo - ] + @spec update(Conn.t, map) :: Conn.t + def update(%Conn{} = conn, %{"id" => id} = params) do + with %GithubRepo{} = github_repo <- GithubRepo |> Repo.get(id), + %User{} = current_user <- conn |> Guardian.Plug.current_resource, + {:ok, :authorized} <- current_user |> Policy.authorize(:update, github_repo, params), + {:ok, %GithubRepo{} = github_repo} <- github_repo |> GithubRepo.update_changeset(params) |> Repo.update() + do + github_repo |> postprocess() + current_user |> track(github_repo) + conn |> render("show.json-api", data: github_repo) + end + end - def preload(data) do - Repo.preload(data, @preloads) + @spec postprocess(GithubRepo.t) :: any + defp postprocess(%GithubRepo{project_id: nil}), do: nil + defp postprocess(%GithubRepo{} = github_repo) do + Processor.process(fn -> CodeCorps.GitHub.Sync.sync_repo(github_repo) end) + end + + @spec track(User.t, GithubRepo.t) :: any + defp track(%User{id: user_id}, %GithubRepo{project_id: nil} = github_repo) do + user_id |> SegmentTracker.track("Disconnected GitHub Repo from Project", github_repo) + end + defp track(%User{id: user_id}, %GithubRepo{} = github_repo) do + user_id |> SegmentTracker.track("Connected GitHub Repo to Project", github_repo) end end diff --git a/lib/code_corps_web/controllers/project_controller.ex b/lib/code_corps_web/controllers/project_controller.ex index a506effe9..8cb11f703 100644 --- a/lib/code_corps_web/controllers/project_controller.ex +++ b/lib/code_corps_web/controllers/project_controller.ex @@ -45,9 +45,9 @@ defmodule CodeCorpsWeb.ProjectController do end @preloads [ - :donation_goals, [organization: :stripe_connect_account], - :project_categories, :project_github_repos, :project_skills, - :project_users, :stripe_connect_plan, :task_lists, :tasks + :donation_goals, :github_repos, [organization: :stripe_connect_account], + :project_categories, :project_skills, :project_users, :stripe_connect_plan, + :task_lists, :tasks ] def preload(data) do diff --git a/lib/code_corps_web/controllers/project_github_repo_controller.ex b/lib/code_corps_web/controllers/project_github_repo_controller.ex deleted file mode 100644 index a197c8c0b..000000000 --- a/lib/code_corps_web/controllers/project_github_repo_controller.ex +++ /dev/null @@ -1,69 +0,0 @@ -defmodule CodeCorpsWeb.ProjectGithubRepoController do - @moduledoc false - use CodeCorpsWeb, :controller - - alias CodeCorps.{Analytics.SegmentTracker, Processor, ProjectGithubRepo, User, Helpers.Query} - - action_fallback CodeCorpsWeb.FallbackController - plug CodeCorpsWeb.Plug.DataToAttributes - plug CodeCorpsWeb.Plug.IdsToIntegers - - @spec index(Conn.t, map) :: Conn.t - def index(%Conn{} = conn, %{} = params) do - with organization_installations <- ProjectGithubRepo |> Query.id_filter(params) |> Repo.all do - conn |> render("index.json-api", data: organization_installations) - end - end - - @spec show(Conn.t, map) :: Conn.t - def show(%Conn{} = conn, %{"id" => id}) do - with %ProjectGithubRepo{} = project_github_repo <- ProjectGithubRepo |> Repo.get(id) do - conn |> render("show.json-api", data: project_github_repo) - end - end - - @spec create(Plug.Conn.t, map) :: Conn.t - def create(%Conn{} = conn, %{} = params) do - with %User{} = current_user <- conn |> Guardian.Plug.current_resource, - {:ok, :authorized} <- current_user |> Policy.authorize(:create, %ProjectGithubRepo{}, params), - {:ok, %ProjectGithubRepo{} = project_github_repo} <- create_project_repo_changeset(params) |> Repo.insert do - - Processor.process(fn -> - CodeCorps.GitHub.Sync.sync_project_github_repo(project_github_repo) - end) - - current_user |> track_created(project_github_repo) - - conn |> put_status(:created) |> render("show.json-api", data: project_github_repo) - end - end - - @spec delete(Plug.Conn.t, map) :: Conn.t - def delete(%Conn{} = conn, %{"id" => id} = params) do - with %ProjectGithubRepo{} = project_github_repo <- ProjectGithubRepo |> Repo.get(id), - %User{} = current_user <- conn |> Guardian.Plug.current_resource, - {:ok, :authorized} <- current_user |> Policy.authorize(:delete, project_github_repo, params), - {:ok, project_github_repo} <- project_github_repo |> Repo.delete do - - current_user |> track_deleted(project_github_repo) - - conn |> send_resp(:no_content, "") - end - end - - @spec create_project_repo_changeset(map) :: Ecto.Changeset.t - defp create_project_repo_changeset(params) do - %ProjectGithubRepo{} - |> ProjectGithubRepo.create_changeset(params) - end - - @spec track_created(User.t, ProjectGithubRepo.t) :: any - defp track_created(%User{id: user_id}, %ProjectGithubRepo{} = project_github_repo) do - user_id |> SegmentTracker.track("Connected GitHub Repo to Project", project_github_repo) - end - - @spec track_deleted(User.t, ProjectGithubRepo.t) :: any - defp track_deleted(%User{id: user_id}, %ProjectGithubRepo{} = project_github_repo) do - user_id |> SegmentTracker.track("Disconnected GitHub Repo from Project", project_github_repo) - end -end diff --git a/lib/code_corps_web/plugs/ids_to_integers.ex b/lib/code_corps_web/plugs/ids_to_integers.ex index 9b78eaf56..f6df5d0fe 100644 --- a/lib/code_corps_web/plugs/ids_to_integers.ex +++ b/lib/code_corps_web/plugs/ids_to_integers.ex @@ -39,14 +39,13 @@ defmodule CodeCorpsWeb.Plug.IdsToIntegers do defp convert?("comment_id"), do: true defp convert?("donation_goal_id"), do: true defp convert?("github_app_installation_id"), do: true - defp convert?("github_repo_id_id"), do: true + defp convert?("github_repo_id"), do: true defp convert?("organization_github_app_installation_id"), do: true defp convert?("organization_invite_id"), do: true defp convert?("organization_id"), do: true defp convert?("preview_id"), do: true defp convert?("project_id"), do: true defp convert?("project_category_id"), do: true - defp convert?("project_github_repo_id"), do: true defp convert?("project_skill_id"), do: true defp convert?("project_user_id"), do: true defp convert?("role_id"), do: true diff --git a/lib/code_corps_web/router.ex b/lib/code_corps_web/router.ex index 89b2017f1..c1678ff3d 100644 --- a/lib/code_corps_web/router.ex +++ b/lib/code_corps_web/router.ex @@ -71,12 +71,12 @@ defmodule CodeCorpsWeb.Router do post "/oauth/github", UserController, :github_oauth resources "/github-app-installations", GithubAppInstallationController, only: [:create] resources "/github-events", GithubEventController, only: [:index, :show] + resources "/github-repos", GithubRepoController, only: [:update] resources "/organization-github-app-installations", OrganizationGithubAppInstallationController, only: [:create, :delete] resources "/organizations", OrganizationController, only: [:create, :update] resources "/organization-invites", OrganizationInviteController, only: [:create, :update] resources "/previews", PreviewController, only: [:create] resources "/project-categories", ProjectCategoryController, only: [:create, :delete] - resources "/project-github-repos", ProjectGithubRepoController, only: [:create, :delete] resources "/project-skills", ProjectSkillController, only: [:create, :delete] resources "/project-users", ProjectUserController, only: [:create, :update, :delete] resources "/projects", ProjectController, only: [:create, :update] @@ -116,7 +116,6 @@ defmodule CodeCorpsWeb.Router do resources "/organization-invites", OrganizationInviteController, only: [:index, :show] post "/password/forgot", PasswordController, :forgot_password resources "/project-categories", ProjectCategoryController, only: [:index, :show] - resources "/project-github-repos", ProjectGithubRepoController, only: [:index, :show] resources "/project-skills", ProjectSkillController, only: [:index, :show] resources "/project-users", ProjectUserController, only: [:index, :show] resources "/projects", ProjectController, only: [:index, :show] do diff --git a/lib/code_corps_web/views/github_repo_view.ex b/lib/code_corps_web/views/github_repo_view.ex index 26ae00e31..bdee6dbba 100644 --- a/lib/code_corps_web/views/github_repo_view.ex +++ b/lib/code_corps_web/views/github_repo_view.ex @@ -9,5 +9,5 @@ defmodule CodeCorpsWeb.GithubRepoView do :syncing_pull_requests_count, :sync_state, :updated_at] has_one :github_app_installation, type: "github-app-installation", field: :github_app_installation_id - has_one :project_github_repo, serializer: CodeCorpsWeb.ProjectGithubRepoView + has_one :project, type: "project", field: :project_id end diff --git a/lib/code_corps_web/views/project_github_repo_view.ex b/lib/code_corps_web/views/project_github_repo_view.ex deleted file mode 100644 index e0a5618de..000000000 --- a/lib/code_corps_web/views/project_github_repo_view.ex +++ /dev/null @@ -1,10 +0,0 @@ -defmodule CodeCorpsWeb.ProjectGithubRepoView do - @moduledoc false - use CodeCorpsWeb, :view - use JaSerializer.PhoenixView - - attributes [:sync_state] - - has_one :github_repo, type: "github-repo", field: :github_repo_id - has_one :project, type: "project", field: :project_id -end diff --git a/lib/code_corps_web/views/project_view.ex b/lib/code_corps_web/views/project_view.ex index 6ce94d29b..0509c47c5 100644 --- a/lib/code_corps_web/views/project_view.ex +++ b/lib/code_corps_web/views/project_view.ex @@ -18,8 +18,8 @@ defmodule CodeCorpsWeb.ProjectView do has_one :stripe_connect_plan, serializer: CodeCorpsWeb.StripeConnectPlanView has_many :donation_goals, serializer: CodeCorpsWeb.DonationGoalView, identifiers: :always + has_many :github_repos, serializer: CodeCorpsWeb.GithubRepoView, identifiers: :always has_many :project_categories, serializer: CodeCorpsWeb.ProjectCategoryView, identifiers: :always - has_many :project_github_repos, serializer: CodeCorpsWeb.ProjectGithubRepoView, identifiers: :always has_many :project_skills, serializer: CodeCorpsWeb.ProjectSkillView, identifiers: :always has_many :project_users, serializer: CodeCorpsWeb.ProjectUserView, identifiers: :always has_many :tasks, serializer: CodeCorpsWeb.TaskView, identifiers: :always diff --git a/mix.exs b/mix.exs index 395a819f5..9c64f54e3 100644 --- a/mix.exs +++ b/mix.exs @@ -121,7 +121,6 @@ defmodule CodeCorps.Mixfile do CodeCorps.Project, CodeCorps.Project.Query, CodeCorps.ProjectCategory, - CodeCorps.ProjectGithubRepo, CodeCorps.ProjectSkill, CodeCorps.ProjectUser, CodeCorps.Repo, @@ -178,7 +177,6 @@ defmodule CodeCorps.Mixfile do Policy.Preview, Policy.Project, Policy.ProjectCategory, - Policy.ProjectGithubRepo, Policy.ProjectSkill, Policy.ProjectUser, Policy.Role, diff --git a/priv/repo/migrations/20171114225214_add_project_id_to_github_repo.exs b/priv/repo/migrations/20171114225214_add_project_id_to_github_repo.exs new file mode 100644 index 000000000..b602a7673 --- /dev/null +++ b/priv/repo/migrations/20171114225214_add_project_id_to_github_repo.exs @@ -0,0 +1,11 @@ +defmodule CodeCorps.Repo.Migrations.AddProjectIdToGithubRepo do + use Ecto.Migration + + def change do + alter table(:github_repos) do + add :project_id, references(:projects, on_delete: :nothing) + end + + create unique_index(:github_repos, [:project_id]) + end +end diff --git a/priv/repo/migrations/20171114225713_migrate_project_github_repos_to_github_repo.exs b/priv/repo/migrations/20171114225713_migrate_project_github_repos_to_github_repo.exs new file mode 100644 index 000000000..5a23639b7 --- /dev/null +++ b/priv/repo/migrations/20171114225713_migrate_project_github_repos_to_github_repo.exs @@ -0,0 +1,42 @@ +defmodule CodeCorps.Repo.Migrations.MigrateProjectGithubReposToGithubRepo do + use Ecto.Migration + + import Ecto.Query + + alias CodeCorps.Repo + + def up do + project_github_repos = from( + pgr in "project_github_repos", + left_join: + gr in "github_repos", + on: gr.id == pgr.github_repo_id, + select: {pgr.project_id, pgr.sync_state, gr.id, gr.sync_state, pgr.id} + ) |> Repo.all() + + project_github_repos + |> Enum.each(fn {project_id, project_repo_state, repo_id, repo_state, project_repo_id} -> + + sync_state = transform_sync_state(project_repo_state, repo_state) + + from( + gr in "github_repos", + where: [id: ^repo_id], + inner_join: + pgr in "project_github_repos", + on: gr.id == pgr.github_repo_id, + where: pgr.id == ^project_repo_id, + update: [set: [project_id: ^project_id, sync_state: ^sync_state]] + ) |> Repo.update_all([]) + end) + end + + defp transform_sync_state("unsynced", repo_state), do: repo_state + defp transform_sync_state("syncing_github_repo", repo_state), do: repo_state + defp transform_sync_state("errored_syncing_github_repo", repo_state), do: repo_state + defp transform_sync_state(project_repo_state, _repo_state), do: project_repo_state + + def down do + # unsupported + end +end diff --git a/priv/repo/migrations/20171114232534_remove_project_github_repos.exs b/priv/repo/migrations/20171114232534_remove_project_github_repos.exs new file mode 100644 index 000000000..fcd99a140 --- /dev/null +++ b/priv/repo/migrations/20171114232534_remove_project_github_repos.exs @@ -0,0 +1,20 @@ +defmodule CodeCorps.Repo.Migrations.RemoveProjectGithubRepos do + use Ecto.Migration + + def up do + drop table(:project_github_repos) + end + + def down do + create table(:project_github_repos) do + add :project_id, references(:projects, on_delete: :delete_all) + add :github_repo_id, references(:github_repos, on_delete: :delete_all) + add :sync_state, :string, default: "unsynced" + + timestamps() + end + + create unique_index(:project_github_repos, [:project_id, :github_repo_id]) + create index(:project_github_repos, [:sync_state]) + end +end diff --git a/priv/repo/structure.sql b/priv/repo/structure.sql index 28b02202b..3f9aab99d 100644 --- a/priv/repo/structure.sql +++ b/priv/repo/structure.sql @@ -2,8 +2,8 @@ -- PostgreSQL database dump -- --- Dumped from database version 9.5.10 --- Dumped by pg_dump version 10.1 +-- Dumped from database version 10.0 +-- Dumped by pg_dump version 10.0 SET statement_timeout = 0; SET lock_timeout = 0; @@ -433,7 +433,8 @@ CREATE TABLE github_repos ( sync_state character varying(255) DEFAULT 'unsynced'::character varying, syncing_comments_count integer DEFAULT 0, syncing_issues_count integer DEFAULT 0, - syncing_pull_requests_count integer DEFAULT 0 + syncing_pull_requests_count integer DEFAULT 0, + project_id bigint ); @@ -659,39 +660,6 @@ CREATE SEQUENCE project_categories_id_seq ALTER SEQUENCE project_categories_id_seq OWNED BY project_categories.id; --- --- Name: project_github_repos; Type: TABLE; Schema: public; Owner: - --- - -CREATE TABLE project_github_repos ( - id bigint NOT NULL, - project_id bigint, - github_repo_id bigint, - inserted_at timestamp without time zone NOT NULL, - updated_at timestamp without time zone NOT NULL, - sync_state character varying(255) DEFAULT 'unsynced'::character varying -); - - --- --- Name: project_github_repos_id_seq; Type: SEQUENCE; Schema: public; Owner: - --- - -CREATE SEQUENCE project_github_repos_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - --- --- Name: project_github_repos_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - --- - -ALTER SEQUENCE project_github_repos_id_seq OWNED BY project_github_repos.id; - - -- -- Name: project_skills; Type: TABLE; Schema: public; Owner: - -- @@ -1881,13 +1849,6 @@ ALTER TABLE ONLY previews ALTER COLUMN id SET DEFAULT nextval('previews_id_seq': ALTER TABLE ONLY project_categories ALTER COLUMN id SET DEFAULT nextval('project_categories_id_seq'::regclass); --- --- Name: project_github_repos id; Type: DEFAULT; Schema: public; Owner: - --- - -ALTER TABLE ONLY project_github_repos ALTER COLUMN id SET DEFAULT nextval('project_github_repos_id_seq'::regclass); - - -- -- Name: project_skills id; Type: DEFAULT; Schema: public; Owner: - -- @@ -2205,14 +2166,6 @@ ALTER TABLE ONLY project_categories ADD CONSTRAINT project_categories_pkey PRIMARY KEY (id); --- --- Name: project_github_repos project_github_repos_pkey; Type: CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY project_github_repos - ADD CONSTRAINT project_github_repos_pkey PRIMARY KEY (id); - - -- -- Name: project_skills project_skills_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -2564,6 +2517,13 @@ CREATE INDEX github_repos_github_app_installation_id_index ON github_repos USING CREATE UNIQUE INDEX github_repos_github_id_index ON github_repos USING btree (github_id); +-- +-- Name: github_repos_project_id_index; Type: INDEX; Schema: public; Owner: - +-- + +CREATE UNIQUE INDEX github_repos_project_id_index ON github_repos USING btree (project_id); + + -- -- Name: github_repos_sync_state_index; Type: INDEX; Schema: public; Owner: - -- @@ -2690,27 +2650,6 @@ CREATE UNIQUE INDEX project_categories_project_id_category_id_index ON project_c CREATE INDEX project_categories_project_id_index ON project_categories USING btree (project_id); --- --- Name: project_github_repos_github_repo_id_index; Type: INDEX; Schema: public; Owner: - --- - -CREATE UNIQUE INDEX project_github_repos_github_repo_id_index ON project_github_repos USING btree (github_repo_id); - - --- --- Name: project_github_repos_project_id_index; Type: INDEX; Schema: public; Owner: - --- - -CREATE INDEX project_github_repos_project_id_index ON project_github_repos USING btree (project_id); - - --- --- Name: project_github_repos_sync_state_index; Type: INDEX; Schema: public; Owner: - --- - -CREATE INDEX project_github_repos_sync_state_index ON project_github_repos USING btree (sync_state); - - -- -- Name: project_skills_project_id_index; Type: INDEX; Schema: public; Owner: - -- @@ -3448,6 +3387,14 @@ ALTER TABLE ONLY github_repos ADD CONSTRAINT github_repos_github_app_installation_id_fkey FOREIGN KEY (github_app_installation_id) REFERENCES github_app_installations(id); +-- +-- Name: github_repos github_repos_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY github_repos + ADD CONSTRAINT github_repos_project_id_fkey FOREIGN KEY (project_id) REFERENCES projects(id); + + -- -- Name: organization_github_app_installations organization_github_app_installations_github_app_installation_i; Type: FK CONSTRAINT; Schema: public; Owner: - -- @@ -3496,22 +3443,6 @@ ALTER TABLE ONLY project_categories ADD CONSTRAINT project_categories_project_id_fkey FOREIGN KEY (project_id) REFERENCES projects(id); --- --- Name: project_github_repos project_github_repos_github_repo_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY project_github_repos - ADD CONSTRAINT project_github_repos_github_repo_id_fkey FOREIGN KEY (github_repo_id) REFERENCES github_repos(id) ON DELETE CASCADE; - - --- --- Name: project_github_repos project_github_repos_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY project_github_repos - ADD CONSTRAINT project_github_repos_project_id_fkey FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; - - -- -- Name: project_skills project_skills_project_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: - -- @@ -3868,5 +3799,5 @@ ALTER TABLE ONLY users -- PostgreSQL database dump complete -- -INSERT INTO "schema_migrations" (version) VALUES (20160723215749), (20160804000000), (20160804001111), (20160805132301), (20160805203929), (20160808143454), (20160809214736), (20160810124357), (20160815125009), (20160815143002), (20160816020347), (20160816034021), (20160817220118), (20160818000944), (20160818132546), (20160820113856), (20160820164905), (20160822002438), (20160822004056), (20160822011624), (20160822020401), (20160822044612), (20160830081224), (20160830224802), (20160911233738), (20160912002705), (20160912145957), (20160918003206), (20160928232404), (20161003185918), (20161019090945), (20161019110737), (20161020144622), (20161021131026), (20161031001615), (20161121005339), (20161121014050), (20161121043941), (20161121045709), (20161122015942), (20161123081114), (20161123150943), (20161124085742), (20161125200620), (20161126045705), (20161127054559), (20161205024856), (20161207112519), (20161209192504), (20161212005641), (20161214005935), (20161215052051), (20161216051447), (20161218005913), (20161219160401), (20161219163909), (20161220141753), (20161221085759), (20161226213600), (20161231063614), (20170102130055), (20170102181053), (20170104113708), (20170104212623), (20170104235423), (20170106013143), (20170115035159), (20170115230549), (20170121014100), (20170131234029), (20170201014901), (20170201025454), (20170201035458), (20170201183258), (20170220032224), (20170224233516), (20170226050552), (20170228085250), (20170308214128), (20170308220713), (20170308222552), (20170313130611), (20170318032449), (20170318082740), (20170324194827), (20170424215355), (20170501225441), (20170505224222), (20170526095401), (20170602000208), (20170622205732), (20170626231059), (20170628092119), (20170628213609), (20170629183404), (20170630140136), (20170706132431), (20170707213648), (20170711122252), (20170717092127), (20170725060612), (20170727052644), (20170731130121), (20170814131722), (20170913114958), (20170921014405), (20170925214512), (20170925230419), (20170926134646), (20170927100300), (20170928234412), (20171003134956), (20171003225853), (20171006063358), (20171006161407), (20171012215106), (20171012221231), (20171016125229), (20171016125516), (20171016223356), (20171016235656), (20171017235433), (20171019191035), (20171025184225), (20171026010933), (20171027061833), (20171028011642), (20171028173508), (20171030182857), (20171031232023), (20171031234356), (20171101023309), (20171104013543), (20171106045740), (20171106050209), (20171106103153), (20171106200036), (20171109231538), (20171110001134), (20171114010851), (20171114033357); +INSERT INTO "schema_migrations" (version) VALUES (20160723215749), (20160804000000), (20160804001111), (20160805132301), (20160805203929), (20160808143454), (20160809214736), (20160810124357), (20160815125009), (20160815143002), (20160816020347), (20160816034021), (20160817220118), (20160818000944), (20160818132546), (20160820113856), (20160820164905), (20160822002438), (20160822004056), (20160822011624), (20160822020401), (20160822044612), (20160830081224), (20160830224802), (20160911233738), (20160912002705), (20160912145957), (20160918003206), (20160928232404), (20161003185918), (20161019090945), (20161019110737), (20161020144622), (20161021131026), (20161031001615), (20161121005339), (20161121014050), (20161121043941), (20161121045709), (20161122015942), (20161123081114), (20161123150943), (20161124085742), (20161125200620), (20161126045705), (20161127054559), (20161205024856), (20161207112519), (20161209192504), (20161212005641), (20161214005935), (20161215052051), (20161216051447), (20161218005913), (20161219160401), (20161219163909), (20161220141753), (20161221085759), (20161226213600), (20161231063614), (20170102130055), (20170102181053), (20170104113708), (20170104212623), (20170104235423), (20170106013143), (20170115035159), (20170115230549), (20170121014100), (20170131234029), (20170201014901), (20170201025454), (20170201035458), (20170201183258), (20170220032224), (20170224233516), (20170226050552), (20170228085250), (20170308214128), (20170308220713), (20170308222552), (20170313130611), (20170318032449), (20170318082740), (20170324194827), (20170424215355), (20170501225441), (20170505224222), (20170526095401), (20170602000208), (20170622205732), (20170626231059), (20170628092119), (20170628213609), (20170629183404), (20170630140136), (20170706132431), (20170707213648), (20170711122252), (20170717092127), (20170725060612), (20170727052644), (20170731130121), (20170814131722), (20170913114958), (20170921014405), (20170925214512), (20170925230419), (20170926134646), (20170927100300), (20170928234412), (20171003134956), (20171003225853), (20171006063358), (20171006161407), (20171012215106), (20171012221231), (20171016125229), (20171016125516), (20171016223356), (20171016235656), (20171017235433), (20171019191035), (20171025184225), (20171026010933), (20171027061833), (20171028011642), (20171028173508), (20171030182857), (20171031232023), (20171031234356), (20171101023309), (20171104013543), (20171106045740), (20171106050209), (20171106103153), (20171106200036), (20171109231538), (20171110001134), (20171114010851), (20171114033357), (20171114225214), (20171114225713), (20171114232534); diff --git a/test/lib/code_corps/analytics/segment_traits_builder_test.exs b/test/lib/code_corps/analytics/segment_traits_builder_test.exs index bcbe58d4e..e4422bb46 100644 --- a/test/lib/code_corps/analytics/segment_traits_builder_test.exs +++ b/test/lib/code_corps/analytics/segment_traits_builder_test.exs @@ -17,10 +17,10 @@ defmodule CodeCorps.Analytics.SegmentTraitsBuilderTest do assert :donation_goal |> insert |> SegmentTraitsBuilder.build assert :github_app_installation |> insert |> SegmentTraitsBuilder.build + assert :github_repo |> insert |> SegmentTraitsBuilder.build assert :project_skill |> insert |> SegmentTraitsBuilder.build assert :project_user |> insert |> SegmentTraitsBuilder.build - assert :project_github_repo |> insert |> SegmentTraitsBuilder.build assert :stripe_connect_account |> insert |> SegmentTraitsBuilder.build assert :stripe_connect_charge |> insert |> SegmentTraitsBuilder.build diff --git a/test/lib/code_corps/github/event/installation_repositories/installation_repositories_test.exs b/test/lib/code_corps/github/event/installation_repositories/installation_repositories_test.exs index 2c13818ea..1cf45a5e0 100644 --- a/test/lib/code_corps/github/event/installation_repositories/installation_repositories_test.exs +++ b/test/lib/code_corps/github/event/installation_repositories/installation_repositories_test.exs @@ -8,7 +8,6 @@ defmodule CodeCorps.GitHub.Event.InstallationRepositoriesTest do alias CodeCorps.{ GithubRepo, GitHub.Event.InstallationRepositories, - ProjectGithubRepo, Repo } @@ -113,21 +112,19 @@ defmodule CodeCorps.GitHub.Event.InstallationRepositoriesTest do describe "handle/1 for InstallationRepositories::removed" do @payload load_event_fixture("installation_repositories_removed") - test "deletes github repos and associated project github repos" do + test "deletes github repos" do %{ "installation" => %{"id" => installation_github_id}, "repositories_removed" => [repo_1_payload, repo_2_payload] } = @payload %{project: project} = installation = insert(:github_app_installation, github_id: installation_github_id) - github_repo_1 = insert(:github_repo, github_app_installation: installation, github_id: repo_1_payload["id"]) - insert(:project_github_repo, project: project, github_repo: github_repo_1) + insert(:github_repo, github_app_installation: installation, github_id: repo_1_payload["id"], project: project) insert(:github_repo, github_app_installation: installation, github_id: repo_2_payload["id"]) {:ok, [%GithubRepo{}, %GithubRepo{}]} = InstallationRepositories.handle(@payload) assert Repo.aggregate(GithubRepo, :count, :id) == 0 - assert Repo.aggregate(ProjectGithubRepo, :count, :id) == 0 end test "skips deleting if nothing to delete" do @@ -137,13 +134,11 @@ defmodule CodeCorps.GitHub.Event.InstallationRepositoriesTest do } = @payload %{project: project} = installation = insert(:github_app_installation, github_id: installation_github_id) - github_repo_1 = insert(:github_repo, github_app_installation: installation, github_id: repo_1_payload["id"]) - insert(:project_github_repo, project: project, github_repo: github_repo_1) + insert(:github_repo, github_app_installation: installation, github_id: repo_1_payload["id"], project: project) {:ok, [%GithubRepo{}]} = InstallationRepositories.handle(@payload) assert Repo.aggregate(GithubRepo, :count, :id) == 0 - assert Repo.aggregate(ProjectGithubRepo, :count, :id) == 0 end test "marks event as errored if invalid instalation payload" do diff --git a/test/lib/code_corps/github/event/issue_comment/issue_comment_test.exs b/test/lib/code_corps/github/event/issue_comment/issue_comment_test.exs index 3b693969b..a6d46917d 100644 --- a/test/lib/code_corps/github/event/issue_comment/issue_comment_test.exs +++ b/test/lib/code_corps/github/event/issue_comment/issue_comment_test.exs @@ -22,8 +22,8 @@ defmodule CodeCorps.GitHub.Event.IssueCommentTest do test "creates or updates associated records" do %{"repository" => %{"id" => repo_github_id}} = @payload - github_repo = insert(:github_repo, github_id: repo_github_id) - %{project: project} = insert(:project_github_repo, github_repo: github_repo) + project = insert(:project) + insert(:github_repo, github_id: repo_github_id, project: project) insert(:task_list, project: project, inbox: true) {:ok, %Comment{}} = IssueComment.handle(@payload) diff --git a/test/lib/code_corps/github/event/issues/issues_test.exs b/test/lib/code_corps/github/event/issues/issues_test.exs index 028a48be6..e943bc55f 100644 --- a/test/lib/code_corps/github/event/issues/issues_test.exs +++ b/test/lib/code_corps/github/event/issues/issues_test.exs @@ -22,8 +22,8 @@ defmodule CodeCorps.GitHub.Event.IssuesTest do test "creates or updates associated records" do %{"repository" => %{"id" => repo_github_id}} = @payload - github_repo = insert(:github_repo, github_id: repo_github_id) - %{project: project} = insert(:project_github_repo, github_repo: github_repo) + project = insert(:project) + insert(:github_repo, github_id: repo_github_id, project: project) insert(:task_list, project: project, done: true) insert(:task_list, project: project, inbox: true) insert(:task_list, project: project, pull_requests: true) diff --git a/test/lib/code_corps/github/event/pull_request/pull_request_test.exs b/test/lib/code_corps/github/event/pull_request/pull_request_test.exs index 98f47103c..7631e1899 100644 --- a/test/lib/code_corps/github/event/pull_request/pull_request_test.exs +++ b/test/lib/code_corps/github/event/pull_request/pull_request_test.exs @@ -23,8 +23,8 @@ defmodule CodeCorps.GitHub.Event.PullRequestTest do test "creates or updates associated records" do %{"repository" => %{"id" => repo_github_id}} = @payload - github_repo = insert(:github_repo, github_id: repo_github_id) - %{project: project} = insert(:project_github_repo, github_repo: github_repo) + project = insert(:project) + github_repo = insert(:github_repo, github_id: repo_github_id, project: project) insert(:task_list, project: project, pull_requests: true) {:ok, %{github_pull_request: github_pull_request}} = PullRequest.handle(@payload) diff --git a/test/lib/code_corps/github/sync/comment/comment/comment_test.exs b/test/lib/code_corps/github/sync/comment/comment/comment_test.exs index 087d97cb6..1d52e9f88 100644 --- a/test/lib/code_corps/github/sync/comment/comment/comment_test.exs +++ b/test/lib/code_corps/github/sync/comment/comment/comment_test.exs @@ -8,13 +8,11 @@ defmodule CodeCorps.GitHub.Sync.Comment.CommentTest do describe "sync/4" do test "creates missing comments for each project associated with the github repo" do user = insert(:user) - github_repo = insert(:github_repo) + project = insert(:project) + github_repo = insert(:github_repo, project: project) github_issue = insert(:github_issue, github_repo: github_repo) github_comment = insert(:github_comment, github_issue: github_issue) - project = insert(:project) - insert(:project_github_repo, github_repo: github_repo, project: project) - task = insert(:task, project: project, user: user, github_issue: github_issue, github_repo: github_repo) # update will fail unless source is newer than target @@ -35,13 +33,11 @@ defmodule CodeCorps.GitHub.Sync.Comment.CommentTest do test "updates existing comments for each project associated with the github repo" do user = insert(:user) - github_repo = insert(:github_repo) + project = insert(:project) + github_repo = insert(:github_repo, project: project) github_issue = insert(:github_issue, github_repo: github_repo) github_comment = insert(:github_comment, github_issue: github_issue) - project = insert(:project) - insert(:project_github_repo, github_repo: github_repo, project: project) - task = insert(:task, project: project, user: user, github_issue: github_issue, github_repo: github_repo) existing_comment = insert(:comment, task: task, user: user, github_comment: github_comment) @@ -62,14 +58,12 @@ defmodule CodeCorps.GitHub.Sync.Comment.CommentTest do test "fails on validation errors" do user = insert(:user) - github_repo = insert(:github_repo) + project = insert(:project) + github_repo = insert(:github_repo, project: project) github_issue = insert(:github_issue, github_repo: github_repo) # body will trigger validation error github_comment = insert(:github_comment, github_issue: github_issue, body: nil) - project = insert(:project) - insert(:project_github_repo, github_repo: github_repo, project: project) - task = insert(:task, project: project, user: user, github_issue: github_issue, github_repo: github_repo) # update will fail either way unless source is newer than target diff --git a/test/lib/code_corps/github/sync/issue/issue_test.exs b/test/lib/code_corps/github/sync/issue/issue_test.exs index 5a3e2a5f0..dba4257dc 100644 --- a/test/lib/code_corps/github/sync/issue/issue_test.exs +++ b/test/lib/code_corps/github/sync/issue/issue_test.exs @@ -24,10 +24,8 @@ defmodule CodeCorps.GitHub.Sync.IssueTest do "repository" => %{"id" => repo_github_id} } = @payload - github_repo = insert(:github_repo, github_id: repo_github_id) - project = insert(:project) - insert(:project_github_repo, github_repo: github_repo, project: project) + github_repo = insert(:github_repo, github_id: repo_github_id, project: project) insert(:task_list, project: project, inbox: true) changes = %{repo: github_repo} @@ -59,11 +57,10 @@ defmodule CodeCorps.GitHub.Sync.IssueTest do user = insert(:user, github_id: user_github_id) - github_repo = insert(:github_repo, github_id: repo_github_id) + project = insert(:project) + github_repo = insert(:github_repo, github_id: repo_github_id, project: project) github_issue = insert(:github_issue, github_id: issue_github_id, number: number, github_repo: github_repo) - project = insert(:project) - insert(:project_github_repo, github_repo: github_repo, project: project) insert(:task_list, project: project, inbox: true) existing_task = insert(:task, project: project, user: user, github_repo: github_repo, github_issue: github_issue) @@ -95,11 +92,10 @@ defmodule CodeCorps.GitHub.Sync.IssueTest do user = insert(:user, github_id: user_github_id) - github_repo = insert(:github_repo, github_id: repo_github_id) + project = insert(:project) + github_repo = insert(:github_repo, github_id: repo_github_id, project: project) github_issue = insert(:github_issue, github_id: issue_github_id, number: number, github_repo: github_repo) - project = insert(:project) - insert(:project_github_repo, github_repo: github_repo, project: project) task_list = insert(:task_list, project: project, pull_requests: true) existing_task = insert(:task, project: project, user: user, github_repo: github_repo, github_issue: github_issue) diff --git a/test/lib/code_corps/github/sync/issue/task/changeset_test.exs b/test/lib/code_corps/github/sync/issue/task/changeset_test.exs index 348e2a0c2..838fcc958 100644 --- a/test/lib/code_corps/github/sync/issue/task/changeset_test.exs +++ b/test/lib/code_corps/github/sync/issue/task/changeset_test.exs @@ -16,12 +16,12 @@ defmodule CodeCorps.GitHub.Sync.Issue.Task.ChangesetTest do github_created_at: DateTime.utc_now |> Timex.shift(minutes: 1), github_updated_at: DateTime.utc_now |> Timex.shift(hours: 1)) project = insert(:project) - project_github_repo = insert(:project_github_repo, project: project) + github_repo = insert(:github_repo, project: project) user = insert(:user) task_list = insert(:task_list, project: project, inbox: true) changeset = TaskChangeset.build_changeset( - task, github_issue, project_github_repo, user + task, github_issue, github_repo, user ) # adapted fields @@ -42,8 +42,8 @@ defmodule CodeCorps.GitHub.Sync.Issue.Task.ChangesetTest do # relationships are proper assert get_change(changeset, :github_issue_id) == github_issue.id - assert get_change(changeset, :github_repo_id) == project_github_repo.github_repo_id - assert get_change(changeset, :project_id) == project_github_repo.project_id + assert get_change(changeset, :github_repo_id) == github_repo.id + assert get_change(changeset, :project_id) == github_repo.project_id assert get_change(changeset, :task_list_id) == task_list.id assert get_change(changeset, :user_id) == user.id @@ -57,12 +57,12 @@ defmodule CodeCorps.GitHub.Sync.Issue.Task.ChangesetTest do task = %Task{} github_issue = insert(:github_issue, state: "open") project = insert(:project) - project_github_repo = insert(:project_github_repo, project: project) + github_repo = insert(:github_repo, project: project) user = insert(:user) task_list = insert(:task_list, project: project, inbox: true) changeset = TaskChangeset.build_changeset( - task, github_issue, project_github_repo, user + task, github_issue, github_repo, user ) assert get_change(changeset, :task_list_id) == task_list.id @@ -73,12 +73,12 @@ defmodule CodeCorps.GitHub.Sync.Issue.Task.ChangesetTest do github_pull_request = insert(:github_pull_request) github_issue = insert(:github_issue, github_pull_request: github_pull_request, state: "open") project = insert(:project) - project_github_repo = insert(:project_github_repo, project: project) + github_repo = insert(:github_repo, project: project) user = insert(:user) task_list = insert(:task_list, project: project, pull_requests: true) changeset = TaskChangeset.build_changeset( - task, github_issue, project_github_repo, user + task, github_issue, github_repo, user ) assert get_change(changeset, :task_list_id) == task_list.id @@ -88,12 +88,12 @@ defmodule CodeCorps.GitHub.Sync.Issue.Task.ChangesetTest do task = %Task{} github_issue = insert(:github_issue, state: "closed") project = insert(:project) - project_github_repo = insert(:project_github_repo, project: project) + github_repo = insert(:github_repo, project: project) user = insert(:user) task_list = insert(:task_list, project: project, done: true) changeset = TaskChangeset.build_changeset( - task, github_issue, project_github_repo, user + task, github_issue, github_repo, user ) assert get_change(changeset, :task_list_id) == task_list.id @@ -104,12 +104,12 @@ defmodule CodeCorps.GitHub.Sync.Issue.Task.ChangesetTest do github_pull_request = insert(:github_pull_request) github_issue = insert(:github_issue, github_pull_request: github_pull_request, state: "closed") project = insert(:project) - project_github_repo = insert(:project_github_repo, project: project) + github_repo = insert(:github_repo, project: project) user = insert(:user) task_list = insert(:task_list, project: project, done: true) changeset = TaskChangeset.build_changeset( - task, github_issue, project_github_repo, user + task, github_issue, github_repo, user ) assert get_change(changeset, :task_list_id) == task_list.id @@ -127,12 +127,12 @@ defmodule CodeCorps.GitHub.Sync.Issue.Task.ChangesetTest do github_updated_at: over_a_month_ago) project = insert(:project) - project_github_repo = insert(:project_github_repo, project: project) + github_repo = insert(:github_repo, project: project) user = insert(:user) insert(:task_list, project: project, done: true) changeset = TaskChangeset.build_changeset( - task, github_issue, project_github_repo, user + task, github_issue, github_repo, user ) assert get_field(changeset, :archived) == true @@ -142,14 +142,13 @@ defmodule CodeCorps.GitHub.Sync.Issue.Task.ChangesetTest do test "validates that modified_at has not already happened" do project = insert(:project) github_issue = insert(:github_issue, github_updated_at: DateTime.utc_now |> Timex.shift(minutes: -1), state: "open") - github_repo = insert(:github_repo) - project_github_repo = insert(:project_github_repo, github_repo: github_repo, project: project) + github_repo = insert(:github_repo, project: project) user = insert(:user) task = insert(:task, project: project, github_issue: github_issue, github_repo: github_repo, user: user, modified_at: DateTime.utc_now) insert(:task_list, project: project, inbox: true) changeset = TaskChangeset.build_changeset( - task, github_issue, project_github_repo, user + task, github_issue, github_repo, user ) refute changeset.valid? diff --git a/test/lib/code_corps/github/sync/issue/task/task_test.exs b/test/lib/code_corps/github/sync/issue/task/task_test.exs index 09a5ca6fe..346031ce7 100644 --- a/test/lib/code_corps/github/sync/issue/task/task_test.exs +++ b/test/lib/code_corps/github/sync/issue/task/task_test.exs @@ -12,7 +12,7 @@ defmodule CodeCorps.GitHub.Sync.Issue.TaskTest do # github repo. Returns that data as a map user = insert(:user) project = insert(:project) - github_repo = insert(:github_repo) + github_repo = insert(:github_repo, project: project) github_issue = insert( :github_issue, github_repo: github_repo, @@ -20,7 +20,6 @@ defmodule CodeCorps.GitHub.Sync.Issue.TaskTest do ) insert(:task_list, project: project, inbox: true) - insert(:project_github_repo, project: project, github_repo: github_repo) %{github_issue: github_issue, github_repo: github_repo, project: project, user: user} end @@ -54,10 +53,9 @@ defmodule CodeCorps.GitHub.Sync.Issue.TaskTest do end test "fails on validation errors" do - %{github_repo: github_repo} = github_issue = insert(:github_issue, title: nil) - - %{project: project} = - insert(:project_github_repo, github_repo: github_repo) + project = insert(:project) + github_repo = insert(:github_repo, project: project) + github_issue = insert(:github_issue, title: nil, github_repo: github_repo) %{user: user} = insert(:task, project: project, github_issue: github_issue, github_repo: github_repo) diff --git a/test/lib/code_corps/github/sync/sync_test.exs b/test/lib/code_corps/github/sync/sync_test.exs index 9a99f830e..57bb58db0 100644 --- a/test/lib/code_corps/github/sync/sync_test.exs +++ b/test/lib/code_corps/github/sync/sync_test.exs @@ -44,8 +44,8 @@ defmodule CodeCorps.GitHub.SyncTest do } } = @payload - github_repo = insert(:github_repo, github_id: repo_github_id) - %{project: project} = insert(:project_github_repo, github_repo: github_repo) + project = insert(:project) + github_repo = insert(:github_repo, github_id: repo_github_id, project: project) insert(:task_list, project: project, done: true) insert(:task_list, project: project, inbox: true) insert(:task_list, project: project, pull_requests: true) @@ -91,20 +91,20 @@ defmodule CodeCorps.GitHub.SyncTest do end end - describe "sync_project_github_repo/1" do + describe "sync_repo/1" do test "syncs and resyncs with the project repo" do owner = "baxterthehacker" repo = "public-repo" github_app_installation = insert(:github_app_installation, github_account_login: owner) - github_repo = insert(:github_repo, github_app_installation: github_app_installation, name: repo, github_account_id: 6752317, github_account_avatar_url: "https://avatars3.githubusercontent.com/u/6752317?v=4", github_account_type: "User", github_id: 35129377) - %{project: project} = project_github_repo = insert(:project_github_repo, github_repo: github_repo) + project = insert(:project) + github_repo = insert(:github_repo, github_app_installation: github_app_installation, name: repo, github_account_id: 6752317, github_account_avatar_url: "https://avatars3.githubusercontent.com/u/6752317?v=4", github_account_type: "User", github_id: 35129377, project: project) insert(:task_list, project: project, done: true) insert(:task_list, project: project, inbox: true) insert(:task_list, project: project, pull_requests: true) # Sync a first time - Sync.sync_project_github_repo(project_github_repo) + Sync.sync_repo(github_repo) repo = Repo.one(GithubRepo) @@ -122,7 +122,7 @@ defmodule CodeCorps.GitHub.SyncTest do # Sync a second time – should run without trouble - Sync.sync_project_github_repo(project_github_repo) + Sync.sync_repo(github_repo) repo = Repo.one(GithubRepo) @@ -141,10 +141,10 @@ defmodule CodeCorps.GitHub.SyncTest do @tag acceptance: true test "syncs with the project repo with the real API" do - project_github_repo = setup_coderly_project_repo() + github_repo = setup_coderly_repo() with_real_api do - Sync.sync_project_github_repo(project_github_repo) + Sync.sync_repo(github_repo) end repo = Repo.one(GithubRepo) diff --git a/test/lib/code_corps/github/sync/utils/repo_finder_test.exs b/test/lib/code_corps/github/sync/utils/repo_finder_test.exs index 8b76c6b3e..c7dd7028f 100644 --- a/test/lib/code_corps/github/sync/utils/repo_finder_test.exs +++ b/test/lib/code_corps/github/sync/utils/repo_finder_test.exs @@ -19,7 +19,7 @@ defmodule CodeCorps.GitHub.Sync.Utils.RepoFinderTest do assert RepoFinder.find_repo(payload) == {:error, :unmatched_repository} end - test "returns repository if matched, preloads project github repos", %{payload: payload} do + test "returns repository if matched, preloads github repos", %{payload: payload} do github_repo = insert(:github_repo, github_id: payload["repository"]["id"]) {:ok, %{id: found_repo_id}} = RepoFinder.find_repo(payload) assert found_repo_id == github_repo.id diff --git a/test/lib/code_corps/github/webhook/handler_test.exs b/test/lib/code_corps/github/webhook/handler_test.exs index 16ab3f070..fed2a2410 100644 --- a/test/lib/code_corps/github/webhook/handler_test.exs +++ b/test/lib/code_corps/github/webhook/handler_test.exs @@ -13,8 +13,7 @@ defmodule CodeCorps.GitHub.Webhook.HandlerTest do defp setup_repo(github_repo_id) do project = insert(:project) - github_repo = insert(:github_repo, github_id: github_repo_id) - insert(:project_github_repo, github_repo: github_repo, project: project) + insert(:github_repo, github_id: github_repo_id, project: project) insert(:task_list, project: project, done: true) insert(:task_list, project: project, inbox: true) insert(:task_list, project: project, pull_requests: true) diff --git a/test/lib/code_corps/model/github_repo_test.exs b/test/lib/code_corps/model/github_repo_test.exs index 8232ffdd5..cbbdc54ee 100644 --- a/test/lib/code_corps/model/github_repo_test.exs +++ b/test/lib/code_corps/model/github_repo_test.exs @@ -1,7 +1,7 @@ defmodule CodeCorps.GithubRepoTest do use CodeCorps.ModelCase - alias CodeCorps.{GithubRepo, ProjectGithubRepo} + alias CodeCorps.GithubRepo @valid_attrs %{ github_account_avatar_url: "https://avatars.githubusercontent.com/u/6752317?v=3", @@ -25,6 +25,21 @@ defmodule CodeCorps.GithubRepoTest do end end + describe "update_changeset/2" do + test "when project added" do + attrs = @valid_attrs |> Map.put(:project_id, 1) + changeset = GithubRepo.update_changeset(%GithubRepo{}, attrs) + assert changeset.valid? + end + + test "when project removed" do + attrs = @valid_attrs |> Map.put(:project_id, nil) + changeset = GithubRepo.update_changeset(%GithubRepo{sync_state: "synced"}, attrs) + assert changeset.valid? + assert changeset.changes[:sync_state] == "unsynced" + end + end + describe "update_sync_changeset/2" do test "with valid attributes" do GithubRepo.sync_states |> Enum.each(fn state -> @@ -41,14 +56,4 @@ defmodule CodeCorps.GithubRepoTest do assert changeset.errors[:sync_state] == {"is invalid", [validation: :inclusion]} end end - - test "deletes associated ProjectGithubRepo record when deleting GithubRepo" do - github_repo = insert(:github_repo) - insert(:project_github_repo, github_repo: github_repo) - - github_repo |> Repo.delete - - assert Repo.aggregate(GithubRepo, :count, :id) == 0 - assert Repo.aggregate(ProjectGithubRepo, :count, :id) == 0 - end end diff --git a/test/lib/code_corps/model/project_github_repo_test.exs b/test/lib/code_corps/model/project_github_repo_test.exs deleted file mode 100644 index 77116efa3..000000000 --- a/test/lib/code_corps/model/project_github_repo_test.exs +++ /dev/null @@ -1,103 +0,0 @@ -defmodule CodeCorps.ProjectGithubRepoTest do - use CodeCorps.ModelCase - - alias CodeCorps.ProjectGithubRepo - - describe "create_changeset/2" do - test "with valid attributes" do - project_id = insert(:project).id - github_repo_id = insert(:github_repo).id - - changeset = ProjectGithubRepo.create_changeset(%ProjectGithubRepo{}, %{project_id: project_id, github_repo_id: github_repo_id}) - assert changeset.valid? - end - - test "requires project_id" do - github_repo_id = insert(:github_repo).id - - changeset = ProjectGithubRepo.create_changeset(%ProjectGithubRepo{}, %{github_repo_id: github_repo_id}) - - refute changeset.valid? - assert_error_message(changeset, :project_id, "can't be blank") - end - - - test "requires github_repo_id" do - project_id = insert(:project).id - - changeset = ProjectGithubRepo.create_changeset(%ProjectGithubRepo{}, %{project_id: project_id}) - - refute changeset.valid? - assert_error_message(changeset, :github_repo_id, "can't be blank") - end - - test "requires id of actual project" do - project_id = -1 - github_repo_id = insert(:github_repo).id - - {result, changeset} = - ProjectGithubRepo.create_changeset(%ProjectGithubRepo{}, %{project_id: project_id, github_repo_id: github_repo_id}) - |> Repo.insert - - assert result == :error - refute changeset.valid? - assert_error_message(changeset, :project, "does not exist") - end - - test "ensures uniqueness for github repo" do - project = insert(:project) - github_repo = insert(:github_repo) - insert(:project_github_repo, project: project, github_repo: github_repo) - - {result, changeset} = - ProjectGithubRepo.create_changeset(%ProjectGithubRepo{}, %{project_id: project.id, github_repo_id: github_repo.id}) - |> Repo.insert - - assert result == :error - refute changeset.valid? - assert_error_message(changeset, :github_repo, "has already been taken") - end - - test "requires id of actual github_repo" do - project_id = insert(:project).id - github_repo_id = -1 - - {result, changeset} = - ProjectGithubRepo.create_changeset(%ProjectGithubRepo{}, %{project_id: project_id, github_repo_id: github_repo_id}) - |> Repo.insert - - assert result == :error - refute changeset.valid? - assert_error_message(changeset, :github_repo, "does not exist") - end - end - - describe "update_sync_changeset/2" do - test "with valid attributes" do - project_id = insert(:project).id - github_repo_id = insert(:github_repo).id - attrs = %{project_id: project_id, github_repo_id: github_repo_id} - - ProjectGithubRepo.sync_states |> Enum.each(fn state -> - attrs = - attrs - |> Map.put(:sync_state, state) - - changeset = ProjectGithubRepo.update_sync_changeset(%ProjectGithubRepo{}, attrs) - assert changeset.valid? - end) - end - - test "with invalid attributes" do - project_id = insert(:project).id - github_repo_id = insert(:github_repo).id - attrs = - %{project_id: project_id, github_repo_id: github_repo_id} - |> Map.put(:sync_state, "not_a_valid_sync_state") - - changeset = ProjectGithubRepo.update_sync_changeset(%ProjectGithubRepo{}, attrs) - refute changeset.valid? - assert changeset.errors[:sync_state] == {"is invalid", [validation: :inclusion]} - end - end -end diff --git a/test/lib/code_corps/policy/github_repo_test.exs b/test/lib/code_corps/policy/github_repo_test.exs new file mode 100644 index 000000000..a44a767c2 --- /dev/null +++ b/test/lib/code_corps/policy/github_repo_test.exs @@ -0,0 +1,34 @@ +defmodule CodeCorps.Policy.GithubRepoTest do + use CodeCorps.PolicyCase + + import CodeCorps.Policy.GithubRepo, only: [update?: 3] + + alias CodeCorps.GithubRepo + + describe "update?/3" do + test "returns true when user is adding project where they're an admin" do + project = insert(:project) + user = insert(:user) + insert(:project_user, project: project, user: user, role: "admin") + github_repo = %GithubRepo{project_id: project.id} + + assert update?(user, github_repo, %{}) + end + + test "returns true when user is removing project where they're an admin" do + project = insert(:project) + user = insert(:user) + insert(:project_user, project: project, user: user, role: "admin") + + assert update?(user, %GithubRepo{}, %{"project_id" => project.id}) + end + + test "returns false for normal user" do + project = insert(:project) + user = insert(:user) + github_repo = %GithubRepo{project_id: project.id} + + refute update?(user, github_repo, %{}) + end + end +end diff --git a/test/lib/code_corps/policy/project_github_repo_test.exs b/test/lib/code_corps/policy/project_github_repo_test.exs deleted file mode 100644 index 76234500f..000000000 --- a/test/lib/code_corps/policy/project_github_repo_test.exs +++ /dev/null @@ -1,81 +0,0 @@ -defmodule CodeCorps.Policy.ProjectGithubRepoTest do - use CodeCorps.PolicyCase - - import CodeCorps.Policy.ProjectGithubRepo, only: [create?: 2, delete?: 2] - - describe "create?" do - test "returns false when user is not a project member" do - user = insert(:user) - project = insert(:project) - - params = %{"project_id" => project.id, "user_id" => user.id} - refute create?(user, params) - end - - test "returns false when user is a pending project member" do - %{project: project, user: user} = insert(:project_user, role: "pending") - - params = %{"project_id" => project.id, "user_id" => user.id} - refute create?(user, params) - end - - test "returns false when user is a project contributor" do - %{project: project, user: user} = insert(:project_user, role: "contributor") - - params = %{"project_id" => project.id, "user_id" => user.id} - refute create?(user, params) - end - - test "returns true when user is a project admin" do - %{project: project, user: user} = insert(:project_user, role: "admin") - - params = %{"project_id" => project.id, "user_id" => user.id} - assert create?(user, params) - end - - test "returns true when user is project owner" do - %{project: project, user: user} = insert(:project_user, role: "owner") - - params = %{"project_id" => project.id, "user_id" => user.id} - assert create?(user, params) - end - end - - describe "delete?" do - test "returns false when user is not a project member" do - user = insert(:user) - project = insert(:project) - - record = insert(:project_github_repo, project: project) - refute delete?(user, record) - end - - test "returns false when user is a pending project member" do - %{project: project, user: user} = insert(:project_user, role: "pending") - - record = insert(:project_github_repo, project: project) - refute delete?(user, record) - end - - test "returns false when user is a project contributor" do - %{project: project, user: user} = insert(:project_user, role: "contributor") - - record = insert(:project_github_repo, project: project) - refute delete?(user, record) - end - - test "returns true when user is a project admin" do - %{project: project, user: user} = insert(:project_user, role: "admin") - - record = insert(:project_github_repo, project: project) - assert delete?(user, record) - end - - test "returns true when user is project owner" do - %{project: project, user: user} = insert(:project_user, role: "owner") - - record = insert(:project_github_repo, project: project) - assert delete?(user, record) - end - end -end diff --git a/test/lib/code_corps/task/service_test.exs b/test/lib/code_corps/task/service_test.exs index ab403fd2f..f2b0701bd 100644 --- a/test/lib/code_corps/task/service_test.exs +++ b/test/lib/code_corps/task/service_test.exs @@ -58,7 +58,7 @@ defmodule CodeCorps.Task.ServiceTest do :github_repo |> insert(github_account_login: "foo", name: "bar") - insert(:project_github_repo, project: project, github_repo: github_repo) + insert(:github_repo, project: project) {:ok, task} = attrs @@ -82,7 +82,7 @@ defmodule CodeCorps.Task.ServiceTest do :github_repo |> insert(github_account_login: "foo", name: "bar") - insert(:project_github_repo, project: project, github_repo: github_repo) + insert(:github_repo, project: project) with_mock_api(CodeCorps.GitHub.FailureAPI) do assert {:error, :github} == diff --git a/test/lib/code_corps_web/controllers/github_repo_controller_test.exs b/test/lib/code_corps_web/controllers/github_repo_controller_test.exs index 877a25f02..eba46435e 100644 --- a/test/lib/code_corps_web/controllers/github_repo_controller_test.exs +++ b/test/lib/code_corps_web/controllers/github_repo_controller_test.exs @@ -1,6 +1,8 @@ defmodule CodeCorpsWeb.GithubRepoControllerTest do use CodeCorpsWeb.ApiCase, resource_name: :github_repo + import CodeCorps.GitHub.TestHelpers + describe "index" do test "lists all resources", %{conn: conn} do [record_1, record_2] = insert_pair(:github_repo) @@ -36,4 +38,64 @@ defmodule CodeCorpsWeb.GithubRepoControllerTest do assert conn |> request_show(:not_found) |> json_response(404) end end + + describe "update" do + @tag :authenticated + test "updates repo to add project", %{conn: conn, current_user: user} do + %{project: project} = record = setup_coderly_repo() + insert(:project_user, project: project, user: user, role: "admin") + attrs = %{project: project} + + assert conn |> request_update(record, attrs) |> json_response(200) + + user_id = user.id + tracking_properties = %{ + id: record.id, + github_account_login: record.github_account_login, + github_account_type: record.github_account_type, + github_id: record.github_id, + github_repo_name: record.name, + project: project.title, + project_id: project.id + } + + assert_received {:track, ^user_id, "Connected GitHub Repo to Project", ^tracking_properties} + end + + @tag :authenticated + test "updates repo to remove project", %{conn: conn, current_user: user} do + %{project: project} = record = setup_coderly_repo() + insert(:project_user, project: project, user: user, role: "admin") + attrs = %{project_id: nil} + + assert conn |> request_update(record, attrs) |> json_response(200) + + user_id = user.id + tracking_properties = %{ + id: record.id, + github_account_login: record.github_account_login, + github_account_type: record.github_account_type, + github_id: record.github_id, + github_repo_name: record.name, + project: "", + project_id: nil + } + + assert_received {:track, ^user_id, "Disconnected GitHub Repo from Project", ^tracking_properties} + end + + test "doesn't update and renders 401 when unauthenticated", %{conn: conn} do + assert conn |> request_update |> json_response(401) + end + + @tag :authenticated + test "doesn't update and renders 403 when not authorized", %{conn: conn} do + assert conn |> request_update |> json_response(403) + end + + @tag :authenticated + test "renders 404 when id is nonexistent on update", %{conn: conn} do + assert conn |> request_update(:not_found) |> json_response(404) + end + end end diff --git a/test/lib/code_corps_web/controllers/project_github_repo_controller_test.exs b/test/lib/code_corps_web/controllers/project_github_repo_controller_test.exs deleted file mode 100644 index 30c7f8ccd..000000000 --- a/test/lib/code_corps_web/controllers/project_github_repo_controller_test.exs +++ /dev/null @@ -1,139 +0,0 @@ -defmodule CodeCorpsWeb.ProjectGithubRepoControllerTest do - use CodeCorpsWeb.ApiCase, resource_name: :project_github_repo - - alias CodeCorps.{ - Analytics.SegmentTraitsBuilder, - ProjectGithubRepo, - Repo, - User - } - - describe "index" do - test "lists all entries on index", %{conn: conn} do - [project_github_repo_1, project_github_repo_2] = insert_pair(:project_github_repo) - - conn - |> request_index - |> json_response(200) - |> assert_ids_from_response([project_github_repo_1.id, project_github_repo_2.id]) - end - - test "filters resources on index", %{conn: conn} do - [project_github_repo_1, project_github_repo_2 | _] = insert_list(3, :project_github_repo) - - path = "project-github-repos/?filter[id]=#{project_github_repo_1.id},#{project_github_repo_2.id}" - - conn - |> get(path) - |> json_response(200) - |> assert_ids_from_response([project_github_repo_1.id, project_github_repo_2.id]) - end - end - - describe "show" do - test "shows chosen resource", %{conn: conn} do - github_repo = insert(:github_repo) - project = insert(:project) - project_github_repo = insert(:project_github_repo, project: project, github_repo: github_repo) - - conn - |> request_show(project_github_repo) - |> json_response(200) - |> assert_id_from_response(project_github_repo.id) - end - - test "renders 404 error when id is nonexistent", %{conn: conn} do - assert conn |> request_show(:not_found) |> json_response(404) - end - end - - describe "create" do - @tag :authenticated - test "creates and renders resource when data is valid", %{conn: conn, current_user: current_user} do - {project, github_repo} = setup_project_repo(current_user) - attrs = %{project: project, github_repo: github_repo} - assert conn |> request_create(attrs) |> json_response(201) - end - - @tag :authenticated - test "is being tracked", %{conn: conn, current_user: current_user} do - {project, github_repo} = setup_project_repo(current_user) - attrs = %{project: project, github_repo: github_repo} - conn |> request_create(attrs) - - user_id = current_user.id - traits = ProjectGithubRepo |> Repo.one |> SegmentTraitsBuilder.build - - assert_receive({:track, ^user_id, "Connected GitHub Repo to Project", ^traits}) - end - - @tag :authenticated - test "renders 422 error when data is invalid", %{conn: conn, current_user: current_user} do - project = insert(:project) - insert(:project_user, project: project, user: current_user, role: "owner") - - invalid_attrs = %{project: project} - assert conn |> request_create(invalid_attrs) |> json_response(422) - end - - test "renders 401 when unauthenticated", %{conn: conn} do - assert conn |> request_create |> json_response(401) - end - - @tag :authenticated - test "renders 403 when not authorized", %{conn: conn} do - assert conn |> request_create |> json_response(403) - end - end - - describe "delete" do - @tag :authenticated - test "deletes chosen resource", %{conn: conn, current_user: current_user} do - project = insert(:project) - insert(:project_user, project: project, user: current_user, role: "owner") - project_github_repo = insert(:project_github_repo, project: project) - assert conn |> request_delete(project_github_repo) |> response(204) - end - - @tag :authenticated - test "is being tracked", %{conn: conn, current_user: current_user} do - project = insert(:project) - insert(:project_user, project: project, user: current_user, role: "owner") - project_github_repo = insert(:project_github_repo, project: project) - - conn |> request_delete(project_github_repo) - - user_id = current_user.id - traits = project_github_repo |> SegmentTraitsBuilder.build - - assert_receive({:track, ^user_id, "Disconnected GitHub Repo from Project", ^traits}) - end - - test "renders 401 when unauthenticated", %{conn: conn} do - assert conn |> request_delete |> json_response(401) - end - - @tag :authenticated - test "renders 403 when not authorized", %{conn: conn} do - assert conn |> request_delete |> json_response(403) - end - - @tag :authenticated - test "renders 404 when id is nonexistent on delete", %{conn: conn} do - assert conn |> request_delete(:not_found) |> json_response(404) - end - end - - defp setup_project_repo(%User{} = current_user) do - project = insert(:project) - insert(:project_user, project: project, user: current_user, role: "owner") - owner = "baxterthehacker" - repo = "public-repo" - github_app_installation = insert(:github_app_installation, github_account_login: owner) - github_repo = insert(:github_repo, github_app_installation: github_app_installation, name: repo, github_account_id: 6752317, github_account_avatar_url: "https://avatars3.githubusercontent.com/u/6752317?v=4", github_account_type: "User", github_id: 35129377) - insert(:task_list, project: project, done: true) - insert(:task_list, project: project, inbox: true) - insert(:task_list, project: project, pull_requests: true) - {project, github_repo} - end -end diff --git a/test/lib/code_corps_web/controllers/task_controller_test.exs b/test/lib/code_corps_web/controllers/task_controller_test.exs index 14bd24d0c..85daa8ba0 100644 --- a/test/lib/code_corps_web/controllers/task_controller_test.exs +++ b/test/lib/code_corps_web/controllers/task_controller_test.exs @@ -128,8 +128,7 @@ defmodule CodeCorpsWeb.TaskControllerTest do @tag :authenticated test "tracks connecting to github", %{conn: conn, current_user: current_user} do - %{project: project, github_repo: github_repo} = - insert(:project_github_repo) + %{project: project} = github_repo = insert(:github_repo) task_list = insert(:task_list, project: project) assocs = %{ project: project, @@ -172,7 +171,7 @@ defmodule CodeCorpsWeb.TaskControllerTest do @tag :authenticated test "tracks connecting to github", %{conn: conn, current_user: current_user} do - %{project: project, github_repo: github_repo} = insert(:project_github_repo) + %{project: project} = github_repo = insert(:github_repo) task_list = insert(:task_list, project: project) task = insert(:task, task_list: task_list, project: project, user: current_user) @@ -186,7 +185,7 @@ defmodule CodeCorpsWeb.TaskControllerTest do @tag :authenticated test "does not track connecting to github if already connected", %{conn: conn, current_user: current_user} do - %{project: project, github_repo: github_repo} = insert(:project_github_repo) + %{project: project} = github_repo = insert(:github_repo) task_list = insert(:task_list, project: project) github_issue = insert(:github_issue, github_repo: github_repo) task = insert(:task, task_list: task_list, project: project, user: current_user, github_repo: github_repo, github_issue: github_issue) diff --git a/test/lib/code_corps_web/views/github_repo_view_test.exs b/test/lib/code_corps_web/views/github_repo_view_test.exs index 3aa13df58..0bb8eda81 100644 --- a/test/lib/code_corps_web/views/github_repo_view_test.exs +++ b/test/lib/code_corps_web/views/github_repo_view_test.exs @@ -2,11 +2,10 @@ defmodule CodeCorpsWeb.GithubRepoViewTest do use CodeCorpsWeb.ViewCase test "renders all attributes and relationships properly" do + project = insert(:project) github_app_installation = insert(:github_app_installation) - github_repo = insert(:github_repo, github_app_installation: github_app_installation) - project_github_repo = insert(:project_github_repo, github_repo: github_repo) + github_repo = insert(:github_repo, github_app_installation: github_app_installation, project: project) - github_repo = CodeCorpsWeb.GithubRepoController.preload(github_repo) rendered_json = render(CodeCorpsWeb.GithubRepoView, "show.json-api", data: github_repo) expected_json = %{ @@ -31,8 +30,8 @@ defmodule CodeCorpsWeb.GithubRepoViewTest do "github-app-installation" => %{ "data" => %{"id" => github_app_installation.id |> Integer.to_string, "type" => "github-app-installation"} }, - "project-github-repo" => %{ - "data" => %{"id" => project_github_repo.id |> Integer.to_string, "type" => "project-github-repo"} + "project" => %{ + "data" => %{"id" => project.id |> Integer.to_string, "type" => "project"} } } }, diff --git a/test/lib/code_corps_web/views/project_github_repo_view_test.exs b/test/lib/code_corps_web/views/project_github_repo_view_test.exs deleted file mode 100644 index 51d214dde..000000000 --- a/test/lib/code_corps_web/views/project_github_repo_view_test.exs +++ /dev/null @@ -1,32 +0,0 @@ -defmodule CodeCorpsWeb.ProjectGithubRepoViewTest do - use CodeCorpsWeb.ViewCase - - test "renders all attributes and relationships properly" do - project_github_repo = insert(:project_github_repo) - - rendered_json = render(CodeCorpsWeb.ProjectGithubRepoView, "show.json-api", data: project_github_repo) - - expected_json = %{ - "data" => %{ - "id" => project_github_repo.id |> Integer.to_string, - "type" => "project-github-repo", - "attributes" => %{ - "sync-state" => project_github_repo.sync_state, - }, - "relationships" => %{ - "github-repo" => %{ - "data" => %{"id" => project_github_repo.github_repo_id |> Integer.to_string, "type" => "github-repo"} - }, - "project" => %{ - "data" => %{"id" => project_github_repo.project_id |> Integer.to_string, "type" => "project"} - } - } - }, - "jsonapi" => %{ - "version" => "1.0" - } - } - - assert rendered_json == expected_json - end -end diff --git a/test/lib/code_corps_web/views/project_view_test.exs b/test/lib/code_corps_web/views/project_view_test.exs index b0c4a5e3b..d4e8f592c 100644 --- a/test/lib/code_corps_web/views/project_view_test.exs +++ b/test/lib/code_corps_web/views/project_view_test.exs @@ -7,7 +7,7 @@ defmodule CodeCorpsWeb.ProjectViewTest do donation_goal = insert(:donation_goal, project: project) project_category = insert(:project_category, project: project) - project_github_repo = insert(:project_github_repo, project: project) + github_repo = insert(:github_repo, project: project) project_skill = insert(:project_skill, project: project) project_user = insert(:project_user, project: project) stripe_connect_plan = insert(:stripe_connect_plan, project: project) @@ -47,6 +47,14 @@ defmodule CodeCorpsWeb.ProjectViewTest do "type" => "donation-goal" } ]}, + "github-repos" => %{ + "data" => [ + %{ + "id" => github_repo.id |> Integer.to_string, + "type" => "github-repo" + } + ] + }, "organization" => %{ "data" => %{ "id" => organization.id |> Integer.to_string, @@ -61,14 +69,6 @@ defmodule CodeCorpsWeb.ProjectViewTest do } ] }, - "project-github-repos" => %{ - "data" => [ - %{ - "id" => project_github_repo.id |> Integer.to_string, - "type" => "project-github-repo" - } - ] - }, "project-skills" => %{ "data" => [ %{ diff --git a/test/support/factories.ex b/test/support/factories.ex index e33018f70..0764d4084 100644 --- a/test/support/factories.ex +++ b/test/support/factories.ex @@ -86,7 +86,8 @@ defmodule CodeCorps.Factories do %CodeCorps.GithubRepo{ github_account_login: sequence(:github_account_login, &"owner_#{&1}"), github_app_installation: build(:github_app_installation), - name: sequence(:name, &"repo_#{&1}") + name: sequence(:name, &"repo_#{&1}"), + project: build(:project) } end @@ -179,13 +180,6 @@ defmodule CodeCorps.Factories do } end - def project_github_repo_factory do - %CodeCorps.ProjectGithubRepo{ - project: build(:project), - github_repo: build(:github_repo) - } - end - def role_factory do %CodeCorps.Role{ name: sequence(:name, &"Role #{&1}"), diff --git a/test/support/github/test_helpers.ex b/test/support/github/test_helpers.ex index 51a82ad29..10fa68fe0 100644 --- a/test/support/github/test_helpers.ex +++ b/test/support/github/test_helpers.ex @@ -11,8 +11,8 @@ defmodule CodeCorps.GitHub.TestHelpers do "./test/fixtures/github/events/#{id}.json" |> File.read! |> Poison.decode! end - @spec setup_coderly_project_repo :: %CodeCorps.ProjectGithubRepo{} - def setup_coderly_project_repo do + @spec setup_coderly_repo :: %CodeCorps.GithubRepo{} + def setup_coderly_repo do # Data is from the coderly/github-app-testing repository # # Uses: @@ -22,11 +22,11 @@ defmodule CodeCorps.GitHub.TestHelpers do # - the real GitHub user id of the repository owner # - the real GitHub App id # - the real GitHub repo id - setup_real_project_repo("coderly", "github-app-testing", 321667, 63365, 108674236) + setup_real_repo("coderly", "github-app-testing", 321667, 63365, 108674236) end - @spec setup_real_project_repo(String.t, String.t, Integer.t, Integer.t, Integer.t) :: %CodeCorps.ProjectGithubRepo{} - def setup_real_project_repo(repo_owner, repo_name, repo_owner_id, app_github_id, repo_github_id) do + @spec setup_real_repo(String.t, String.t, Integer.t, Integer.t, Integer.t) :: %CodeCorps.GithubRepo{} + def setup_real_repo(repo_owner, repo_name, repo_owner_id, app_github_id, repo_github_id) do # Create the user # # Simulates: @@ -65,11 +65,10 @@ defmodule CodeCorps.GitHub.TestHelpers do # # - installation or installation_repositories webhook # - user connecting the repository to the project - github_repo = insert(:github_repo, github_app_installation: github_app_installation, name: repo_name, github_account_id: repo_owner_id, github_account_avatar_url: "https://avatars3.githubusercontent.com/u/#{repo_owner_id}?v=4", github_account_type: "User", github_id: repo_github_id) - project_github_repo = insert(:project_github_repo, github_repo: github_repo, project: project) + github_repo = insert(:github_repo, github_app_installation: github_app_installation, name: repo_name, github_account_id: repo_owner_id, github_account_avatar_url: "https://avatars3.githubusercontent.com/u/#{repo_owner_id}?v=4", github_account_type: "User", github_id: repo_github_id, project: project) - # Return the %CodeCorps.ProjectGithubRepo{} record - project_github_repo + # Return the %CodeCorps.GithubRepo{} record + github_repo end @doc ~S"""