hubstats 0.4.4 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +5 -13
  2. data/.ruby-gemset +1 -0
  3. data/.ruby-version +1 -0
  4. data/CHANGELOG.markdown +5 -0
  5. data/README.md +64 -22
  6. data/app/assets/javascripts/hubstats/pull_requests.js +5 -0
  7. data/app/assets/javascripts/hubstats/select2.js +46 -3
  8. data/app/assets/javascripts/hubstats/users.js +8 -0
  9. data/app/assets/stylesheets/hubstats/application.css +5 -1
  10. data/app/controllers/hubstats/pull_requests_controller.rb +2 -3
  11. data/app/controllers/hubstats/repos_controller.rb +7 -12
  12. data/app/controllers/hubstats/teams_controller.rb +62 -0
  13. data/app/controllers/hubstats/users_controller.rb +9 -8
  14. data/app/models/hubstats/comment.rb +1 -0
  15. data/app/models/hubstats/pull_request.rb +40 -8
  16. data/app/models/hubstats/repo.rb +1 -1
  17. data/app/models/hubstats/team.rb +159 -0
  18. data/app/models/hubstats/user.rb +10 -1
  19. data/app/views/hubstats/deploys/show.html.erb +1 -4
  20. data/app/views/hubstats/partials/_comment-condensed.html.erb +1 -0
  21. data/app/views/hubstats/partials/_comment.html.erb +1 -0
  22. data/app/views/hubstats/partials/_footer.html.erb +3 -0
  23. data/app/views/hubstats/partials/_header.html.erb +5 -3
  24. data/app/views/hubstats/partials/_team.html.erb +40 -0
  25. data/app/views/hubstats/partials/_user-condensed.html.erb +6 -5
  26. data/app/views/hubstats/partials/_user.html.erb +2 -1
  27. data/app/views/hubstats/pull_requests/index.html.erb +4 -0
  28. data/app/views/hubstats/repos/dashboard.html.erb +0 -1
  29. data/app/views/hubstats/repos/show.html.erb +1 -1
  30. data/app/views/hubstats/tables/_comments-condensed.html.erb +1 -1
  31. data/app/views/hubstats/tables/_comments.html.erb +1 -1
  32. data/app/views/hubstats/tables/_deploys.html.erb +1 -1
  33. data/app/views/hubstats/tables/_grouped_deploys.html.erb +1 -1
  34. data/app/views/hubstats/tables/_grouped_pulls.html.erb +1 -1
  35. data/app/views/hubstats/tables/_pulls-condensed.html.erb +1 -1
  36. data/app/views/hubstats/tables/_pulls.html.erb +1 -1
  37. data/app/views/hubstats/tables/_repos-condensed.html.erb +1 -1
  38. data/app/views/hubstats/tables/_repos.html.erb +2 -2
  39. data/app/views/hubstats/tables/_teams.html.erb +28 -0
  40. data/app/views/hubstats/tables/_users-condensed.html.erb +1 -1
  41. data/app/views/hubstats/tables/_users.html.erb +2 -2
  42. data/app/views/hubstats/teams/index.html.erb +10 -0
  43. data/app/views/hubstats/teams/show.html.erb +28 -0
  44. data/app/views/hubstats/users/show.html.erb +2 -2
  45. data/config/routes.rb +4 -3
  46. data/db/migrate/20150706204910_create_hubstats_teams.rb +8 -0
  47. data/db/migrate/20150706205049_create_hubstats_teams_users.rb +8 -0
  48. data/db/migrate/20150713185013_add_team_id_to_prs.rb +5 -0
  49. data/hubstats.gemspec +2 -1
  50. data/lib/generators/hubstats/octokit.example.yml +3 -1
  51. data/lib/hubstats/events_handler.rb +20 -0
  52. data/lib/hubstats/github_api.rb +71 -15
  53. data/lib/hubstats/version.rb +1 -1
  54. data/lib/tasks/hubstats_tasks.rake +19 -0
  55. data/lib/tasks/populate_task.rake +35 -2
  56. data/spec/controllers/hubstats/repos_controller_spec.rb +1 -0
  57. data/spec/controllers/hubstats/teams_controller_spec.rb +39 -0
  58. data/spec/controllers/hubstats/users_controller_spec.rb +2 -0
  59. data/spec/factories/pull_requests.rb +1 -1
  60. data/spec/factories/teams.rb +24 -0
  61. data/spec/factories/users.rb +0 -1
  62. data/spec/lib/hubstats/events_handler_spec.rb +37 -7
  63. data/spec/lib/hubstats/github_api_spec.rb +55 -2
  64. data/spec/lib/hubstats_spec.rb +7 -1
  65. data/spec/models/hubstats/pull_request_spec.rb +34 -0
  66. data/spec/models/hubstats/team_spec.rb +23 -0
  67. data/spec/models/hubstats/user_spec.rb +26 -0
  68. data/test/dummy/config/initializers/octokit_patch.rb +3 -0
  69. data/test/dummy/db/schema.rb +51 -40
  70. metadata +62 -29
@@ -1,3 +1,3 @@
1
1
  module Hubstats
2
- VERSION = "0.4.4"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -9,6 +9,7 @@ namespace :hubstats do
9
9
  Rake::Task['db:migrate'].invoke
10
10
  puts "Pulling data from Github. This may take a while..."
11
11
  Rake::Task['hubstats:populate:setup_repos'].invoke
12
+ Rake::Task['hubstats:populate:setup_teams'].invoke
12
13
  end
13
14
 
14
15
  desc "Drops the database, then runs rake hubstats:setup"
@@ -30,4 +31,22 @@ namespace :hubstats do
30
31
  Rake::Task['db:seed'].invoke
31
32
  end
32
33
 
34
+ desc "Updates the teams for past pull requests"
35
+ task :update_teams_in_pulls => :environment do
36
+ puts "Updating teams for past pull requests"
37
+ Rake::Task['hubstats:populate:update_teams_in_pulls'].invoke
38
+ end
39
+
40
+ desc "Updates the teams"
41
+ task :update_teams => :environment do
42
+ puts "Updating teams"
43
+ Rake::Task['hubstats:populate:update_teams'].invoke
44
+ end
45
+
46
+ desc "Creates webhook from github for organization"
47
+ task :make_org_webhook => :environment do
48
+ puts "Making a webhook for an organization in octokit.yml"
49
+ Rake::Task['hubstats:populate:setup_teams'].invoke
50
+ end
51
+
33
52
  end
@@ -7,8 +7,10 @@ namespace :hubstats do
7
7
  Hubstats::GithubAPI.get_repos.each do |repo|
8
8
  Rake::Task["hubstats:populate:setup_repo"].execute({repo: repo})
9
9
  end
10
- puts "Finished with initial population, grabing extra info about pull requests"
10
+ puts "Finished with initial population, grabbing extra info about pull requests"
11
11
  Rake::Task["hubstats:populate:update_pulls"].execute
12
+ puts "Finished grabbing info about pull requests, populating teams"
13
+ Rake::Task["hubstats:populate:teams"].execute
12
14
  end
13
15
 
14
16
  desc "Updates which repos hubstats tracks"
@@ -20,6 +22,27 @@ namespace :hubstats do
20
22
  end
21
23
  puts "Finished with initial updating, grabbing extra info about pull requests"
22
24
  Rake::Task["hubstats:populate:update_pulls"].execute
25
+ puts "Finished grabbing info about pull requests, populating teams"
26
+ Rake::Task["hubstats:populate:teams"].execute
27
+ end
28
+
29
+ desc "Updates teams for past pull requests"
30
+ task :update_teams_in_pulls => :environment do
31
+ Rake::Task["hubstats:populate:update_teams_in_prs"].execute
32
+ end
33
+
34
+ desc "Updates the teams"
35
+ task :update_teams => :environment do
36
+ Rake::Task['hubstats:populate:teams'].execute
37
+ end
38
+
39
+ desc "Creates the webhook for the current org"
40
+ task :setup_teams => :environment do
41
+ Rake::Task['hubstats:populate:create_org_hook'].execute
42
+ end
43
+
44
+ task :create_org_hook => :environment do
45
+ Hubstats::GithubAPI.create_org_hook(config.github_config["org_name"])
23
46
  end
24
47
 
25
48
  desc "Pulls in all information for an indivdual repo"
@@ -31,7 +54,7 @@ namespace :hubstats do
31
54
  Rake::Task["hubstats:populate:pulls"].execute({repo: repo})
32
55
  Rake::Task["hubstats:populate:comments"].execute({repo: repo})
33
56
  Rake::Task["hubstats:populate:labels"].execute({repo: repo})
34
- end
57
+ end
35
58
 
36
59
  desc "Pull members from Github saves in database"
37
60
  task :users, [:repo] => :environment do |t, args|
@@ -80,6 +103,16 @@ namespace :hubstats do
80
103
  end
81
104
  end
82
105
 
106
+ desc "indivdually gets and updates all of the teams"
107
+ task :teams => :environment do
108
+ Hubstats::GithubAPI.update_teams
109
+ end
110
+
111
+ desc "updates the teams for all pull requests from past 365 days"
112
+ task :update_teams_in_prs => :environment do
113
+ Hubstats::PullRequest.update_teams_in_pulls(365)
114
+ end
115
+
83
116
  desc "Updates WebHooks for all repos"
84
117
  task :update_hooks, [:old_endpoint] => :environment do |t, args|
85
118
  Hubstats::Repo.all.each do |repo|
@@ -45,6 +45,7 @@ module Hubstats
45
45
  expect(assigns(:repo).pull_requests).to contain_exactly(pull1, pull2)
46
46
  expect(assigns(:repo).deploys).to contain_exactly(deploy1, deploy2)
47
47
  expect(assigns(:repo).owner_id).to eq(user.id)
48
+ expect(response).to have_http_status(200)
48
49
  end
49
50
  end
50
51
 
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ module Hubstats
4
+ describe TeamsController, :type => :controller do
5
+ routes { Hubstats::Engine.routes }
6
+
7
+ describe "#index" do
8
+ it "should return all of the teams" do
9
+ team1 = create(:team, :name => "Team One", :hubstats => true)
10
+ team2 = create(:team, :name => "Team Two", :hubstats => false)
11
+ team3 = create(:team, :name => "Team Three", :hubstats => true)
12
+ team4 = create(:team, :name => "Team Four", :hubstats => true)
13
+ expect(Hubstats::Team).to receive_message_chain("with_id.custom_order.paginate").and_return([team1, team2, team3, team4])
14
+ allow(Hubstats).to receive_message_chain(:config, :github_config, :[]).with("ignore_users_list") { ["user"] }
15
+ get :index
16
+ expect(response).to have_http_status(200)
17
+ end
18
+ end
19
+
20
+ describe "#show" do
21
+ it "should return the team and all of its users and pull requests" do
22
+ team = create(:team, :name => "Team Tests Passing", :hubstats => true, :id => 1)
23
+ user1 = create(:user, :id => 101010, :login => "examplePerson1")
24
+ user2 = create(:user, :id => 202020, :login => "examplePerson2")
25
+ team.users << user1
26
+ team.users << user2
27
+ pull1 = create(:pull_request, :user => user1, :id => 303030, :team => team)
28
+ pull2 = create(:pull_request, :user => user2, :id => 404040, :team => team, :repo => pull1.repo)
29
+ allow(Hubstats).to receive_message_chain(:config, :github_config, :[]).with("ignore_users_list") { ["user"] }
30
+ get :show, id: 1
31
+ expect(assigns(:team)).to eq(team)
32
+ expect(pull1.team_id).to eq(team.id)
33
+ expect(pull2.team_id).to eq(team.id)
34
+ expect(assigns(:team).users).to contain_exactly(user1, user2)
35
+ expect(response).to have_http_status(200)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -12,6 +12,7 @@ module Hubstats
12
12
  user4 = create(:user, :id => 404040, :login => "examplePerson4")
13
13
  expect(Hubstats::User).to receive_message_chain("with_id.custom_order.paginate").and_return([user2, user3, user1, user4])
14
14
  get :index
15
+ expect(response).to have_http_status(200)
15
16
  end
16
17
  end
17
18
 
@@ -29,6 +30,7 @@ module Hubstats
29
30
  expect(assigns(:user).pull_requests).to contain_exactly(pull1, pull2)
30
31
  expect(assigns(:user).deploys).to contain_exactly(deploy1, deploy2)
31
32
  expect(assigns(:user).comments).to contain_exactly(comment2, comment1)
33
+ expect(response).to have_http_status(200)
32
34
  end
33
35
  end
34
36
  end
@@ -35,5 +35,5 @@ FactoryGirl.define do
35
35
  merged_by(:id => 202020)
36
36
 
37
37
  initialize_with { attributes }
38
- end
38
+ end
39
39
  end
@@ -0,0 +1,24 @@
1
+ # Generates fake team data we can use to test with
2
+ FactoryGirl.define do
3
+ factory :team, :class => Hubstats::Team do
4
+ name "Team One"
5
+ hubstats true
6
+ end
7
+
8
+ factory :team_hash, class:Hash do
9
+ association :user, factory: :user_hash, strategy: :build
10
+ id {Faker::Number.number(6).to_i}
11
+ name "Team One"
12
+ hubstats true
13
+ action "added"
14
+ initialize_with { attributes }
15
+ end
16
+
17
+ factory :team_payload_hash, class:Hash do
18
+ id {Faker::Number.number(6).to_i}
19
+ type "MembershipEvent"
20
+ association :user, factory: :user_hash, strategy: :build
21
+ association :team, factory: :team_hash, strategy: :build
22
+ initialize_with { attributes }
23
+ end
24
+ end
@@ -13,5 +13,4 @@ FactoryGirl.define do
13
13
 
14
14
  initialize_with { attributes }
15
15
  end
16
-
17
16
  end
@@ -10,7 +10,7 @@ module Hubstats
10
10
  subject {Hubstats::EventsHandler.new()}
11
11
  it 'should successfully route the event' do
12
12
  expect(subject).to receive(:pull_processor)
13
- subject.route(payload,payload[:type])
13
+ subject.route(payload, payload[:type])
14
14
  end
15
15
 
16
16
  it 'should add labels to pull request' do
@@ -18,7 +18,7 @@ module Hubstats
18
18
  allow(Repo).to receive(:where) {[repo,repo]}
19
19
  allow(GithubAPI).to receive(:get_labels_for_pull) {['low','high']}
20
20
  expect(pull).to receive(:add_labels).with(['low','high'])
21
- subject.route(payload,payload[:type])
21
+ subject.route(payload, payload[:type])
22
22
  end
23
23
  end
24
24
 
@@ -27,22 +27,52 @@ module Hubstats
27
27
  ehandler = EventsHandler.new()
28
28
  payload = build(:comment_payload_hash)
29
29
  expect(ehandler).to receive(:comment_processor)
30
-
31
- ehandler.route(payload,payload[:type])
30
+ ehandler.route(payload, payload[:type])
32
31
  end
33
32
 
34
33
  it 'should successfully process the event' do
35
34
  ehandler = Hubstats::EventsHandler.new()
36
35
  payload = build(:comment_payload_hash)
37
36
  expect(Hubstats::Comment).to receive(:create_or_update)
38
-
39
- ehandler.route(payload,payload[:type])
37
+ ehandler.route(payload, payload[:type])
40
38
  end
41
39
 
42
40
  it 'should successfully creates_or_updates the event' do
43
41
  ehandler = Hubstats::EventsHandler.new()
44
42
  payload = build(:comment_payload_hash)
45
- expect(ehandler.route(payload,payload[:type]).class).to eq(Hubstats::Comment)
43
+ expect(ehandler.route(payload, payload[:type]).class).to eq(Hubstats::Comment)
44
+ end
45
+ end
46
+
47
+ context "TeamEvent" do
48
+ it 'should successfully route the team' do
49
+ ehandler = EventsHandler.new()
50
+ payload = build(:team_payload_hash)
51
+ expect(ehandler).to receive(:team_processor)
52
+ ehandler.route(payload, payload[:type])
53
+ end
54
+
55
+ it 'should successfully process the team' do
56
+ ehandler = Hubstats::EventsHandler.new()
57
+ payload = build(:team_payload_hash)
58
+ user = build(:user)
59
+ allow(Hubstats).to receive_message_chain(:config, :github_config, :[]).with("team_list") { ["Team One", "Team Two", "Team Three"] }
60
+ allow(Hubstats::User).to receive(:create_or_update).and_return(user)
61
+ expect(Hubstats::Team).to receive(:create_or_update)
62
+ expect(Hubstats::Team).to receive(:update_users_in_team)
63
+ ehandler.route(payload, payload[:type])
64
+ end
65
+
66
+ it 'should successfully create_or_update the team' do
67
+ ehandler = Hubstats::EventsHandler.new()
68
+ payload = build(:team_payload_hash)
69
+ team = build(:team)
70
+ user = build(:user)
71
+ allow(Hubstats).to receive_message_chain(:config, :github_config, :[]).with("team_list") { ["Team One", "Team Two", "Team Three"] }
72
+ allow(Hubstats::User).to receive(:create_or_update).and_return(user)
73
+ expect(Hubstats::Team).to receive(:update_users_in_team)
74
+ expect(Hubstats::Team).to receive(:create_or_update).and_return(team)
75
+ ehandler.route(payload, payload[:type])
46
76
  end
47
77
  end
48
78
 
@@ -67,6 +67,38 @@ module Hubstats
67
67
  end
68
68
  end
69
69
 
70
+ context '.update_teams' do
71
+ subject {Hubstats::GithubAPI}
72
+ let(:org) {'sportngin'}
73
+ let(:team1) {build(:team_hash, :name => "Team One")}
74
+ let(:team2) {build(:team_hash, :name => "Team Four")}
75
+ let(:team3) {build(:team_hash, :name => "Team Five")}
76
+ let(:team4) {build(:team_hash, :name => "Team Six")}
77
+ let(:team) {build(:team)}
78
+ let(:user1) {build(:user_hash)}
79
+ let(:user2) {build(:user_hash)}
80
+ let(:user3) {build(:user_hash)}
81
+ let(:hubstats_user) {build(:user)}
82
+ let(:access_token) { "access_token" }
83
+ let(:user) { double }
84
+ let(:client) { double(:user => user) }
85
+
86
+ it 'should successfully update all teams' do
87
+ allow_message_expectations_on_nil
88
+ allow(client).to receive(:organization_teams).with("sportngin").and_return([team1, team2, team3, team4])
89
+ allow(client).to receive(:team_members).with(team1[:id]).and_return([user1, user2, user3])
90
+ allow(Hubstats).to receive_message_chain(:config, :github_config, :[]).with("team_list") { ["Team One", "Team Two", "Team Three"] }
91
+ allow(Hubstats).to receive_message_chain(:config, :github_config, :[]).with("org_name") {"sportngin"}
92
+ allow(Hubstats::GithubAPI).to receive(:client).and_return(client)
93
+ allow(client).to receive(:rate_limit)
94
+ allow(Hubstats::Team).to receive_message_chain(:where, :name).with("Team One")
95
+ allow(Hubstats::Team.where(name: "Team One")).to receive(:first).and_return(team)
96
+ allow(client).to receive_message_chain(:rate_limit, :remaining).and_return(500)
97
+ expect(Hubstats::Team).to receive(:create_or_update).at_least(:once)
98
+ subject.update_teams
99
+ end
100
+ end
101
+
70
102
  context ".update_hook" do
71
103
  subject {Hubstats::GithubAPI}
72
104
  let(:repo) {'hubstats'}
@@ -98,16 +130,37 @@ module Hubstats
98
130
  allow(subject).to receive(:client) {client}
99
131
  end
100
132
 
101
- it "should call octokit create_hook" do
133
+ it "should call octokit create_hook for repositories" do
102
134
  expect(client).to receive(:create_hook)
103
135
  subject.create_hook(repo)
104
136
  end
105
137
 
106
- it "should rescue unprocessable entity" do
138
+ it "should rescue unprocessable entity from repo hook" do
107
139
  allow(client).to receive(:create_hook) { raise Octokit::UnprocessableEntity }
108
140
  subject.create_hook(repo)
109
141
  end
110
142
  end
111
143
 
144
+ context ".create_org_hook" do
145
+ subject {Hubstats::GithubAPI}
146
+ let(:config) {double(:webhook_secret => 'a1b2c3d4', :webhook_endpoint => "hubstats.com")}
147
+ let(:client) {double}
148
+ let(:org) {double(:full_name => 'sportngin') }
149
+ before do
150
+ allow(Hubstats).to receive(:config) {config}
151
+ allow(subject).to receive(:client) {client}
152
+ end
153
+
154
+ it "should call octokit create_hook for organizations" do
155
+ expect(client).to receive(:create_hook)
156
+ subject.create_hook(org)
157
+ end
158
+
159
+ it "should rescue unprocessable entity from organization hook" do
160
+ allow(client).to receive(:create_hook) { raise Octokit::UnprocessableEntity }
161
+ subject.create_hook(org)
162
+ end
163
+ end
164
+
112
165
  end
113
166
  end
@@ -3,9 +3,15 @@ require 'spec_helper'
3
3
  describe Hubstats
4
4
  context ".config" do
5
5
  subject { Hubstats }
6
- after do
6
+
7
+ before do
7
8
  Hubstats.class_variable_set(:@@config, nil)
8
9
  end
10
+
11
+ after do
12
+ Hubstats.remove_class_variable(:@@config)
13
+ end
14
+
9
15
  it "creates a new config object" do
10
16
  expect(Hubstats::Config).to receive(:parse).once { double(:config) }
11
17
  subject.config
@@ -41,5 +41,39 @@ module Hubstats
41
41
  expect(deploy.user_id).to eq(nil)
42
42
  expect(pull_request.deploy.user_id).to eq(202020)
43
43
  end
44
+
45
+ it "should track the team_id when making a pull request" do
46
+ user_hash = {login: 'name', id: '12345'}
47
+ user = User.create(user_hash)
48
+ team = create(:team, id: 1010)
49
+ team.users << user
50
+ pull = build(:pull_request_hash, :user => user_hash)
51
+ pull_request = PullRequest.create_or_update(pull)
52
+ expect(pull_request.user_id).to eq(user[:id])
53
+ expect(pull_request.team_id).to eq(team[:id])
54
+ end
55
+
56
+ it "should leave the team_id of a pull request blank if user is not part of a team" do
57
+ user_hash = {login: 'name', id: '12345'}
58
+ user = User.create(user_hash)
59
+ pull = build(:pull_request_hash, :user => user_hash)
60
+ pull_request = PullRequest.create_or_update(pull)
61
+ expect(pull_request.user_id).to eq(user[:id])
62
+ expect(pull_request.team_id).to eq(nil)
63
+ end
64
+
65
+ it 'should update the team_ids in pull requests' do
66
+ team = build(:team)
67
+ repo = build(:repo)
68
+ user1 = build(:user)
69
+ user2 = build(:user, :id => 7)
70
+ team.users << user1
71
+ team.users << user2
72
+ pull1 = build(:pull_request, :created_at => Date.today - 250, :user => user1)
73
+ pull2 = build(:pull_request, :created_at => Date.today - 3, :repo => repo, :user => user2)
74
+ Hubstats::PullRequest.update_teams_in_pulls(365)
75
+ expect(pull1.team_id).to eq(team.id)
76
+ expect(pull2.team_id).to eq(team.id)
77
+ end
44
78
  end
45
79
  end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ module Hubstats
4
+ describe Team, :type => :model do
5
+ it 'should create a team' do
6
+ team_hash = {name: "Team Tippy-Tappy-Toes",
7
+ hubstats: true}
8
+ team = Team.create(team_hash)
9
+ expect(Team.count).to eq(1)
10
+ expect(team.name).to eq("Team Tippy-Tappy-Toes")
11
+ expect(team.hubstats).to eq(true)
12
+ end
13
+
14
+ it 'should add a member to a team' do
15
+ user = build(:user)
16
+ action = "added"
17
+ team = build(:team)
18
+ Hubstats::Team.update_users_in_team(team, user, action)
19
+ expect(team.users).to eq([user])
20
+ expect(team.users.length).to eq(1)
21
+ end
22
+ end
23
+ end