peoplegroup-connectors 0.1.5 → 0.1.11

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a7daab0b3d624677382171608419d46c06ac97245d7590105ecd75538ed7a1ff
4
- data.tar.gz: 0d569ecd15cb4aba65dec278b785bc8f3fe4904d5083ff28d6ed7d12e5f2c4dd
3
+ metadata.gz: 2193145f0bfa0c5e69c282db2c6d3c6d61c98c5ddf97f6a5adf50e9d3041c932
4
+ data.tar.gz: 06c04625b87ce7653df20a404a7bd8dd0c696516f6aa24523542985ad06373b5
5
5
  SHA512:
6
- metadata.gz: 878ac4e1352046ef512d388024cbb79e6cf56085916aaf544b789e32eb71e526ea7453d6702a6dbc895ec68056621d8f41c6a719eb0374bf18ce8a07bc6f0045
7
- data.tar.gz: fdd8026563f694852891e44f30f9634fee7ecf4b0623bf574e04c47def55d61dbed4c1cf1c2f9e8d12e3ba19c6d4a38410193a0d002e71f0f97770ccb8ba525c
6
+ metadata.gz: 237ba92529a93da4c53b20ec134545f7873b8d677c7a33d36ab009b9e21b49316de6e51a27cac18f408619db59d4b006037cbeced4ec8aad229c1b4ba5f695f4
7
+ data.tar.gz: fc4b1ef1b8dd1271ea1c61fd164f673a444fe8dc27966925d9f320cc09e06b521316bdaba26d8d5dc557b02555ea46f1535fef985350f82ff474ec1b85cdc76b
data/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # PeopleGroup::Connectors
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/peoplegroup/connectors`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ The gem contains wrapper code for all the services we sync with. The reason we bundled this in a separate gem is to not have duplicate code in our different projects.
6
4
 
7
5
  ## Installation
8
6
 
@@ -22,7 +20,10 @@ Or install it yourself as:
22
20
 
23
21
  ## Usage
24
22
 
25
- TODO: Write usage instructions here
23
+ ```ruby
24
+ gitlab_client = PeopleGroup::Connectors::GitLab.new
25
+ gitlab_client.find_gitlabber(:email, 'some-email@domain.com')
26
+ ```
26
27
 
27
28
  ## Development
28
29
 
@@ -2,6 +2,10 @@
2
2
 
3
3
  require_relative 'connectors/version'
4
4
  require_relative 'connectors/gitlab'
5
+ require_relative 'connectors/slack'
6
+ require_relative 'connectors/pto_roots'
7
+ require_relative 'connectors/bamboo'
8
+ require_relative 'connectors/greenhouse'
5
9
 
6
10
  module PeopleGroup
7
11
  module Connectors
@@ -0,0 +1,174 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bamboozled'
4
+
5
+ module PeopleGroup
6
+ module Connectors
7
+ class Bamboo
8
+ MAX_RETRIES = 3
9
+
10
+ def initialize
11
+ @client = Bamboozled.client(subdomain: 'gitlab', api_key: ENV['BAMBOO_API_KEY'])
12
+ end
13
+
14
+ def get_employee_details(id)
15
+ employees.find { |emp| emp['id'] == id.to_s }
16
+ end
17
+
18
+ def get_employee(id)
19
+ @client.employee.find(id, %w[firstName lastName jobTitle supervisor hireDate country location department division workEmail customCostCenter])
20
+ end
21
+
22
+ def search_employee(name)
23
+ return if name.empty?
24
+
25
+ employees.find do |emp|
26
+ [
27
+ emp['displayName']&.downcase,
28
+ "#{emp['firstName']&.downcase} #{emp['lastName']&.downcase}",
29
+ "#{emp['preferredName']&.downcase} #{emp['lastName']&.downcase}",
30
+ "#{emp['firstName']&.downcase} #{emp['customPreferredLastName']&.downcase}",
31
+ "#{emp['preferredName']&.downcase} #{emp['customPreferredLastName']&.downcase}"
32
+ ].include?(name.downcase)
33
+ end
34
+ end
35
+ alias_method :search_team_member, :search_employee
36
+
37
+ def search_employee_by_field(field:, value:)
38
+ employees.find { |employee| employee[field] == value.to_s }
39
+ end
40
+
41
+ def fetch_manager(team_member)
42
+ active_team_members.find { |tm| tm['id'] == team_member['supervisorEId'] }
43
+ end
44
+
45
+ def fetch_second_level_manager(team_member)
46
+ fetch_manager(fetch_manager(team_member))
47
+ end
48
+
49
+ def create_employee(employee_details_hash)
50
+ @client.employee.add(employee_details_hash)
51
+ end
52
+
53
+ def update_employee(employee_id, employee_details_hash)
54
+ @client.employee.update(employee_id, employee_details_hash)
55
+ end
56
+
57
+ def departments
58
+ meta_fields.detect { |res| res['name'] == 'Department' }.dig('options').each_with_object([]) { |option, array| array << option['name'] if option['archived'] == 'no' } || []
59
+ end
60
+
61
+ def divisions
62
+ meta_fields.detect { |res| res['name'] == 'Division' }.dig('options').each_with_object([]) { |option, array| array << option['name'] if option['archived'] == 'no' } || []
63
+ end
64
+
65
+ def fields
66
+ @fields ||= (Bamboozled::API::FieldCollection.all_names + @client.meta.fields.map { |f| f['alias'] }).compact.uniq
67
+ end
68
+
69
+ def employees
70
+ retries = 0
71
+
72
+ begin
73
+ @employees ||= @client.report.custom(fields, 'JSON').reject { |employee| employee['lastName'] == 'Test-Gitlab' }
74
+ rescue Net::ReadTimeout
75
+ retry if (retries += 1) < MAX_RETRIES
76
+ end
77
+ end
78
+
79
+ def active_employees
80
+ employees.select { |employee| employee['status'] == 'Active' }
81
+ end
82
+ alias_method :active_team_members, :active_employees
83
+
84
+ def add_stock_options(employee_id, data)
85
+ @client.employee.add_table_row(employee_id, 'customEquity', data)
86
+ end
87
+
88
+ def stock_options_data(employee_id)
89
+ @client.employee.table_data(employee_id, 'customEquity')
90
+ end
91
+
92
+ def update_job_details(employee_id, data)
93
+ current_data = job_details(employee_id) # it should only be one row as we just created this user
94
+ row_id = current_data.first.dig('id')
95
+ @client.employee.update_table_row(employee_id, 'jobInfo', row_id, data)
96
+ end
97
+
98
+ def add_compensation_details(employee_id, data)
99
+ @client.employee.add_table_row(employee_id, 'compensation', data)
100
+ end
101
+
102
+ def employment_statuses(employee_id)
103
+ @client.employee.table_data(employee_id, 'employmentStatus')
104
+ end
105
+
106
+ def job_details(employee_id)
107
+ @client.employee.table_data(employee_id, 'jobInfo')
108
+ end
109
+
110
+ def resumes_folder_id(employee_id)
111
+ @resumes_folder_id ||= files(employee_id).dig('categories').find { |folder| folder['name'] == 'Resumes and Applications' }.dig('id')
112
+ end
113
+
114
+ def contract_folder_id(employee_id)
115
+ @contract_folder_id ||= files(employee_id).dig('categories').find { |folder| folder['name'] == 'Contracts & Changes' }.dig('id')
116
+ end
117
+
118
+ def add_file(employee_id, file_name, file, folder_id)
119
+ options = {
120
+ category: folder_id,
121
+ fileName: file_name,
122
+ share: 'yes',
123
+ file: file
124
+ }
125
+ @client.employee.add_file(employee_id, options)
126
+ end
127
+
128
+ def add_employment_status(employee_id, data)
129
+ @client.employee.add_table_row(employee_id, 'employmentStatus', data)
130
+ end
131
+
132
+ def add_currency_conversion(employee_id, data)
133
+ @client.employee.add_table_row(employee_id, 'customCurrencyConversion', data)
134
+ end
135
+
136
+ def add_on_target_earnings(employee_id, data)
137
+ @client.employee.add_table_row(employee_id, 'customOnTargetEarnings', data)
138
+ end
139
+
140
+ def add_signing_bonus(employee_id, data)
141
+ @client.employee.add_table_row(employee_id, 'customBonus', data)
142
+ end
143
+
144
+ def add_family_member(employee_id, data)
145
+ @client.employee.add_table_row(employee_id, 'customFamilyMember', data)
146
+ end
147
+
148
+ def add_additional_data(employee_id, data)
149
+ @client.employee.add_table_row(employee_id, 'customAdditionalInformation1', data)
150
+ end
151
+
152
+ def add_bonus(team_member_id, comment)
153
+ data = {
154
+ customBonusdate: Date.today.to_s,
155
+ customBonusamount: { value: 1_000, currency: 'USD' },
156
+ customBonustype: 'Discretionary Bonus',
157
+ customBonuscomments: comment
158
+ # customNominatedBy: 'TODO'
159
+ }
160
+ @client.employee.add_table_row(team_member_id, 'customBonus', data)
161
+ end
162
+
163
+ private
164
+
165
+ def meta_fields
166
+ @meta_fields ||= @client.meta.lists
167
+ end
168
+
169
+ def files(employee_id)
170
+ @files ||= @client.employee.files(employee_id)
171
+ end
172
+ end
173
+ end
174
+ end
@@ -45,7 +45,25 @@ module PeopleGroup
45
45
  epic || @client.create_epic(group_id, title, options)
46
46
  end
47
47
 
48
- def commit_change_to_new_merge_request_v2(project_id, branch_name, commit_message, description = '', files_to_delete = [], files_to_update = [])
48
+ def commit_new_files_to_new_merge_request(project_id, branch_name, new_files, commit_message, description = nil)
49
+ @client.create_branch(project_id, branch_name, 'master')
50
+ actions = []
51
+ new_files.each do |file|
52
+ actions << {
53
+ action: 'create',
54
+ file_path: file.sub('tmp', '/data/team_members'),
55
+ content: File.read(file)
56
+ }
57
+ end
58
+
59
+ @client.create_commit(project_id, branch_name, commit_message, actions)
60
+
61
+ options = { source_branch: branch_name, target_branch: 'master', remove_source_branch: true }
62
+ options[:description] = description if description
63
+ @client.create_merge_request(project_id, commit_message, options)
64
+ end
65
+
66
+ def commit_change_to_new_merge_request_v2(project_id, branch_name, commit_message, description = nil, files_to_delete = [], files_to_update = [])
49
67
  actions = []
50
68
 
51
69
  files_to_delete.each do |file|
@@ -71,7 +89,7 @@ module PeopleGroup
71
89
  @client.create_commit(project_id, branch_name, commit_message, actions)
72
90
 
73
91
  options = { source_branch: branch_name, target_branch: 'master', remove_source_branch: true }
74
- options[:description] = description if description.present?
92
+ options[:description] = description if description
75
93
  @client.create_merge_request(project_id, commit_message, options)
76
94
  end
77
95
 
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'greenhouse_io'
4
+
5
+ module PeopleGroup
6
+ module Connectors
7
+ class Greenhouse
8
+ MAX_RETRIES = 3
9
+
10
+ def initialize(use_users_api_key: false)
11
+ api_key = use_users_api_key ? ENV['GREENHOUSE_API_KEY_USERS'] : ENV['GREENHOUSE_API_KEY']
12
+ @client = GreenhouseIo::Client.new(api_key)
13
+ end
14
+
15
+ def offer_for_application(application_id)
16
+ @client.offers_for_application(application_id)
17
+ end
18
+
19
+ def hired_candidates(updated_since)
20
+ page = 1
21
+ candidates = []
22
+ retries = 0
23
+
24
+ loop do
25
+ begin
26
+ results = @client.candidates(nil, updated_after: updated_since, page: page)
27
+ break if results.empty?
28
+
29
+ results.each do |candidate|
30
+ candidates << candidate if hired_non_active?(candidate)
31
+ end
32
+ rescue GreenhouseIo::Error
33
+ p [updated_since, page]
34
+ retry if (retries += 1) < MAX_RETRIES
35
+ end
36
+ page += 1
37
+ end
38
+
39
+ candidates
40
+ end
41
+
42
+ def candidate(candidate_id)
43
+ @client.candidates(candidate_id)
44
+ end
45
+
46
+ def add_sync_note_to_candidate(candidate_id)
47
+ note = {
48
+ user_id: ENV['GREENHOUSE_AUTHOR_ID'],
49
+ body: "This person was synced at #{Time.now} by the Employee Bot",
50
+ visibility: 'public'
51
+ }
52
+ @client.create_candidate_note(candidate_id, note, ENV['GREENHOUSE_AUTHOR_ID'])
53
+ end
54
+
55
+ def users
56
+ page = 1
57
+ users = []
58
+
59
+ loop do
60
+ results = @client.users(nil, page: page)
61
+ break if results.empty?
62
+
63
+ users += results
64
+ page += 1
65
+ end
66
+
67
+ users
68
+ end
69
+
70
+ private
71
+
72
+ def hired_non_active?(candidate)
73
+ # If the candidate has any application that is active, we don't sync.
74
+ return false if candidate['applications'].any? { |application| application['status'] == 'active' }
75
+
76
+ # Check if candidate is hired for just one of their applications
77
+ candidate['applications'].one? { |application| application['status'] == 'hired' }
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'splinter'
4
+
5
+ module PeopleGroup
6
+ module Connectors
7
+ class PTORoots
8
+ def initialize
9
+ ::Splinter.configure do |config|
10
+ config.api_key = ENV['PTO_ROOTS_API_KEY']
11
+ end
12
+ end
13
+
14
+ def pto(params)
15
+ Splinter::OOOEvents.get_all(params)
16
+ end
17
+
18
+ def pto_type(type)
19
+ pto_types.find { |pto_type| pto_type['name'] == type }
20
+ end
21
+
22
+ private
23
+
24
+ def pto_types
25
+ Splinter::OOOTypes.get_all
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'slack-ruby-client'
4
+
5
+ module PeopleGroup
6
+ module Connectors
7
+ class Slack
8
+ def initialize
9
+ ::Slack.configure do |config|
10
+ config.token = ENV['SLACK_API_TOKEN']
11
+ end
12
+ @client = ::Slack::Web::Client.new
13
+ end
14
+
15
+ def find_user(email)
16
+ @client.users_lookupByEmail(email: email)
17
+ rescue ::Slack::Web::Api::Errors::SlackError
18
+ nil
19
+ end
20
+
21
+ def list_public_channels
22
+ channels = @client.channels_list(exclude_archived: true).channels
23
+ channels.reject(&:is_private)&.map(:name)
24
+ end
25
+
26
+ def send_message(channel:, text:, as_user: true, attachments: [])
27
+ @client.chat_postMessage(channel: channel, text: text, as_user: true, attachments: attachments, unfurl_links: false)
28
+ end
29
+
30
+ def update_message(channel:, timestamp:, text:)
31
+ @client.chat_update(channel: channel, text: text, ts: timestamp, as_user: true, attachments: [])
32
+ end
33
+
34
+ def send_modal_message(trigger:, view:)
35
+ @client.views_open(trigger_id: trigger, view: view)
36
+ end
37
+
38
+ def publish_view(user_id:, trigger:, view:)
39
+ @client.views_publish(user_id: user_id, trigger_id: trigger, view: view)
40
+ end
41
+ end
42
+ end
43
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module PeopleGroup
4
4
  module Connectors
5
- VERSION = '0.1.5'
5
+ VERSION = '0.1.11'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: peoplegroup-connectors
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - lien van den steen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-01 00:00:00.000000000 Z
11
+ date: 2021-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gitlab
@@ -24,6 +24,62 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: slack-ruby-client
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.14'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.14'
41
+ - !ruby/object:Gem::Dependency
42
+ name: splinter-pto
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bamboozled-gitlab
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.2.9
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.2.9
69
+ - !ruby/object:Gem::Dependency
70
+ name: greenhouse_io-gitlab
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.5'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.5'
27
83
  - !ruby/object:Gem::Dependency
28
84
  name: rspec
29
85
  requirement: !ruby/object:Gem::Requirement
@@ -44,14 +100,28 @@ dependencies:
44
100
  requirements:
45
101
  - - "~>"
46
102
  - !ruby/object:Gem::Version
47
- version: '0.85'
103
+ version: 0.91.1
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 0.91.1
111
+ - !ruby/object:Gem::Dependency
112
+ name: gitlab-styles
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '6.0'
48
118
  type: :development
49
119
  prerelease: false
50
120
  version_requirements: !ruby/object:Gem::Requirement
51
121
  requirements:
52
122
  - - "~>"
53
123
  - !ruby/object:Gem::Version
54
- version: '0.85'
124
+ version: '6.0'
55
125
  - !ruby/object:Gem::Dependency
56
126
  name: rubocop-packaging
57
127
  requirement: !ruby/object:Gem::Requirement
@@ -90,9 +160,12 @@ files:
90
160
  - LICENSE.txt
91
161
  - README.md
92
162
  - lib/peoplegroup/connectors.rb
163
+ - lib/peoplegroup/connectors/bamboo.rb
93
164
  - lib/peoplegroup/connectors/gitlab.rb
165
+ - lib/peoplegroup/connectors/greenhouse.rb
166
+ - lib/peoplegroup/connectors/pto_roots.rb
167
+ - lib/peoplegroup/connectors/slack.rb
94
168
  - lib/peoplegroup/connectors/version.rb
95
- - lib/peoplegroup_connectors.rb
96
169
  homepage: https://gitlab.com/gitlab-com/people-group/peopleops-eng/connectors-gem
97
170
  licenses:
98
171
  - MIT
@@ -1,10 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'peoplegroup/connectors/version'
4
- require_relative 'peoplegroup/connectors/gitlab'
5
-
6
- module PeopleGroup
7
- module Connectors
8
- class Error < StandardError; end
9
- end
10
- end