lita-github 0.0.10 → 0.0.11

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0edd68ade3e5fc642ccb5e606a94b09d40e08d8f
4
- data.tar.gz: 8461b46c716ea556aa2c7cf50db4f91c994d91a6
3
+ metadata.gz: f9d776a2cd23860fda771d4efd3a3602b672cfb0
4
+ data.tar.gz: 074232e708387b5457e8162b247ab40042fee1cb
5
5
  SHA512:
6
- metadata.gz: 4842ed8a61059de7b651561966c2f074f223c1cc1489ecd92f379dad78ac6c19e5d3d5d7eb727d5254eb4125450e486847aa5a144c9520bff9cdf287ae1aaa01
7
- data.tar.gz: d3f24df978afe5d70bd924c8c6165c391b225d55af099c684c06549d3bb615fea9dc73ebd0fe668cfb5b3c0e5ea8e7854b4079c96ec8639968dcec995e73f4e6
6
+ metadata.gz: 656ec110d8e8461509241198219d5fa7cd7fca49cf92ce6f50bd0260ebfddc3e74a47cc09cfca4c4f948bbfa04d10f0ee614223f16c552a0d7cf86127cc5c80c
7
+ data.tar.gz: a8cb3ffc5acc22b40f504027d303978eff9043c00ae8bcce84dbc51d73e69adf08610c174edf316b0cea875917b54bf8bed5d2a8db44180d17ea4b029cea6ce5
data/README.md CHANGED
@@ -80,3 +80,5 @@ Here is the current functionality:
80
80
  ### Github Organization Handler
81
81
  * `!gh org teams PagerDuty` & `!gh teams PagerDuty`
82
82
  * list the teams for the GitHub repo
83
+
84
+ There is also an early version of organization team management (add / remove) not documented as well. Documentation is missing because it's not feature complete.
@@ -0,0 +1,61 @@
1
+ # -*- coding: UTF-8 -*-
2
+ #
3
+ # Copyright 2014 PagerDuty, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'lita-github/r'
18
+
19
+ module LitaGithub
20
+ # Github handler common-use methods
21
+ #
22
+ # @author Tim Heckman <tim@pagerduty.com>
23
+ module General
24
+ # Parse the options in the command using the standard option regex
25
+ #
26
+ # @author Tim Heckman <tim@pagerduty.com>
27
+ # @param cmd [String] the full command line provided to Lita
28
+ # @return [Hash] the key:value pairs that were in the command string
29
+ def opts_parse(cmd)
30
+ o = {}
31
+ cmd.scan(LitaGithub::R::OPT_REGEX).flatten.each do |opt|
32
+ k, v = opt.strip.split(':')
33
+ k = k.to_sym
34
+ o[k] = v unless o.key?(k)
35
+ end
36
+ o
37
+ end
38
+
39
+ # Parse the options in the command using the extended option regex
40
+ #
41
+ # @author Tim Heckman <tim@pagerduty.com>
42
+ # @param cmd [String] the full command line provided to Lita
43
+ # @return [Hash] the key:value pairs that were in the command string
44
+ def e_opts_parse(cmd)
45
+ o = {}
46
+ cmd.scan(LitaGithub::R::E_OPT_REGEX).flatten.each do |opt|
47
+ k, v = opt.strip.split(':')
48
+ k = k.to_sym
49
+
50
+ # if it looks like we're using the extended option (first character is a " or '):
51
+ # slice off the first and last character of the string
52
+ # otherwise:
53
+ # do nothing
54
+ v = v.slice!(1, (v.length - 2)) if %w(' ").include?(v.slice(0))
55
+
56
+ o[k] = v unless o.key?(k)
57
+ end
58
+ o
59
+ end
60
+ end
61
+ end
@@ -16,13 +16,61 @@
16
16
 
17
17
  module LitaGithub
18
18
  # Github handler common-use Organization methods
19
+ #
20
+ # @author Tim Heckman <tim@pagerduty.com>
19
21
  module Org
22
+ # Uses default organization if one provided is nil or empty string
23
+ #
24
+ # @author Tim Heckman <tim@pagerduty.com>
25
+ # @param name [String,Nil] the name of the organization
26
+ # @return [String] the name of the organization to use
20
27
  def organization(name)
21
28
  name.nil? || name.empty? ? config.default_org : name
22
29
  end
23
30
 
31
+ # Sorts a list of Github team objects by name
32
+ #
33
+ # @author Tim Heckman <tim@pagerduty.com>
34
+ # @param teams [Array<Teams>] pass in the teams you want to sort by name
35
+ # @return [Array] the teams but sorted by name
24
36
  def sort_by_name(teams)
25
37
  teams.sort_by { |h| h[:name].downcase }
26
38
  end
39
+
40
+ # Get the Github team ID using its slug
41
+ #
42
+ # This depends on the `octo()` method from LitaGithub::Octo being within the same scope
43
+ #
44
+ # @author Tim Heckman <tim@pagerduty.com>
45
+ # @param slug [String] the slug of the team you're getting the ID for
46
+ # @param org [String] the organization this team should belong in
47
+ # @return [Nil] if no team was found nil is returned
48
+ # @return [Integer] if a team is found the team's ID is returned
49
+ def team_id_by_slug(slug, org)
50
+ octo.organization_teams(org).each do |team|
51
+ return team[:id] if team[:slug] == slug
52
+ end
53
+ nil
54
+ end
55
+
56
+ # Get the team id based on either the team slug or the team id
57
+ #
58
+ # @author Tim Heckman <tim@pagerduty.com>
59
+ # @param team [String,Integer] this is either the team's slug or the team's id
60
+ # @return [Integer] the team's id
61
+ def team_id(team, org)
62
+ /^\d+$/.match(team.to_s) ? team : team_id_by_slug(team, org)
63
+ end
64
+
65
+ # Check if a team exists
66
+ #
67
+ # @param id [Integer] the id number for the team
68
+ # @return [Sawyer::Resource(Github team)] if team exists
69
+ # @return [FalseClass] if team does not exist
70
+ def team?(id)
71
+ octo.team(id)
72
+ rescue Octokit::NotFound
73
+ false
74
+ end
27
75
  end
28
76
  end
data/lib/lita-github/r.rb CHANGED
@@ -24,6 +24,10 @@ module LitaGithub
24
24
  # key1:value key2:value, etc.
25
25
  OPT_REGEX ||= /((?:\s+?[a-zA-Z0-9_]+?):(?:[a-zA-Z0-9_]+))/
26
26
 
27
+ # extended option regex, letting you scan the string for things like:
28
+ # key1:value key2:"value2" key3:'a better value'
29
+ E_OPT_REGEX ||= /((?:\s+?[a-zA-Z0-9_]+?):(?:(?:".+?")|(?:'.+?')|(?:[a-zA-Z0-9_]+)))/
30
+
27
31
  # regex matcher for: Org/repo
28
32
  REPO_REGEX = '(?:(?<org>[a-zA-Z0-9_\-]+)(?:\s+?)?\/)?(?:\s+?)?(?<repo>[a-zA-Z0-9_\-]+)'
29
33
  end
@@ -16,6 +16,6 @@
16
16
 
17
17
  # Administer your Hub of Gits with Lita!
18
18
  module LitaGithub
19
- VERSION = '0.0.10'
19
+ VERSION = '0.0.11'
20
20
  MAJ, MIN, REV = VERSION.split('.').map(&:to_i)
21
21
  end
@@ -79,6 +79,11 @@ module Lita
79
79
 
80
80
  # Lita::Handlers::GithubPR
81
81
  config.pr_merge_enabled = true
82
+
83
+ # Lita::Handlers::GithubOrg
84
+ config.org_team_add_enabled = false
85
+ config.org_team_rm_enabled = false
86
+ config.org_team_add_allowed_perms = %w(pull)
82
87
  end
83
88
 
84
89
  def status(response)
@@ -15,22 +15,27 @@
15
15
  # limitations under the License.
16
16
 
17
17
  require 'lita-github/r'
18
+ require 'lita-github/general'
18
19
  require 'lita-github/config'
19
20
  require 'lita-github/octo'
20
21
  require 'lita-github/org'
22
+ require 'lita-github/filters'
21
23
 
22
24
  module Lita
23
25
  # Lita Handler
24
26
  module Handlers
25
27
  # GitHub Lita Handler
26
28
  class GithubOrg < Handler
29
+ include LitaGithub::General # Github handler common-use methods
27
30
  include LitaGithub::Config # Github handler Lita configuration methods
28
31
  include LitaGithub::Octo # Github handler common-use Octokit methods
29
32
  include LitaGithub::Org # Github handler common-use Organization methods
33
+ include LitaGithub::Filters # Github handler common-use method filters
30
34
 
31
35
  on :loaded, :setup_octo # from LitaGithub::Octo
32
36
 
33
- # rubocop:disable Metrics/LineLength
37
+ KNOWN_PERMS = %w(pull push admin)
38
+
34
39
  route(
35
40
  /#{LitaGithub::R::A_REG}(?:teams|org\s+?teams|org\s+?team\s+?list)(?<org>\s+[a-zA-Z0-9_\-]+)?/,
36
41
  :org_teams_list,
@@ -40,8 +45,29 @@ module Lita
40
45
  'gh teams [organization]' => 'an alias for gh org teams'
41
46
  }
42
47
  )
48
+
49
+ # rubocop:disable Metrics/LineLength
50
+ route(
51
+ # /#{LitaGithub::R::A_REG}org\s+?team\s+?add(?<org>\s+?[a-zA-Z0-9_\-]+)?(?<perm>\s+?[a-zA-Z]+)\s+?(?<name>.*)$/,
52
+ /#{LitaGithub::R::A_REG}org\s+?team\s+?add(?<org>\s+?[a-zA-Z0-9_\-]+)?/,
53
+ :org_team_add, command: true, confirmation: true,
54
+ help: {
55
+ 'gh org team add PagerDuty name:"All Employees" perms:pull' => 'add an "All Engineers" team with pull permissions',
56
+ 'gh org team add PagerDuty name:Leads perms:pull' => 'add a "Leads" team with admin permissions',
57
+ 'gh org team add PagerDuty name:Ops perms:push' => 'add an "Ops" team with push permissions'
58
+ }
59
+ )
43
60
  # rubocop:enable Metrics/LineLength
44
61
 
62
+ route(
63
+ /#{LitaGithub::R::A_REG}org\s+?team\s+?rm(?<org>\s+?[a-zA-Z0-9_\-]+)?(?<team>\s+?[a-zA-Z0-9_\-]+)/,
64
+ :org_team_rm, command: true, confirmation: true,
65
+ help: {
66
+ 'gh org team rm PagerDuty ops' => 'delete the Operations team',
67
+ 'gh org team rm PagerDuty 42' => 'delete the team with id 42'
68
+ }
69
+ )
70
+
45
71
  def org_teams_list(response)
46
72
  md = response.match_data
47
73
  org = md[:org].nil? ? config.default_org : organization(md[:org].strip)
@@ -63,6 +89,62 @@ module Lita
63
89
 
64
90
  response.reply(reply)
65
91
  end
92
+
93
+ def org_team_add(response)
94
+ return response.reply(t('method_disabled')) if func_disabled?(__method__)
95
+
96
+ opts = e_opts_parse(response.message.body)
97
+ vo = validate_team_add_opts(opts)
98
+ return response.reply(vo[:msg]) unless vo[:success]
99
+
100
+ md = response.match_data
101
+ org, perm, name = [organization(md['org'].strip), opts[:perms].strip.downcase, opts[:name]]
102
+
103
+ return response.reply(
104
+ t('org_team_add.perm_not_permitted', perms: config.org_team_add_allowed_perms.join(', '))
105
+ ) unless permission_allowed?(perm)
106
+
107
+ begin
108
+ resp = octo.create_team(org, name: name, permission: perm)
109
+ rescue Octokit::NotFound
110
+ return response.reply(t('org_not_found', org: org))
111
+ end
112
+
113
+ response.reply(t('org_team_add.created_team', resp.to_h))
114
+ end
115
+
116
+ def org_team_rm(response)
117
+ return response.reply(t('method_disabled')) if func_disabled?(__method__)
118
+
119
+ md = response.match_data
120
+ org, team = [organization(md['org'].strip), md['team'].strip]
121
+
122
+ t_id = team_id(team, org)
123
+ t = team?(t_id)
124
+
125
+ return response.reply(t('team_not_found', team: team)) unless t
126
+
127
+ if octo.delete_team(t_id)
128
+ response.reply(t('org_team_rm.pass', t.to_h))
129
+ else
130
+ response.reply(t('org_team_rm.fail', t.to_h))
131
+ end
132
+ end
133
+
134
+ private
135
+
136
+ def validate_team_add_opts(opts)
137
+ h = { success: true, msg: '' }
138
+ h[:msg] << t('org_team_add.missing_option', opt: 'name') unless opts.key?(:name)
139
+ h[:msg] << t('org_team_add.missing_option', opt: 'perms') unless opts.key?(:perms)
140
+ h[:msg] << t('org_team_add.perm_invalid') if opts.key?(:perms) && !KNOWN_PERMS.include?(opts[:perms].downcase)
141
+ h[:success] = false unless h[:msg].empty?
142
+ h
143
+ end
144
+
145
+ def permission_allowed?(perm)
146
+ config.org_team_add_allowed_perms.include?(perm)
147
+ end
66
148
  end
67
149
 
68
150
  Lita.register_handler(GithubOrg)
@@ -16,6 +16,7 @@
16
16
 
17
17
  require 'uri'
18
18
  require 'lita-github/r'
19
+ require 'lita-github/general'
19
20
  require 'lita-github/config'
20
21
  require 'lita-github/octo'
21
22
  require 'lita-github/org'
@@ -27,6 +28,7 @@ module Lita
27
28
  module Handlers
28
29
  # GitHub Lita Handler
29
30
  class GithubRepo < Handler
31
+ include LitaGithub::General # Github handler common-use methods
30
32
  include LitaGithub::Config # Github handler Lita configuration methods
31
33
  include LitaGithub::Octo # Github handler common-use Octokit methods
32
34
  include LitaGithub::Org # Github handler common-use Organization methods
@@ -104,7 +106,7 @@ module Lita
104
106
  return response.reply(t('repo_create.exists', org: org, repo: repo))
105
107
  end
106
108
 
107
- opts = extrapolate_create_opts(command_opts(response.args.join(' ')), org)
109
+ opts = extrapolate_create_opts(opts_parse(response.message.body), org)
108
110
 
109
111
  response.reply(create_repo(org, repo, opts))
110
112
  end
@@ -245,16 +247,6 @@ module Lita
245
247
  t('repo_update_homepage.updated', repo: full_name, url: resp[:homepage])
246
248
  end
247
249
 
248
- def command_opts(cmd)
249
- o = {}
250
- cmd.scan(LitaGithub::R::OPT_REGEX).flatten.compact.each do |opt|
251
- k, v = opt.strip.split(':')
252
- k = k.to_sym
253
- o[k] = v unless o.key?(k)
254
- end
255
- o
256
- end
257
-
258
250
  def extrapolate_create_opts(opts, org)
259
251
  opts[:organization] = org
260
252
 
@@ -271,13 +263,6 @@ module Lita
271
263
  opts
272
264
  end
273
265
 
274
- def team_id_by_slug(slug, org)
275
- octo.organization_teams(org).each do |team|
276
- return team[:id] if team[:slug] == slug
277
- end
278
- nil
279
- end
280
-
281
266
  def default_team(org)
282
267
  config.default_team_slug.nil? ? nil : team_id_by_slug(config.default_team_slug, org)
283
268
  end
@@ -333,12 +318,12 @@ module Lita
333
318
  end
334
319
 
335
320
  def gh_team(org, team)
336
- team_id = /^\d+$/.match(team.to_s) ? team : team_id_by_slug(team, org)
321
+ t_id = team_id(team, org)
337
322
 
338
- return nil if team_id.nil?
323
+ return nil if t_id.nil?
339
324
 
340
325
  begin
341
- octo.team(team_id)
326
+ octo.team(t_id)
342
327
  rescue Octokit::NotFound
343
328
  nil
344
329
  end
data/lita-github.gemspec CHANGED
@@ -42,6 +42,7 @@ Gem::Specification.new do |s|
42
42
  s.add_development_dependency 'fuubar', '~> 2.0'
43
43
  s.add_development_dependency 'pry', '~> 0.10', '>= 0.10.1'
44
44
  s.add_development_dependency 'codeclimate-test-reporter', '~> 0.4', '>= 0.4.0'
45
+ s.add_development_dependency 'yard', '~> 0.8.7'
45
46
 
46
47
  s.add_runtime_dependency 'lita', '~> 3.3'
47
48
  s.add_runtime_dependency 'octokit', '~> 3.3'
data/locales/en.yml CHANGED
@@ -59,7 +59,17 @@ en:
59
59
  large_list: "You have more than %{max} open pull requests :(! Here are the ten newest oldest:\n"
60
60
  no_prs: "This repo has no open pull requests; good job!"
61
61
  github_org:
62
- org_not_found: "The organization '%{org}' was not found. Does my user have ownership permission?"
62
+ method_disabled: "Sorry, this function has either been disabled or not enabled in the config"
63
+ org_not_found: "The organization '%{org}' was not found. Does my user have ownership perms?"
64
+ team_not_found: "Unable to match any teams based on: %{team}"
63
65
  org_teams_list:
64
66
  header: "Showing %{num_teams} team(s) for %{org}:\n"
65
67
  team: "Name: %{name}, Slug: %{slug}, ID: %{id}, Perms: %{permission}\n"
68
+ org_team_add:
69
+ missing_option: "Missing the %{opt} option\n"
70
+ perm_invalid: "Valid perms are: pull push admin -- they can be selectively enabled via the config\n"
71
+ perm_not_permitted: "Sorry, the permission level you requested was not allowed in the config. Right now the only perms permitted are: %{perms}"
72
+ created_team: "The '%{name}' team was created; Slug: %{slug}, ID: %{id}, Perms: %{permission}"
73
+ org_team_rm:
74
+ pass: "The '%{name}' team was deleted. Its ID was %{id}"
75
+ fail: "Something went wrong trying to delete the '%{name}' team. Is Github having issues?"
@@ -1,4 +1,18 @@
1
1
  # -*- coding: UTF-8 -*-
2
+ #
3
+ # Copyright 2014 PagerDuty, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
2
16
 
3
17
  require 'spec_helper'
4
18
 
@@ -0,0 +1,45 @@
1
+ # -*- coding: UTF-8 -*-
2
+ #
3
+ # Copyright 2014 PagerDuty, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'spec_helper'
18
+
19
+ describe LitaGithub::General do
20
+ include LitaGithub::General
21
+
22
+ describe '.opts_parse' do
23
+ it 'should find the valid options' do
24
+ o = ' private:true team:heckman bacon:always bacon:sometimes'
25
+ co = opts_parse(o)
26
+ expect(co).to be_an_instance_of Hash
27
+ expect(co[:private]).to eql 'true'
28
+ expect(co[:team]).to eql 'heckman'
29
+ expect(co[:bacon]).to eql 'always' # of course it's always
30
+ end
31
+ end
32
+
33
+ describe '.e_opts_parse' do
34
+ it 'should find the valid options' do
35
+ o = %q( private:true team:heckman bacon:always bacon:sometimes string1:"something here" string2:'something else')
36
+ co = e_opts_parse(o)
37
+ expect(co).to be_an_instance_of Hash
38
+ expect(co[:private]).to eql 'true'
39
+ expect(co[:team]).to eql 'heckman'
40
+ expect(co[:bacon]).to eql 'always' # of course it's always
41
+ expect(co[:string1]).to eql 'something here'
42
+ expect(co[:string2]).to eql 'something else'
43
+ end
44
+ end
45
+ end
@@ -1,4 +1,18 @@
1
1
  # -*- coding: UTF-8 -*-
2
+ #
3
+ # Copyright 2014 PagerDuty, Inc.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
2
16
 
3
17
  require 'spec_helper'
4
18
 
@@ -46,4 +60,71 @@ describe LitaGithub::Org do
46
60
  expect(sort_by_name(unsorted_list)).to eql sorted_list
47
61
  end
48
62
  end
63
+
64
+ describe '.team_id_by_slug' do
65
+ before do
66
+ @teams = [
67
+ { id: 1, slug: 'hi' },
68
+ { id: 42, slug: 'heckman' },
69
+ { id: 84, slug: 'orwell' }
70
+ ]
71
+ @octo_obj = double('Octokit::Client', organization_teams: @teams)
72
+ allow(self).to receive(:octo).and_return(@octo_obj)
73
+ end
74
+
75
+ it 'should return the team id of the team matching the slug' do
76
+ expect(@octo_obj).to receive(:organization_teams).with('GrapeDuty').and_return(@teams)
77
+ expect(team_id_by_slug('heckman', 'GrapeDuty')).to eql 42
78
+ expect(team_id_by_slug('orwell', 'GrapeDuty')).to eql 84
79
+ expect(team_id_by_slug('unknown', 'GrapeDuty')).to be_nil
80
+ end
81
+
82
+ it 'should return nil if unknown' do
83
+ expect(team_id_by_slug('unknown', 'x')).to be_nil
84
+ end
85
+ end
86
+
87
+ describe '.team_id' do
88
+ before { allow(self).to receive(:team_id_by_slug).and_return(84) }
89
+
90
+ context 'when value is an "Integer"' do
91
+ it 'should return the value passed in' do
92
+ v = 42
93
+ expect(team_id(v, 'GrapeDuty')).to eql v
94
+ end
95
+ end
96
+
97
+ context 'when the value is not an Integer' do
98
+ it 'should return the id from team_id_by_slug()' do
99
+ expect(self).to receive(:team_id_by_slug).with('TestIt', 'GrapeDuty').and_return(84)
100
+ expect(team_id('TestIt', 'GrapeDuty')).to eql 84
101
+ end
102
+ end
103
+ end
104
+
105
+ describe '.team?' do
106
+ before do
107
+ @octo_obj = double('Octokit::Client', team: {})
108
+ allow(self).to receive(:octo).and_return(@octo_obj)
109
+ end
110
+
111
+ it 'should try to load the team' do
112
+ expect(@octo_obj).to receive(:team).with(42).and_return(nil)
113
+ team?(42)
114
+ end
115
+
116
+ context 'when team exists' do
117
+ it 'should return true' do
118
+ expect(team?(42)).to be_truthy
119
+ end
120
+ end
121
+
122
+ context 'when team does not exist' do
123
+ before { allow(@octo_obj).to receive(:team).and_raise(Octokit::NotFound.new) }
124
+
125
+ it 'should return false' do
126
+ expect(team?(42)).to be_falsey
127
+ end
128
+ end
129
+ end
49
130
  end
@@ -47,39 +47,95 @@ describe LitaGithub::R do
47
47
  context 'it should match' do
48
48
  it 'test:pass' do
49
49
  s = ' test:pass'
50
- m = s.scan(subject).flatten.compact
51
- expect(m).to eql [' test:pass']
50
+ m = s.scan(subject).flatten.map(&:strip)
51
+ expect(m).to eql ['test:pass']
52
52
  end
53
53
 
54
54
  it 'test7_pass:pAss_test' do
55
55
  s = ' test7_pass:pAss_test'
56
- m = s.scan(subject).flatten.compact
57
- expect(m).to eql [' test7_pass:pAss_test']
56
+ m = s.scan(subject).flatten.map(&:strip)
57
+ expect(m).to eql ['test7_pass:pAss_test']
58
58
  end
59
59
 
60
60
  it 'test:pass bacon:always test:coverage' do
61
61
  s = ' test:pass bacon:always test:coverage'
62
- m = s.scan(subject).flatten.compact
63
- expect(m).to eql [' test:pass', ' bacon:always', ' test:coverage']
62
+ m = s.scan(subject).flatten.map(&:strip)
63
+ expect(m).to eql ['test:pass', 'bacon:always', 'test:coverage']
64
64
  end
65
65
  end
66
66
 
67
67
  context 'it should not match' do
68
68
  it 'test-stuff:fail' do
69
69
  s = ' test-stuff:fail'
70
- m = s.scan(subject).flatten.compact
70
+ m = s.scan(subject).flatten
71
71
  expect(m).to be_empty
72
72
  end
73
73
 
74
74
  it 'test: fail' do
75
75
  s = ' test: fail'
76
- m = s.scan(subject).flatten.compact
76
+ m = s.scan(subject).flatten
77
77
  expect(m).to be_empty
78
78
  end
79
79
 
80
80
  it 'test:fail (no leading space)' do
81
81
  s = 'test:fail'
82
- m = s.scan(subject).flatten.compact
82
+ m = s.scan(subject).flatten
83
+ expect(m).to be_empty
84
+ end
85
+ end
86
+ end
87
+
88
+ describe '::E_OPT_REGEX' do
89
+ subject { LitaGithub::R::E_OPT_REGEX }
90
+
91
+ context 'it should match' do
92
+ it 'test:pass' do
93
+ s = ' test:pass'
94
+ m = s.scan(subject).flatten.map(&:strip)
95
+ expect(m).to eql ['test:pass']
96
+ end
97
+
98
+ it 'test7_pass:pAss_test' do
99
+ s = ' test7_pass:pAss_test'
100
+ m = s.scan(subject).flatten.map(&:strip)
101
+ expect(m).to eql ['test7_pass:pAss_test']
102
+ end
103
+
104
+ it 'test:pass bacon:always test:coverage' do
105
+ s = ' test:pass bacon:always test:coverage'
106
+ m = s.scan(subject).flatten.map(&:strip)
107
+ expect(m).to eql ['test:pass', 'bacon:always', 'test:coverage']
108
+ end
109
+
110
+ it 'testing:"hi" test:"hello there"' do
111
+ s = ' testing:"hi" test:"hello there"'
112
+ m = s.scan(subject).flatten.map(&:strip)
113
+ expect(m).to eql ['testing:"hi"', 'test:"hello there"']
114
+ end
115
+
116
+ it "testing:'hello' test:'what is up?'" do
117
+ s = " testing:'hello' test:'what is up?'"
118
+ m = s.scan(subject).flatten.map(&:strip)
119
+ expect(m).to eql ["testing:'hello'", "test:'what is up?'"]
120
+ end
121
+ end
122
+
123
+ context 'it should not match' do
124
+ it 'test-stuff:fail' do
125
+ s = ' test-stuff:fail'
126
+ m = s.scan(subject).flatten
127
+ expect(m).to be_empty
128
+ end
129
+
130
+ it 'test: fail' do
131
+ s = ' test: fail'
132
+ m = s.scan(subject).flatten
133
+ expect(m).to be_empty
134
+ end
135
+
136
+ it 'test:fail (no leading space)' do
137
+ s = 'test:fail'
138
+ m = s.scan(subject).flatten
83
139
  expect(m).to be_empty
84
140
  end
85
141
  end
@@ -17,15 +17,92 @@
17
17
  require 'spec_helper'
18
18
 
19
19
  describe Lita::Handlers::GithubOrg, lita_handler: true do
20
+ # org_team_list routing
20
21
  it { routes_command('gh teams PagerDuty').to(:org_teams_list) }
21
22
  it { routes_command('gh org teams GrapeDuty').to(:org_teams_list) }
22
- it { routes_command('gh org team list PagerDuty').to(:org_teams_list) }
23
+ it { routes_command('gh org team list GrapeDuty').to(:org_teams_list) }
23
24
  it { routes_command('gh teams').to(:org_teams_list) }
24
25
  it { routes_command('gh org teams').to(:org_teams_list) }
25
26
  it { routes_command('gh org team list').to(:org_teams_list) }
26
27
 
28
+ # org_team_add routing
29
+ it { routes_command('gh org team add GrapeDuty name:"All Staff" perms:pull').to(:org_team_add) }
30
+ it { routes_command('gh org team add name:"All Staff" perms:pull').to(:org_team_add) }
31
+
27
32
  let(:github_org) { Lita::Handlers::GithubOrg.new('robot') }
28
33
 
34
+ ####
35
+ # Helper Methods
36
+ ####
37
+ describe '.validate_team_add_opts' do
38
+ context 'when opts are valid' do
39
+ let(:opts) { { name: 'hi', perms: 'pull' } }
40
+
41
+ it 'should return with happy Hash' do
42
+ expect(github_org.send(:validate_team_add_opts, opts)).to eql success: true, msg: ''
43
+ end
44
+ end
45
+
46
+ context 'when name is missing' do
47
+ let(:opts) { { perms: 'pull' } }
48
+
49
+ it 'should return a bad has with a proper message' do
50
+ r = github_org.send(:validate_team_add_opts, opts)
51
+ expect(r).to eql success: false, msg: "Missing the name option\n"
52
+ end
53
+ end
54
+
55
+ context 'when perms is missing' do
56
+ let(:opts) { { name: 'hi' } }
57
+
58
+ it 'should return a bad has with a proper message' do
59
+ r = github_org.send(:validate_team_add_opts, opts)
60
+ expect(r).to eql success: false, msg: "Missing the perms option\n"
61
+ end
62
+ end
63
+
64
+ context 'when perms is invalid' do
65
+ let(:opts) { { name: 'hi', perms: 'something' } }
66
+
67
+ it 'should return a bad has with a proper message' do
68
+ r = github_org.send(:validate_team_add_opts, opts)
69
+ expect(r).to eql(
70
+ success: false, msg: "Valid perms are: pull push admin -- they can be selectively enabled via the config\n"
71
+ )
72
+ end
73
+ end
74
+ end
75
+
76
+ describe '.permission_allowed?' do
77
+ before do
78
+ @perms = %w(pull push)
79
+ @conf_obj = double('Lita::Config', org_team_add_allowed_perms: @perms)
80
+ allow(github_org).to receive(:config).and_return(@conf_obj)
81
+ end
82
+
83
+ context 'always' do
84
+ it 'should validate perm against the config' do
85
+ expect(@perms).to receive(:include?).with('pull').and_call_original
86
+ github_org.send(:permission_allowed?, 'pull')
87
+ end
88
+ end
89
+
90
+ context 'when the permission is enabled' do
91
+ it 'should return true' do
92
+ expect(github_org.send(:permission_allowed?, 'pull')).to be_truthy
93
+ end
94
+ end
95
+
96
+ context 'when the permission is not enabled' do
97
+ it 'should return false' do
98
+ expect(github_org.send(:permission_allowed?, 'admin')).to be_falsey
99
+ end
100
+ end
101
+ end
102
+
103
+ ####
104
+ # Handlers
105
+ ####
29
106
  describe '.org_teams_list' do
30
107
  before do
31
108
  @teams = [
@@ -57,9 +134,119 @@ Name: HeckmanTest, Slug: heckmantest, ID: 42, Perms: push
57
134
  it 'should return a message indicating it could not find the organization' do
58
135
  send_command('gh teams GrapeDuty')
59
136
  expect(replies.last).to eql(
60
- "The organization 'GrapeDuty' was not found. Does my user have ownership permission?"
137
+ "The organization 'GrapeDuty' was not found. Does my user have ownership perms?"
61
138
  )
62
139
  end
63
140
  end
64
141
  end
142
+
143
+ describe '.org_team_add' do
144
+ before do
145
+ @team = { name: 'HeckmanTest', id: 42, slug: 'heckmantest', permission: 'pull' }
146
+ @octo_obj = double('Octokit::Client', create_team: @team)
147
+ @perms = %w(pull push)
148
+ @conf_obj = double('Lita::Config', org_team_add_allowed_perms: @perms)
149
+ allow(github_org).to receive(:config).and_return(@conf_obj)
150
+ allow(github_org).to receive(:func_disabled?).and_return(false)
151
+ allow(github_org).to receive(:octo).and_return(@octo_obj)
152
+ end
153
+
154
+ context 'when all goes well' do
155
+ it 'should return that the team was created' do
156
+ expect(@octo_obj).to receive(:create_team).with('GrapeDuty', name: 'HeckmanTest', permission: 'pull')
157
+ .and_return(@team)
158
+ send_command('gh org team add GrapeDuty name:"HeckmanTest" perms:pull')
159
+ expect(replies.last).to eql "The 'HeckmanTest' team was created; Slug: heckmantest, ID: 42, Perms: pull"
160
+ end
161
+ end
162
+
163
+ context 'when the method is disabled' do
164
+ before { allow(github_org).to receive(:func_disabled?).and_return(true) }
165
+
166
+ it 'should return the method disabled error' do
167
+ send_command('gh org team add GrapeDuty name:"HeckmanTest" perms:pull')
168
+ expect(replies.last).to eql 'Sorry, this function has either been disabled or not enabled in the config'
169
+ end
170
+ end
171
+
172
+ context 'when all the options are missing' do
173
+ it 'should respond with an error listing each one' do
174
+ send_command('gh org team add GrapeDuty')
175
+ expect(replies.last).to eql "Missing the name option
176
+ Missing the perms option
177
+ "
178
+ end
179
+ end
180
+
181
+ context 'when the permission level is not a known one' do
182
+ it 'should respond telling you the permission is unknown' do
183
+ send_command('gh org team add GrapeDuty name:testing perms:something')
184
+ expect(replies.last).to eql 'Valid perms are: pull push admin -- they can be ' \
185
+ "selectively enabled via the config\n"
186
+ end
187
+ end
188
+
189
+ context 'when the permission is now allowed in the config' do
190
+ it 'should respond informing you of the permitted permissions' do
191
+ send_command('gh org team add GrapeDuty name:testing perms:admin')
192
+ expect(replies.last).to eql 'Sorry, the permission level you requested was not allowed in the '\
193
+ 'config. Right now the only perms permitted are: pull, push'
194
+ end
195
+ end
196
+
197
+ context 'when the organization is not found' do
198
+ before { allow(@octo_obj).to receive(:create_team).and_raise(Octokit::NotFound.new) }
199
+
200
+ it 'should reply that the org was not found' do
201
+ send_command('gh org team add GrapeDuty name:testing perms:pull')
202
+ expect(replies.last).to eql "The organization 'GrapeDuty' was not found. Does my user have ownership perms?"
203
+ end
204
+ end
205
+ end
206
+
207
+ describe '.org_team_rm' do
208
+ before do
209
+ @team = { name: 'HeckmanTest', id: 42, slug: 'heckmantest', permission: 'pull' }
210
+ @octo_obj = double('Octokit::Client', delete_team: true)
211
+ allow(github_org).to receive(:config).and_return(@conf_obj)
212
+ allow(github_org).to receive(:func_disabled?).and_return(false)
213
+ allow(github_org).to receive(:octo).and_return(@octo_obj)
214
+ allow(github_org).to receive(:team?).with('42').and_return(@team)
215
+ end
216
+
217
+ context 'when all goes well' do
218
+ it 'should return the success message' do
219
+ send_command('gh org team rm GrapeDuty 42')
220
+ expect(replies.last).to eql "The 'HeckmanTest' team was deleted. Its ID was 42"
221
+ end
222
+ end
223
+
224
+ context 'when the method is disabled' do
225
+ before { allow(github_org).to receive(:func_disabled?).and_return(true) }
226
+
227
+ it 'should return the method disabled error' do
228
+ send_command('gh org team rm GrapeDuty 42')
229
+ expect(replies.last).to eql 'Sorry, this function has either been disabled or not enabled in the config'
230
+ end
231
+ end
232
+
233
+ context 'when the team does not exist' do
234
+ before { allow(github_org).to receive(:team?).with('42').and_return(false) }
235
+
236
+ it 'should respond with the team not found error' do
237
+ send_command('gh org team rm GrapeDuty 42')
238
+ expect(replies.last).to eql 'Unable to match any teams based on: 42'
239
+ end
240
+ end
241
+
242
+ context 'when deletion fails' do
243
+ before { allow(@octo_obj).to receive(:delete_team).and_return(false) }
244
+
245
+ it 'should respond with the action failure message' do
246
+ send_command('gh org team rm GrapeDuty 42')
247
+ expect(replies.last).to eql "Something went wrong trying to delete the 'HeckmanTest' " \
248
+ 'team. Is Github having issues?'
249
+ end
250
+ end
251
+ end
65
252
  end
@@ -152,29 +152,6 @@ describe Lita::Handlers::GithubRepo, lita_handler: true do
152
152
  end
153
153
  end
154
154
 
155
- describe '.team_id_by_slug' do
156
- before do
157
- @teams = [
158
- { id: 1, slug: 'hi' },
159
- { id: 42, slug: 'heckman' },
160
- { id: 84, slug: 'orwell' }
161
- ]
162
- @octo_obj = double('Octokit::Client', organization_teams: @teams)
163
- allow(github_repo).to receive(:octo).and_return(@octo_obj)
164
- end
165
-
166
- it 'should return the team id of the team matching the slug' do
167
- expect(@octo_obj).to receive(:organization_teams).with(github_org).and_return(@teams)
168
- expect(github_repo.send(:team_id_by_slug, 'heckman', github_org)).to eql 42
169
- expect(github_repo.send(:team_id_by_slug, 'orwell', github_org)).to eql 84
170
- expect(github_repo.send(:team_id_by_slug, 'unknown', github_org)).to be_nil
171
- end
172
-
173
- it 'should return nil if unknown' do
174
- expect(github_repo.send(:team_id_by_slug, 'unknown', 'x')).to be_nil
175
- end
176
- end
177
-
178
155
  describe '.extrapolate_create_opts' do
179
156
  before do
180
157
  @eco_opts = {}
@@ -268,17 +245,6 @@ describe Lita::Handlers::GithubRepo, lita_handler: true do
268
245
  end
269
246
  end
270
247
 
271
- describe '.command_opts' do
272
- it 'should find the valid options' do
273
- o = ' private:true team:heckman bacon:always bacon:sometimes'
274
- co = github_repo.send(:command_opts, o)
275
- expect(co).to be_an_instance_of Hash
276
- expect(co[:private]).to eql 'true'
277
- expect(co[:team]).to eql 'heckman'
278
- expect(co[:bacon]).to eql 'always' # of course it's always
279
- end
280
- end
281
-
282
248
  describe '.create_repo' do
283
249
  before do
284
250
  allow(github_repo).to receive(:octo).and_return(double('Octokit::Client', create_repository: nil))
@@ -60,6 +60,18 @@ describe Lita::Handlers::Github, lita_handler: true do
60
60
  it 'should enable Lita::Handlers::GithubPR.pr_merge by default' do
61
61
  expect(Lita.config.handlers.github.pr_merge_enabled).to be_truthy
62
62
  end
63
+
64
+ it 'should disable Lita::Handlers::GithubOrg.org_team_add by default' do
65
+ expect(Lita.config.handlers.github.org_team_add_enabled).to be_falsey
66
+ end
67
+
68
+ it 'should disable Lita::Handlers::GithubOrg.org_team_rm by default' do
69
+ expect(Lita.config.handlers.github.org_team_rm_enabled).to be_falsey
70
+ end
71
+
72
+ it 'should allow only teams with "pull" permissions to be created by default' do
73
+ expect(Lita.config.handlers.github.org_team_add_allowed_perms).to eql %w(pull)
74
+ end
63
75
  end
64
76
 
65
77
  describe '.status' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lita-github
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
4
+ version: 0.0.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Heckman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-13 00:00:00.000000000 Z
11
+ date: 2014-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -120,6 +120,20 @@ dependencies:
120
120
  - - ">="
121
121
  - !ruby/object:Gem::Version
122
122
  version: 0.4.0
123
+ - !ruby/object:Gem::Dependency
124
+ name: yard
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - "~>"
128
+ - !ruby/object:Gem::Version
129
+ version: 0.8.7
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: 0.8.7
123
137
  - !ruby/object:Gem::Dependency
124
138
  name: lita
125
139
  requirement: !ruby/object:Gem::Requirement
@@ -194,6 +208,7 @@ files:
194
208
  - lib/lita-github.rb
195
209
  - lib/lita-github/config.rb
196
210
  - lib/lita-github/filters.rb
211
+ - lib/lita-github/general.rb
197
212
  - lib/lita-github/octo.rb
198
213
  - lib/lita-github/org.rb
199
214
  - lib/lita-github/r.rb
@@ -208,6 +223,7 @@ files:
208
223
  - spec/spec_helper.rb
209
224
  - spec/unit/lita-github/config_spec.rb
210
225
  - spec/unit/lita-github/filters_spec.rb
226
+ - spec/unit/lita-github/general_spec.rb
211
227
  - spec/unit/lita-github/octo_spec.rb
212
228
  - spec/unit/lita-github/org_spec.rb
213
229
  - spec/unit/lita-github/r_spec.rb
@@ -247,6 +263,7 @@ test_files:
247
263
  - spec/spec_helper.rb
248
264
  - spec/unit/lita-github/config_spec.rb
249
265
  - spec/unit/lita-github/filters_spec.rb
266
+ - spec/unit/lita-github/general_spec.rb
250
267
  - spec/unit/lita-github/octo_spec.rb
251
268
  - spec/unit/lita-github/org_spec.rb
252
269
  - spec/unit/lita-github/r_spec.rb