codebuild-notifier 1.0.0 → 1.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c165c9da8f00e25f828f0eb5839011c2e28f517289429999a56571c431c766cb
4
- data.tar.gz: 5b9da99ae167f4ed3e3ce49db33b1f95b738820f5ac9acbacc8c416dd2cec2a9
3
+ metadata.gz: db502c3440f34e43f24cc73e679a7fe3d937eb50c1989244799bf713560318cf
4
+ data.tar.gz: a91c267131b3dbac305f3ecf2a955e7a76050d90f59e8c945640a892b06d1fe4
5
5
  SHA512:
6
- metadata.gz: 9d19c47a78c414223965f09c4221c383aca9faee389b35ec3c924d8603a3ae00076ac9c8b1e9bdae2a01233c46f40facf0076229f5498c4c020ea33e67b8f55d
7
- data.tar.gz: d4d63e87575aa32907807cd0157df12da2b60fb6c812bdeca407fb2c6306d34dd2be23ae8f361eab4dcf0879ace21d40711fc75378fee2cdaa34a867a34190e5
6
+ metadata.gz: 3ef7b68705218fcdbee22f06d72121f6a8340b8aee7ba6346982899d175608ec0f29603d4e37ce93999a25bfd5ab5440ba64e902004737f17931a6d21399452c
7
+ data.tar.gz: ef31c8ab2dbb9b3cdc566af9edb12dd116f00dc966881b20b95588ecc5c890e3d7534faa982beba97fa04b006bd7cdec5c1f23efdab91689d42ad762d7bb8399
data/README.md CHANGED
@@ -1,11 +1,11 @@
1
1
  # codebuild-notifier
2
- Reports status of AWS CodeBuild CI jobs to slack.
2
+ Reports status of AWS CodeBuild CI jobs to Slack.
3
3
 
4
4
  # Infrastructure Requirements
5
5
 
6
6
  ### Slack App or Bot in your workspace
7
7
 
8
- Notifications will be sent as slack Direct Messages to users from the default
8
+ Notifications will be sent as Slack Direct Messages to users from the default
9
9
  Slack bot in your workspace (e.g. @slackbot)
10
10
  - Go to <a href="https://api.slack.com/apps">https://api.slack.com/apps</a>
11
11
  - Create a New App, e.g. App Name: CodeBuild Notifier
@@ -24,7 +24,7 @@ will come from a user with a name you choose, e.g. CodeBuildBot
24
24
  - A new OAuth token will be generated specific to the Bot User. Store this in
25
25
  AWS Secrets Manager instead of the App token.
26
26
 
27
- ### DynamoDB table
27
+ ### DynamoDB table for build history
28
28
  - expected to be named 'codebuild-history', but can be configured
29
29
  - the following definition:
30
30
 
@@ -57,6 +57,39 @@ AWS Secrets Manager instead of the App token.
57
57
  { "token": "xoxo-your-slack-app-token" }
58
58
  ```
59
59
 
60
+ ### Optional DynamoDB table for Slack aliases
61
+
62
+ Slack message recipients are located by extracting the email address of the
63
+ author/commiter of the git commit triggering the build, then searching
64
+ for users with that email address within the Slack workspace.
65
+
66
+ Users might sign commits with a different email address than they used
67
+ to register with Slack. Even if their git config has a matching address,
68
+ merges and commits made via the github web interface may use the primary
69
+ email address for the user's github account, or username@noreply.github.com.
70
+
71
+ To ensure delivery in these cases, a second DynamoDb table can be created
72
+ and configured to do a second lookup if the original lookup fails.
73
+
74
+ - suggested table name: 'codebuild-slack-aliases', but can be configured
75
+ - by default, the table name is unspecified, meaning no second lookup will
76
+ be performed
77
+ - the email address for which the original lookup fails (the commit
78
+ signature address) should be stored in index field `alternate_email`
79
+ - the user's Slack email address should be stored in a string field
80
+ named `workspace_email`
81
+ - multiple items can be created with different values for `alternate_email`
82
+ pointing to the same `workspace_email` value
83
+ - the table should have the following definition:
84
+ ```ruby
85
+ AttributeDefinitions [
86
+ { AttributeName: 'alternate_email', AttributeType: 'S' }
87
+ ]
88
+ KeySchema [
89
+ { AttributeName: 'alternate_email', KeyType: 'HASH' }
90
+ ]
91
+ ```
92
+
60
93
  ### IAM Service Role for CodeBuild projects
61
94
 
62
95
  You will likely already have a service role granting CloudWatch access, to
@@ -76,7 +109,10 @@ name:
76
109
  "Effect": "Allow",
77
110
  "Resource": [
78
111
  "arn:aws:dynamodb:<your-region>:<your-account-id>:table/codebuild-history",
79
- "arn:aws:dynamodb:<your-region>:<your-account-id>:table/codbuild-history/*"
112
+ "arn:aws:dynamodb:<your-region>:<your-account-id>:table/codbuild-history/*",
113
+ // if optional slack alias table is configured
114
+ "arn:aws:dynamodb:<your-region>:<your-account-id>:table/codebuild-slack-aliases",
115
+ "arn:aws:dynamodb:<your-region>:<your-account-id>:table/codbuild-slack-aliases/*"
80
116
  ]
81
117
  },
82
118
  {
@@ -88,6 +124,7 @@ name:
88
124
  }
89
125
  ```
90
126
 
127
+
91
128
  # Configuration
92
129
 
93
130
  ## Installation
@@ -261,13 +298,30 @@ phases:
261
298
  not set
262
299
  </td>
263
300
  <td>
264
- If no slack user can be found in your workspace with the email
301
+ If no Slack user can be found in your workspace with the email
265
302
  address of the author or committer of a commit, a message will be
266
- sent to the slack usernames specified.<br />
303
+ sent to the Slack usernames specified.<br />
267
304
  Separate multiple values with commas, with no spaces.<br />
268
305
  e.g. fred,velma
269
306
  </td>
270
307
  </tr>
308
+ <tr>
309
+ <th>
310
+ CBN_SLACK_ALIAS_TABLE
311
+ </th>
312
+ <td>
313
+ <nobr>--slack-alias-table</nobr>
314
+ </td>
315
+ <td>
316
+ not set
317
+ </td>
318
+ <td>
319
+ If no Slack user can be found in your workspace with the email
320
+ address of the author or committer of a commit, this table will
321
+ be queried to find the Slack workspace email matching the failed
322
+ address.
323
+ </td>
324
+ </tr>
271
325
  <tr>
272
326
  <th>
273
327
  CBN_SLACK_SECRET_NAME
@@ -98,6 +98,16 @@ OptionParser.new do |opts|
98
98
  command_line_opts[:slack_admin_users] = usernames
99
99
  end
100
100
 
101
+ opts.on(
102
+ '--slack-alias-table=TABLE',
103
+ 'optional dynamodb table for storing alternate email addresses for when ' \
104
+ 'the commit author email is different from the address associated with ' \
105
+ 'their slack account; can also help with failed lookups for ' \
106
+ 'someuser@noreply.github.com'
107
+ ) do |table|
108
+ command_line_opts[:slack_alias_table] = table
109
+ end
110
+
101
111
  opts.on(
102
112
  '--slack-secret-name=SECRET',
103
113
  'name of Secrets Manager secret with slack app/bot auth token'
@@ -15,12 +15,15 @@
15
15
  # You should have received a copy of the GNU General Public License
16
16
  # along with codebuild-notifier. If not, see <http://www.gnu.org/licenses/>.
17
17
 
18
+ require 'aws-sdk-dynamodb'
19
+
18
20
  module CodeBuildNotifier
19
21
  class Config
20
- DEFAULT_WHITELIST = %w[master]
22
+ DEFAULT_WHITELIST = %w[master].freeze
21
23
 
22
- attr_reader :additional_channel, :default_strategy, :dynamo_table, :region,
23
- :slack_admins, :slack_secret_name, :whitelist_branches
24
+ attr_reader :additional_channel, :default_strategy, :dynamo_table,
25
+ :region, :slack_admins, :slack_alias_table,
26
+ :slack_secret_name, :whitelist_branches
24
27
 
25
28
  # Configuration values specific to CodeBuild Notifier. CBN_ prefix is
26
29
  # used because ENV vars with CODEBUILD_ prefix are reserved for use by AWS.
@@ -30,6 +33,7 @@ module CodeBuildNotifier
30
33
  dynamo_table: ENV['CBN_DYNAMO_TABLE'] || 'codebuild-history',
31
34
  region: ENV['CBN_AWS_REGION'] || ENV['AWS_REGION'],
32
35
  slack_admins: ENV['CBN_SLACK_ADMIN_USERNAMES'],
36
+ slack_alias_table: ENV['CBN_SLACK_ALIAS_TABLE'],
33
37
  slack_secret_name: ENV['CBN_SLACK_SECRET_NAME'] || 'slack/codebuild',
34
38
  strategy_overrides: ENV['CBN_OVERRIDE_NOTIFY_STRATEGY'],
35
39
  whitelist_branches: ENV['CBN_WHITELIST_BRANCHES']
@@ -39,11 +43,16 @@ module CodeBuildNotifier
39
43
  @dynamo_table = dynamo_table
40
44
  @region = region
41
45
  @slack_admins = slack_admins&.split(',') || []
46
+ @slack_alias_table = slack_alias_table
42
47
  @slack_secret_name = slack_secret_name
43
48
  @strategy_overrides = strategy_overrides&.split(',') || []
44
49
  @whitelist_branches = whitelist_branches&.split(',') || DEFAULT_WHITELIST
45
50
  end
46
51
 
52
+ def dynamo_client
53
+ @dynamo_client || Aws::DynamoDB::Client.new(region: region)
54
+ end
55
+
47
56
  def strategy_for_branch(branch_name)
48
57
  lookup = @strategy_overrides.map { |override| override.split(':') }.to_h
49
58
  lookup.fetch(branch_name, default_strategy)
@@ -17,14 +17,13 @@
17
17
 
18
18
  require 'active_support'
19
19
  require 'active_support/core_ext'
20
- require 'aws-sdk-dynamodb'
21
20
  require 'hashie'
22
21
 
23
22
  module CodeBuildNotifier
24
23
  class DynamoBase
25
24
  attr_reader :config, :current_build
26
25
 
27
- delegate :dynamo_table, to: :config
26
+ delegate :dynamo_client, :dynamo_table, to: :config
28
27
 
29
28
  def initialize(config, build)
30
29
  @config = config
@@ -37,10 +36,6 @@ module CodeBuildNotifier
37
36
  )
38
37
  end
39
38
 
40
- private def dynamo_client
41
- @dynamo_client || Aws::DynamoDB::Client.new(region: config.region)
42
- end
43
-
44
39
  private def hash_to_dynamo_update(hash)
45
40
  update = hash.each_with_object(
46
41
  expression_attribute_names: {},
@@ -34,10 +34,8 @@ module CodeBuildNotifier
34
34
  post_message(message, channel)
35
35
  end
36
36
 
37
- message.recipients.each do |email|
38
- slack_user_id = find_slack_user(email)
39
- slack_user_id && post_message(message, slack_user_id)
40
- end
37
+ user_ids = message.recipients.map { |email| find_slack_user(email)&.id }
38
+ user_ids.uniq.compact.each { |user_id| post_message(message, user_id) }
41
39
  end
42
40
 
43
41
  private def post_message(message, channel)
@@ -60,14 +58,29 @@ module CodeBuildNotifier
60
58
  end
61
59
 
62
60
  private def find_slack_user(email)
63
- lookup_response = slack_client.users_lookupByEmail(email: email)
64
- lookup_response.user.id
61
+ slack_client.users_lookupByEmail(email: email)&.user
65
62
  rescue Slack::Web::Api::Errors::SlackError => e
63
+ alias_email = find_alias(email)
64
+ if alias_email
65
+ find_slack_user(alias_email)
66
+ else
67
+ report_lookup_failure(email, e.message)
68
+ nil
69
+ end
70
+ end
71
+
72
+ private def report_lookup_failure(email, error_message)
66
73
  admin_send(
67
74
  "Slack user lookup by email for #{email} failed with " \
68
- "error: #{e.message}"
75
+ "error: #{error_message}"
69
76
  )
70
- nil
77
+ end
78
+
79
+ def find_alias(email)
80
+ config.slack_alias_table && config.dynamo_client.get_item(
81
+ table_name: config.slack_alias_table,
82
+ key: { 'alternate_email' => email }
83
+ ).item&.fetch('workspace_email')
71
84
  end
72
85
 
73
86
  # If the app token starts with xoxb- then it is a Bot User Oauth token
@@ -16,5 +16,5 @@
16
16
  # along with codebuild-notifier. If not, see <http://www.gnu.org/licenses/>.
17
17
 
18
18
  module CodeBuildNotifier
19
- VERSION = '1.0.0'.freeze
19
+ VERSION = '1.1.0'.freeze
20
20
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: codebuild-notifier
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - VHL Ops Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-19 00:00:00.000000000 Z
11
+ date: 2019-05-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport