codebuild-notifier 0.3.2 → 1.0.0

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: 89562832b7f9855d266d8b5bee997da127a0922999f430ea2e8fe08a83bd7927
4
- data.tar.gz: 34068cc500952416033eaa8f3bd8c5ab77b7804078557c53f99e7bdf913a2cd7
3
+ metadata.gz: c165c9da8f00e25f828f0eb5839011c2e28f517289429999a56571c431c766cb
4
+ data.tar.gz: 5b9da99ae167f4ed3e3ce49db33b1f95b738820f5ac9acbacc8c416dd2cec2a9
5
5
  SHA512:
6
- metadata.gz: '01780be2887fd4d76f86700396357d35c4ff26ebb45e683bd3bd7ad17b2ed53320fe5950a26cee11df8086d1779b6f1b54225364438eb9addbc7d71c911e416a'
7
- data.tar.gz: e4e1f33261168a7f71666560bdd2d9f7cf12cd698c35cb3690a54d8f3955e00cacea716457f9b6082942ad9052a92c635484752f8fc0c858997d778fd643c768
6
+ metadata.gz: 9d19c47a78c414223965f09c4221c383aca9faee389b35ec3c924d8603a3ae00076ac9c8b1e9bdae2a01233c46f40facf0076229f5498c4c020ea33e67b8f55d
7
+ data.tar.gz: d4d63e87575aa32907807cd0157df12da2b60fb6c812bdeca407fb2c6306d34dd2be23ae8f361eab4dcf0879ace21d40711fc75378fee2cdaa34a867a34190e5
data/README.md CHANGED
@@ -25,25 +25,28 @@ will come from a user with a name you choose, e.g. CodeBuildBot
25
25
  AWS Secrets Manager instead of the App token.
26
26
 
27
27
  ### DynamoDB table
28
- - expected to be named 'branch-build-status', but can be configured
28
+ - expected to be named 'codebuild-history', but can be configured
29
29
  - the following definition:
30
30
 
31
31
  ```ruby
32
32
  AttributeDefinitions [
33
+ { AttributeName: 'commit_hash', AttributeType: 'S' },
33
34
  { AttributeName: 'source_id', AttributeType: 'S' },
34
- { AttributeName: 'commit_hash', AttributeType: 'S' }
35
+ { AttributeName: 'version_key', AttributeType: 'S' }
35
36
  ]
36
37
  GlobalSecondaryIndexes [
37
38
  {
38
39
  IndexName: 'commit_hash_index',
39
40
  KeySchema: [
40
- { AttributeName: 'commit_hash', KeyType: 'HASH' }
41
+ { AttributeName: 'commit_hash', KeyType: 'HASH' },
42
+ { AttributeName: 'version_key', KeyType: 'RANGE' }
41
43
  ],
42
- Projection: { ProjectionType: 'ALL' },
44
+ Projection: { ProjectionType: 'ALL' }
43
45
  }
44
46
  ]
45
47
  KeySchema [
46
- { AttributeName: 'source_id', KeyType: 'HASH' }
48
+ { AttributeName: 'source_id', KeyType: 'HASH' },
49
+ { AttributeName: 'version_key', KeyType: 'RANGE' }
47
50
  ]
48
51
  ```
49
52
 
@@ -72,8 +75,8 @@ name:
72
75
  ],
73
76
  "Effect": "Allow",
74
77
  "Resource": [
75
- "arn:aws:dynamodb:<your-region>:<your-account-id>:table/branch-build-status",
76
- "arn:aws:dynamodb:<your-region>:<your-account-id>:table/branch-build-status/*"
78
+ "arn:aws:dynamodb:<your-region>:<your-account-id>:table/codebuild-history",
79
+ "arn:aws:dynamodb:<your-region>:<your-account-id>:table/codbuild-history/*"
77
80
  ]
78
81
  },
79
82
  {
@@ -221,7 +224,7 @@ phases:
221
224
  <nobr>--dynamo-table</nobr>
222
225
  </td>
223
226
  <td>
224
- branch-build-status
227
+ codebuild-history
225
228
  </td>
226
229
  <td>
227
230
  This table must be created and permissions granted to it as described
@@ -287,7 +290,7 @@ phases:
287
290
  <nobr>--whitelist-branches</nobr>
288
291
  </td>
289
292
  <td>
290
- master,release
293
+ master
291
294
  </td>
292
295
  <td>
293
296
  Normally statuses will be stored and notifications sent only for builds
@@ -122,17 +122,16 @@ end.parse!
122
122
  config = CodeBuildNotifier::Config.new(command_line_opts)
123
123
  build = CodeBuildNotifier::CurrentBuild.new
124
124
  history = CodeBuildNotifier::BuildHistory.new(config, build)
125
-
126
125
  last_build = history.last_entry
127
126
  build.previous_build = last_build
128
127
 
129
128
  if build.launched_by_retry?
130
129
  # Whenever a build is triggered by a PR or whitelisted branch, we update
131
- # the record for that trigger with the commit hash. If a build is then
132
- # launched using Retry, the status is updated and are notifications sent
133
- # only if the re-tried build was for the latest commit. Otherwise re-trying
134
- # an older commit could result in inaccurate notifications.
135
- quit(not_latest_commit_in_branch_message(build, config)) unless last_build
130
+ # the record for that trigger with the commit hash. If a build is
131
+ # launched using Retry, and there is no history entry for the current
132
+ # commit hash, then the build is not for a PR or a whitelisted branch,
133
+ # and should not be tracked.
134
+ quit(not_pr_or_whitelisted_branch_message(config)) unless last_build
136
135
  else
137
136
  # We only want to track information for whitelisted branches and branches
138
137
  # with open Pull Requests.
@@ -141,8 +140,6 @@ else
141
140
  end
142
141
  end
143
142
 
144
- # Update record for this project + branch/pr in DynamoDb even if the
145
- # status hasn't changed, so the latest commit hash is stored.
146
143
  history.write_entry(build.source_id) do |new_item|
147
144
  cb_puts "Updating dynamo table #{config.dynamo_table} with: #{new_item}"
148
145
  end
@@ -16,9 +16,12 @@
16
16
  # along with codebuild-notifier. If not, see <http://www.gnu.org/licenses/>.
17
17
 
18
18
  require 'codebuild-notifier/config'
19
+ require 'codebuild-notifier/dynamo_base'
20
+ require 'codebuild-notifier/branch_entry'
19
21
  require 'codebuild-notifier/build_history'
20
22
  require 'codebuild-notifier/current_build'
21
23
  require 'codebuild-notifier/git'
24
+ require 'codebuild-notifier/project_summary'
22
25
  require 'codebuild-notifier/slack_message'
23
26
  require 'codebuild-notifier/slack_sender'
24
27
  require 'codebuild-notifier/version'
@@ -0,0 +1,54 @@
1
+ # codebuild-notifier
2
+ # Copyright © 2018 Adam Alboyadjian <adam@cassia.tech>
3
+ # Copyright © 2018 Vista Higher Learning, Inc.
4
+ #
5
+ # codebuild-notifier is free software: you can redistribute it
6
+ # and/or modify it under the terms of the GNU General Public
7
+ # License as published by the Free Software Foundation, either
8
+ # version 3 of the License, or (at your option) any later version.
9
+ #
10
+ # codebuild-notifier is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with codebuild-notifier. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'digest'
19
+
20
+ module CodeBuildNotifier
21
+ class BranchEntry < DynamoBase
22
+ # Creates entries in a partition key with hardcoded primary key.
23
+ # Within the partition key, there is one record for each github repo.
24
+ # The 'projects' field in that record is a Map data type, keyed off
25
+ # project code, containing the status of the last build for that code.
26
+ def update
27
+ updates = hash_to_dynamo_update(branch_entry).merge(
28
+ key: { source_id: source_id, version_key: version_key }
29
+ )
30
+ yield updates if block_given?
31
+ update_item(updates)
32
+ end
33
+
34
+ private def branch_entry
35
+ {
36
+ branch_name: current_build.branch_name,
37
+ build_id: current_build.build_id,
38
+ commit_hash: source_id,
39
+ git_repo_url: current_build.git_repo_url,
40
+ source_ref: current_build.source_ref,
41
+ status: current_build.status,
42
+ timestamp: current_build.start_time.to_i
43
+ }
44
+ end
45
+
46
+ private def source_id
47
+ current_build.project_code
48
+ end
49
+
50
+ private def version_key
51
+ Digest::MD5.hexdigest(current_build.source_ref)
52
+ end
53
+ end
54
+ end
@@ -15,74 +15,94 @@
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 'active_support'
19
- require 'active_support/core_ext'
20
- require 'aws-sdk-dynamodb'
21
- require 'hashie'
22
-
23
18
  module CodeBuildNotifier
24
- class BuildHistory
25
- attr_reader :config, :current_build
26
-
27
- delegate :dynamo_table, to: :config
19
+ class BuildHistory < DynamoBase
28
20
  delegate :branch_name, :launched_by_retry?, to: :current_build
29
21
 
30
- def initialize(config, current_build)
31
- @config = config
32
- @current_build = current_build
33
- end
34
-
35
22
  def last_entry
23
+ return @last_entry if defined?(@last_entry)
36
24
  # If this build was launched using the Retry command from the console
37
25
  # or api we don't have a Pull Request or branch name to use in the
38
26
  # primary key, so we query by commit hash and project instead.
39
- item = launched_by_retry? ? find_by_commit_and_project : find_by_id
27
+ item = launched_by_retry? ? find_by_commit : find_by_id
40
28
 
41
29
  # Provide .dot access to hash values from Dynamo item.
42
- item && Hashie::Mash.new(item)
30
+ @last_entry = item && Hashie::Mash.new(item)
43
31
  end
44
32
 
45
33
  def write_entry(source_id)
46
34
  updates = hash_to_dynamo_update(new_entry).merge(
47
- key: { source_id: source_id }
35
+ key: { source_id: source_id, version_key: version_key }
48
36
  )
49
37
 
50
38
  yield updates if block_given?
51
39
 
52
- dynamo_client.update_item(
53
- updates.merge(table_name: dynamo_table)
54
- )
40
+ update_item(updates)
41
+
42
+ ProjectSummary.new(config, current_build).update
43
+ BranchEntry.new(config, current_build).update
55
44
  end
56
45
 
57
46
  # The commit hash and project code are used to find which Pull Request
58
47
  # or branch the current build belongs to, and the previous build status
59
48
  # for that Pull Request or branch.
60
- private def find_by_commit_and_project
61
- dynamo_client.query(
62
- expression_attribute_values: {
63
- ':commit_hash' => current_build.commit_hash,
64
- ':project_code' => current_build.project_code
65
- },
66
- filter_expression: 'project_code = :project_code',
49
+ private def find_by_commit
50
+ find_latest_version(
51
+ expression_attribute_values: commit_values,
52
+ filter_expression: commit_filter,
67
53
  index_name: 'commit_hash_index',
68
- key_condition_expression: 'commit_hash = :commit_hash',
69
- table_name: dynamo_table
70
- ).items.first
54
+ key_condition_expression: 'commit_hash = :commit_hash'
55
+ )
56
+ end
57
+
58
+ # When searching by commit hash, if the current build source version
59
+ # is for a PR, only return commits with that PR as the source ref.
60
+ # If source version is not for a pr, only return source refs beginning
61
+ # with branch/. This helps protect against the edge case where the same
62
+ # commit appears in two different PRs, or in a PR and whitelisted branch
63
+ # besides than the PR head.
64
+ private def commit_values
65
+ source_ref_val = if current_build.for_pr?
66
+ current_build.source_version
67
+ else
68
+ 'branch/'
69
+ end
70
+ {
71
+ ':commit_hash' => current_build.commit_hash,
72
+ ':project_code' => current_build.project_code,
73
+ ':source_ref' => source_ref_val
74
+ }
75
+ end
76
+
77
+ private def commit_filter
78
+ source_ref_condition = if current_build.for_pr?
79
+ 'source_ref = :source_ref'
80
+ else
81
+ 'begins_with(source_ref, :source_ref)'
82
+ end
83
+ "project_code = :project_code AND #{source_ref_condition}"
71
84
  end
72
85
 
73
86
  private def find_by_id
74
- dynamo_client.get_item(
75
- key: { 'source_id' => current_build.source_id },
76
- table_name: dynamo_table
77
- ).item
87
+ find_latest_version(
88
+ expression_attribute_values: {
89
+ ':source_id' => current_build.source_id
90
+ },
91
+ key_condition_expression: 'source_id = :source_id'
92
+ )
93
+ end
94
+
95
+ private def find_latest_version(args)
96
+ dynamo_client.query(
97
+ args.merge(
98
+ scan_index_forward: false, # Reverse sort by range key
99
+ table_name: dynamo_table
100
+ )
101
+ ).items.first
78
102
  end
79
103
 
80
104
  private def new_entry
81
- {
82
- commit_hash: current_build.commit_hash,
83
- project_code: current_build.project_code,
84
- status: current_build.status
85
- }.tap do |memo|
105
+ current_build.history_fields.tap do |memo|
86
106
  # If launched via manual re-try instead of via a webhook, we don't
87
107
  # want to overwrite the current source_ref value that tells us which
88
108
  # branch or pull request originally created the dynamo record.
@@ -93,21 +113,16 @@ module CodeBuildNotifier
93
113
  end
94
114
  end
95
115
 
96
- private def hash_to_dynamo_update(hash)
97
- update = hash.each_with_object(
98
- expression_attribute_names: {},
99
- expression_attribute_values: {},
100
- update_expression: []
101
- ) do |(key, value), memo|
102
- memo[:expression_attribute_names]["##{key}"] = key.to_s
103
- memo[:expression_attribute_values][":#{key}"] = value
104
- memo[:update_expression] << "##{key} = :#{key}"
116
+ # The first component of the version_key is the timestamp for the
117
+ # first build of the current commit hash. The second component
118
+ # is the timestamp for the current build. This allows easily finding
119
+ # either the latest commit, or the latest re-build of a commit.
120
+ private def version_key
121
+ if launched_by_retry?
122
+ "#{last_entry.start_time}_#{current_build.start_time}"
123
+ else
124
+ "#{current_build.start_time}_#{current_build.start_time}"
105
125
  end
106
- update.merge(update_expression: "SET #{update[:update_expression].join(', ')}")
107
- end
108
-
109
- private def dynamo_client
110
- @dynamo_client || Aws::DynamoDB::Client.new(region: config.region)
111
126
  end
112
127
  end
113
128
  end
@@ -17,7 +17,7 @@
17
17
 
18
18
  module CodeBuildNotifier
19
19
  class Config
20
- DEFAULT_WHITELIST = %w[master release]
20
+ DEFAULT_WHITELIST = %w[master]
21
21
 
22
22
  attr_reader :additional_channel, :default_strategy, :dynamo_table, :region,
23
23
  :slack_admins, :slack_secret_name, :whitelist_branches
@@ -27,7 +27,7 @@ module CodeBuildNotifier
27
27
  def initialize(
28
28
  additional_channel: ENV['CBN_ADDITIONAL_CHANNEL'],
29
29
  default_strategy: ENV['CBN_DEFAULT_NOTIFY_STRATEGY'] || 'fail_or_status_change',
30
- dynamo_table: ENV['CBN_DYNAMO_TABLE'] || 'branch-build-status',
30
+ dynamo_table: ENV['CBN_DYNAMO_TABLE'] || 'codebuild-history',
31
31
  region: ENV['CBN_AWS_REGION'] || ENV['AWS_REGION'],
32
32
  slack_admins: ENV['CBN_SLACK_ADMIN_USERNAMES'],
33
33
  slack_secret_name: ENV['CBN_SLACK_SECRET_NAME'] || 'slack/codebuild',
@@ -17,8 +17,13 @@
17
17
 
18
18
  module CodeBuildNotifier
19
19
  class CurrentBuild
20
- attr_reader :build_id, :commit_hash, :git_repo_url, :status_code, :trigger
21
20
  attr_accessor :previous_build
21
+ attr_reader :build_id, :commit_hash, :git_repo_url, :source_version,
22
+ :start_time, :status_code, :trigger
23
+
24
+ # attrs from git info
25
+ attr_reader :author_email, :author_name, :committer_email, :committer_name,
26
+ :commit_message_subject, :short_hash
22
27
 
23
28
  # Default values are extracted from CODEBUILD_* ENV vars present in each
24
29
  # CodeBuild # job container.
@@ -27,7 +32,9 @@ module CodeBuildNotifier
27
32
  commit_hash: ENV['CODEBUILD_RESOLVED_SOURCE_VERSION'],
28
33
  git_repo: ENV['CODEBUILD_SOURCE_REPO_URL'],
29
34
  head_ref: ENV['CODEBUILD_WEBHOOK_HEAD_REF'],
35
+ start_time: ENV['CODEBUILD_START_TIME'],
30
36
  status_code: ENV['CODEBUILD_BUILD_SUCCEEDING'],
37
+ source_version: ENV['CODEBUILD_SOURCE_VERSION'],
31
38
  trigger: ENV['CODEBUILD_WEBHOOK_TRIGGER']
32
39
  )
33
40
  @build_id = build_id
@@ -35,8 +42,14 @@ module CodeBuildNotifier
35
42
  # Handle repos specified with and without optional .git suffix.
36
43
  @git_repo_url = git_repo.to_s.gsub(/\.git\z/, '')
37
44
  @head_ref = head_ref
45
+ @source_version = source_version
46
+ @start_time = start_time || (Time.now.to_f * 1_000).to_i
38
47
  @status_code = status_code
39
48
  @trigger = trigger
49
+
50
+ @short_hash, @author_name, @author_email,
51
+ @committer_name, @committer_email,
52
+ @commit_message_subject = git_info
40
53
  end
41
54
 
42
55
  # If launched via retry, the webhook head ref env var is blank,
@@ -65,7 +78,7 @@ module CodeBuildNotifier
65
78
  end
66
79
 
67
80
  def for_pr?
68
- %r{^pr/}.match?(trigger.to_s)
81
+ %r{^pr/}.match?(source_version.to_s)
69
82
  end
70
83
 
71
84
  # source_id, the primary key, is a composite of project_code and
@@ -97,5 +110,25 @@ module CodeBuildNotifier
97
110
  trigger
98
111
  end
99
112
  end
113
+
114
+ def history_fields
115
+ {
116
+ author_email: author_email,
117
+ author_name: author_name,
118
+ build_id: build_id,
119
+ commit_hash: commit_hash,
120
+ commit_subject: commit_message_subject,
121
+ committer_email: committer_email,
122
+ committer_name: committer_name,
123
+ git_repo_url: git_repo_url,
124
+ project_code: project_code,
125
+ start_time: start_time,
126
+ status: status
127
+ }
128
+ end
129
+
130
+ private def git_info
131
+ Git.current_commit
132
+ end
100
133
  end
101
134
  end
@@ -0,0 +1,57 @@
1
+ # codebuild-notifier
2
+ # Copyright © 2018 Adam Alboyadjian <adam@cassia.tech>
3
+ # Copyright © 2018 Vista Higher Learning, Inc.
4
+ #
5
+ # codebuild-notifier is free software: you can redistribute it
6
+ # and/or modify it under the terms of the GNU General Public
7
+ # License as published by the Free Software Foundation, either
8
+ # version 3 of the License, or (at your option) any later version.
9
+ #
10
+ # codebuild-notifier is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with codebuild-notifier. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'active_support'
19
+ require 'active_support/core_ext'
20
+ require 'aws-sdk-dynamodb'
21
+ require 'hashie'
22
+
23
+ module CodeBuildNotifier
24
+ class DynamoBase
25
+ attr_reader :config, :current_build
26
+
27
+ delegate :dynamo_table, to: :config
28
+
29
+ def initialize(config, build)
30
+ @config = config
31
+ @current_build = build
32
+ end
33
+
34
+ private def update_item(updates)
35
+ dynamo_client.update_item(
36
+ updates.merge(table_name: dynamo_table)
37
+ )
38
+ end
39
+
40
+ private def dynamo_client
41
+ @dynamo_client || Aws::DynamoDB::Client.new(region: config.region)
42
+ end
43
+
44
+ private def hash_to_dynamo_update(hash)
45
+ update = hash.each_with_object(
46
+ expression_attribute_names: {},
47
+ expression_attribute_values: {},
48
+ update_expression: []
49
+ ) do |(key, value), memo|
50
+ memo[:expression_attribute_names]["##{key}"] = key.to_s
51
+ memo[:expression_attribute_values][":#{key}"] = value
52
+ memo[:update_expression] << "##{key} = :#{key}"
53
+ end
54
+ update.merge(update_expression: "SET #{update[:update_expression].join(', ')}")
55
+ end
56
+ end
57
+ end
@@ -18,7 +18,7 @@
18
18
  module CodeBuildNotifier
19
19
  module Git
20
20
  def current_commit
21
- `git show -s --format='%h|%aN|%aE|%cE|%s'`.chomp.split('|')
21
+ `git show -s --format='%h|%aN|%aE|%cN|%cE|%s'`.chomp.split('|')
22
22
  end
23
23
  module_function :current_commit
24
24
  end
@@ -0,0 +1,125 @@
1
+ # codebuild-notifier
2
+ # Copyright © 2018 Adam Alboyadjian <adam@cassia.tech>
3
+ # Copyright © 2018 Vista Higher Learning, Inc.
4
+ #
5
+ # codebuild-notifier is free software: you can redistribute it
6
+ # and/or modify it under the terms of the GNU General Public
7
+ # License as published by the Free Software Foundation, either
8
+ # version 3 of the License, or (at your option) any later version.
9
+ #
10
+ # codebuild-notifier is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with codebuild-notifier. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'digest'
19
+
20
+ module CodeBuildNotifier
21
+ class ProjectSummary < DynamoBase
22
+ # Creates entries in a partition key with hardcoded primary key.
23
+ # Within the partition key, there is one record for each github repo.
24
+ # The 'projects' field in that record is a Map data type, keyed off
25
+ # project code, containing the status of the last build for that code.
26
+ def update
27
+ return unless whitelisted_branch?
28
+
29
+ updates = project_summary_entry
30
+ yield updates if block_given?
31
+ update_item(updates)
32
+ end
33
+
34
+ private def whitelisted_branch?
35
+ config.whitelist_branches.include?(current_build.branch_name)
36
+ end
37
+
38
+ private def project_summary_entry
39
+ {
40
+ key: { source_id: source_id, version_key: version_key },
41
+ expression_attribute_names: attr_names,
42
+ expression_attribute_values: attr_values,
43
+ update_expression: update_expression
44
+ }
45
+ end
46
+
47
+ private def new_record?
48
+ return @new_record if defined?(@new_record)
49
+
50
+ item = dynamo_client.get_item(
51
+ key: {
52
+ 'source_id' => source_id, 'version_key' => version_key
53
+ },
54
+ table_name: dynamo_table
55
+ ).item
56
+ @new_record = item.nil?
57
+ end
58
+
59
+ private def source_id
60
+ 'project_summary'
61
+ end
62
+
63
+ # The repo url isn't a good format to use as a URL param.
64
+ private def version_key
65
+ Digest::MD5.hexdigest(current_build.git_repo_url)
66
+ end
67
+
68
+ private def attr_names
69
+ {
70
+ '#commit_hash' => 'commit_hash',
71
+ '#git_repo_url' => 'git_repo_url',
72
+ '#timestamp' => 'timestamp',
73
+ '#projects' => 'projects'
74
+ }.merge(project_code_attr_name)
75
+ end
76
+
77
+ # For an existing record, the project key already exists, so
78
+ # an attribute name is needed to be able to update the nested item
79
+ # path. For a new record, the project code is specified as the root
80
+ # key of the value assigned to the projects field.
81
+ private def project_code_attr_name
82
+ if new_record?
83
+ {}
84
+ else
85
+ { '#project_code' => current_build.project_code }
86
+ end
87
+ end
88
+
89
+ private def attr_values
90
+ {
91
+ ':build_status' => status_value,
92
+ ':commit_hash' => source_id,
93
+ ':git_repo_url' => current_build.git_repo_url,
94
+ ':timestamp' => current_build.start_time.to_i
95
+ }
96
+ end
97
+
98
+ private def status_map
99
+ {
100
+ 'build_id' => current_build.build_id,
101
+ 'status' => current_build.status,
102
+ 'timestamp' => current_build.start_time.to_i
103
+ }
104
+ end
105
+
106
+ # If a record already exists, we can address the nested item path for
107
+ # the current project directly and just store the updated status.
108
+ # Otherwise, we have to create a new map object in the projects field.
109
+ private def status_value
110
+ if new_record?
111
+ { current_build.project_code => status_map }
112
+ else
113
+ status_map
114
+ end
115
+ end
116
+
117
+ private def update_expression
118
+ projects_key = new_record? ? '#projects' : '#projects.#project_code'
119
+ 'SET #commit_hash = :commit_hash, ' \
120
+ '#timestamp = :timestamp, ' \
121
+ '#git_repo_url = :git_repo_url, ' \
122
+ "#{projects_key} = :build_status"
123
+ end
124
+ end
125
+ end
@@ -17,16 +17,14 @@
17
17
 
18
18
  module CodeBuildNotifier
19
19
  class SlackMessage
20
- attr_reader :author_email, :author_name, :build, :committer_email,
21
- :commit_message_subject, :config, :short_hash
20
+ attr_reader :build, :config
22
21
 
23
- delegate :source_ref, to: :build
22
+ delegate :author_email, :author_name, :committer_email,
23
+ :commit_message_subject, :short_hash, :source_ref, to: :build
24
24
 
25
25
  def initialize(build, config)
26
26
  @build = build
27
27
  @config = config
28
- @short_hash, @author_name, @author_email,
29
- @committer_email, @commit_message_subject = git_info
30
28
  end
31
29
 
32
30
  def payload
@@ -46,10 +44,6 @@ module CodeBuildNotifier
46
44
  !build.for_pr? && config.additional_channel
47
45
  end
48
46
 
49
- private def git_info
50
- Git.current_commit
51
- end
52
-
53
47
  private def slack_color
54
48
  {
55
49
  'FAILED' => 'danger',
@@ -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 = '0.3.2'.freeze
19
+ VERSION = '1.0.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: 0.3.2
4
+ version: 1.0.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-02-27 00:00:00.000000000 Z
11
+ date: 2019-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -167,10 +167,13 @@ files:
167
167
  - bin/update-build-status
168
168
  - codebuild-notifier.gemspec
169
169
  - lib/codebuild-notifier.rb
170
+ - lib/codebuild-notifier/branch_entry.rb
170
171
  - lib/codebuild-notifier/build_history.rb
171
172
  - lib/codebuild-notifier/config.rb
172
173
  - lib/codebuild-notifier/current_build.rb
174
+ - lib/codebuild-notifier/dynamo_base.rb
173
175
  - lib/codebuild-notifier/git.rb
176
+ - lib/codebuild-notifier/project_summary.rb
174
177
  - lib/codebuild-notifier/slack_message.rb
175
178
  - lib/codebuild-notifier/slack_sender.rb
176
179
  - lib/codebuild-notifier/version.rb