hubstats 0.4.4 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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