codebuild-notifier 0.2.0 → 0.3.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 +4 -4
- data/.rubocop.yml +3 -0
- data/README.md +40 -0
- data/bin/update-build-status +52 -16
- data/lib/codebuild-notifier/build_history.rb +5 -2
- data/lib/codebuild-notifier/config.rb +11 -2
- data/lib/codebuild-notifier/current_build.rb +33 -1
- data/lib/codebuild-notifier/slack_message.rb +4 -3
- data/lib/codebuild-notifier/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 83a2bb81dc8815d9ccfa7073d97408297584a1e6f104f894d1f26c2e2cfd2453
|
4
|
+
data.tar.gz: bcf314b4c5f2e3b708ba5ff8a63b3deda7255291b803f3bd266c76219ffb4aad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e1671f03687d58d57ac917a08511e6cabeee8a687fb33087339d22c0ffae40a0e1b9efb69232ff4a5aa3cff1325c22c26560dd6af9c0084b0ea5caca18403675
|
7
|
+
data.tar.gz: d7e658e90f1bed0eb2ba2d413b4ef9548da102019690fb39bd8263ebbfbcc6206e113caac8ca9ef4264bd6d0657662c7d21bdb59acdac1065dc362ea05f9509d
|
data/.rubocop.yml
CHANGED
data/README.md
CHANGED
@@ -192,6 +192,27 @@ phases:
|
|
192
192
|
that region.
|
193
193
|
</td>
|
194
194
|
</tr>
|
195
|
+
<tr>
|
196
|
+
<th>
|
197
|
+
CBN_DEFAULT_NOTIFY_STRATEGY
|
198
|
+
</th>
|
199
|
+
<td>
|
200
|
+
<nobr>--default-notify-strategy</nobr>
|
201
|
+
</td>
|
202
|
+
<td>
|
203
|
+
fail_or_status_change
|
204
|
+
</td>
|
205
|
+
<td>
|
206
|
+
Determines when notifications will be sent.
|
207
|
+
'status_change' sends notifications for the first build in a PR or
|
208
|
+
whitelisted branch, thereafter if a build in that PR/branch has a
|
209
|
+
different status to the previous build.
|
210
|
+
'every_build' sends a notification regardless of status.
|
211
|
+
'fail_or_status_change', the default value, will send if the status
|
212
|
+
changes, but will also send notifications of every failure,
|
213
|
+
regardless of previous status.
|
214
|
+
</td>
|
215
|
+
</tr>
|
195
216
|
<tr>
|
196
217
|
<th>
|
197
218
|
CBN_DYNAMO_TABLE
|
@@ -207,6 +228,25 @@ phases:
|
|
207
228
|
in <a href="#infrastructure-requirements">Infrastructure Requirements</a>
|
208
229
|
</td>
|
209
230
|
</tr>
|
231
|
+
<tr>
|
232
|
+
<th>
|
233
|
+
CBN_OVERRIDE_NOTIFY_STRATEGY
|
234
|
+
</th>
|
235
|
+
<td>
|
236
|
+
<nobr>--override-notify-strategy</nobr>
|
237
|
+
</td>
|
238
|
+
<td>
|
239
|
+
not set
|
240
|
+
</td>
|
241
|
+
<td>
|
242
|
+
Allows overriding default notify strategy.
|
243
|
+
Specify a branch and strategy for that branch, with a colon separator.
|
244
|
+
Valid strategies are:
|
245
|
+
status_change, every_build, fail_or_status_change
|
246
|
+
Specify multiple branch strategies delimited by comma.
|
247
|
+
e.g. 'master:every_build,jira-15650:status_change'
|
248
|
+
</td>
|
249
|
+
</tr>
|
210
250
|
<tr>
|
211
251
|
<th>
|
212
252
|
CBN_SLACK_ADMIN_USERNAMES
|
data/bin/update-build-status
CHANGED
@@ -60,29 +60,58 @@ OptionParser.new do |opts|
|
|
60
60
|
'--additional-channel=CHANNEL',
|
61
61
|
'status notifications for whitelisted branches will be sent here ' \
|
62
62
|
'as well as to author/committer'
|
63
|
-
)
|
63
|
+
) do |usernames|
|
64
|
+
command_line_opts[:slack_admin_users] = usernames
|
65
|
+
end
|
64
66
|
|
65
67
|
opts.on(
|
66
|
-
'--
|
67
|
-
'
|
68
|
-
'
|
69
|
-
|
68
|
+
'--default-notify-strategy=STRATEGY',
|
69
|
+
'when to send notifications, in the absence of a branch-specific ' \
|
70
|
+
'override -- valid options are: status_change (the default), ' \
|
71
|
+
'every_build, fail_or_status_change'
|
72
|
+
) do |default_strategy|
|
73
|
+
command_line_opts[:default_strategy] = default_strategy
|
74
|
+
end
|
70
75
|
|
71
76
|
opts.on(
|
72
77
|
'--dynamo-table=TABLE',
|
73
78
|
'table for storing build statuses'
|
74
|
-
)
|
79
|
+
) do |table|
|
80
|
+
command_line_opts[:dynamo_table] = table
|
81
|
+
end
|
82
|
+
|
83
|
+
opts.on(
|
84
|
+
'--override-notify-strategy=BRANCH_STRATEGY_PAIRS',
|
85
|
+
'overrides default notify strategy; specify pairs of branch:strategy ' \
|
86
|
+
'Valid strategies are: status_change, every_build, fail_or_status_change ' \
|
87
|
+
'separate pairs with a comma' \
|
88
|
+
'e.g. master:every_build,jira-15650:status_change'
|
89
|
+
) do |overrides|
|
90
|
+
command_line_opts[:strategy_overrides] = overrides
|
91
|
+
end
|
92
|
+
|
93
|
+
opts.on(
|
94
|
+
'--slack-admin-usernames=USERS',
|
95
|
+
'comma-separated list of slack users to be notified if build status ' \
|
96
|
+
'notifications fail to send'
|
97
|
+
) do |usernames|
|
98
|
+
command_line_opts[:slack_admin_users] = usernames
|
99
|
+
end
|
75
100
|
|
76
101
|
opts.on(
|
77
102
|
'--slack-secret-name=SECRET',
|
78
103
|
'name of Secrets Manager secret with slack app/bot auth token'
|
79
|
-
)
|
104
|
+
) do |slack_secret|
|
105
|
+
command_line_opts[:slack_secret_name] = slack_secret
|
106
|
+
end
|
80
107
|
|
81
108
|
opts.on(
|
82
109
|
'--whitelist-branches=BRANCHES',
|
83
110
|
'comma-separated list of branches that will have build notifications ' \
|
84
111
|
'sent even if there is no open Pull Request'
|
85
|
-
)
|
112
|
+
) do |whitelist|
|
113
|
+
command_line_opts[:whitelist_branches] = whitelist
|
114
|
+
end
|
86
115
|
|
87
116
|
opts.on('--region=REGION', 'AWS region') do |region|
|
88
117
|
command_line_opts[:region] = region
|
@@ -95,6 +124,7 @@ build = CodeBuildNotifier::CurrentBuild.new
|
|
95
124
|
history = CodeBuildNotifier::BuildHistory.new(config, build)
|
96
125
|
|
97
126
|
last_build = history.last_entry
|
127
|
+
build.previous_build = last_build
|
98
128
|
|
99
129
|
if build.launched_by_retry?
|
100
130
|
# Whenever a build is triggered by a PR or whitelisted branch, we update
|
@@ -103,27 +133,33 @@ if build.launched_by_retry?
|
|
103
133
|
# only if the re-tried build was for the latest commit. Otherwise re-trying
|
104
134
|
# an older commit could result in inaccurate notifications.
|
105
135
|
quit(not_latest_commit_in_branch_message(build, config)) unless last_build
|
106
|
-
|
107
|
-
source_id = last_build.source_id
|
108
|
-
source_ref = last_build.source_ref
|
109
136
|
else
|
110
137
|
# We only want to track information for whitelisted branches and branches
|
111
138
|
# with open Pull Requests.
|
112
139
|
unless config.non_pr_branch_ids.include?(build.trigger) || build.for_pr?
|
113
140
|
quit(not_pr_or_whitelisted_branch_message(config))
|
114
141
|
end
|
115
|
-
source_id = build.source_id
|
116
|
-
source_ref = build.trigger
|
117
142
|
end
|
118
143
|
|
119
144
|
# Update record for this project + branch/pr in DynamoDb even if the
|
120
145
|
# status hasn't changed, so the latest commit hash is stored.
|
121
|
-
history.write_entry(source_id) do |new_item|
|
146
|
+
history.write_entry(build.source_id) do |new_item|
|
122
147
|
cb_puts "Updating dynamo table #{config.dynamo_table} with: #{new_item}"
|
123
148
|
end
|
124
149
|
|
125
|
-
|
150
|
+
status_changed = last_build&.status != build.status
|
151
|
+
|
152
|
+
strategy = config.strategy_for_branch(build.branch_name)
|
153
|
+
|
154
|
+
unless strategy == 'every_build'
|
155
|
+
if strategy == 'status_change'
|
156
|
+
quit(no_status_diff_message(build)) unless status_changed
|
157
|
+
elsif strategy == 'fail_or_status_change'
|
158
|
+
# TODO: Find good wording for a different exit message for this case.
|
159
|
+
quit(no_status_diff_message(build)) if build.status == 'SUCCEEDED' && !status_changed
|
160
|
+
end
|
161
|
+
end
|
126
162
|
|
127
|
-
slack_message = CodeBuildNotifier::SlackMessage.new(build, config, source_ref)
|
163
|
+
slack_message = CodeBuildNotifier::SlackMessage.new(build, config, build.source_ref)
|
128
164
|
sender = CodeBuildNotifier::SlackSender.new(config)
|
129
165
|
sender.send(slack_message)
|
@@ -25,7 +25,7 @@ module CodeBuildNotifier
|
|
25
25
|
attr_reader :config, :current_build
|
26
26
|
|
27
27
|
delegate :dynamo_table, to: :config
|
28
|
-
delegate :launched_by_retry?, to: :current_build
|
28
|
+
delegate :branch_name, :launched_by_retry?, to: :current_build
|
29
29
|
|
30
30
|
def initialize(config, current_build)
|
31
31
|
@config = config
|
@@ -86,7 +86,10 @@ module CodeBuildNotifier
|
|
86
86
|
# If launched via manual re-try instead of via a webhook, we don't
|
87
87
|
# want to overwrite the current source_ref value that tells us which
|
88
88
|
# branch or pull request originally created the dynamo record.
|
89
|
-
|
89
|
+
unless launched_by_retry?
|
90
|
+
memo[:source_ref] = current_build.trigger
|
91
|
+
memo[:branch_name] = branch_name unless branch_name.empty?
|
92
|
+
end
|
90
93
|
end
|
91
94
|
end
|
92
95
|
|
@@ -19,27 +19,36 @@ module CodeBuildNotifier
|
|
19
19
|
class Config
|
20
20
|
DEFAULT_WHITELIST = %w[master release]
|
21
21
|
|
22
|
-
attr_reader :additional_channel, :
|
23
|
-
:slack_secret_name, :whitelist_branches
|
22
|
+
attr_reader :additional_channel, :default_strategy, :dynamo_table, :region,
|
23
|
+
:slack_admins, :slack_secret_name, :whitelist_branches
|
24
24
|
|
25
25
|
# Configuration values specific to CodeBuild Notifier. CBN_ prefix is
|
26
26
|
# used because ENV vars with CODEBUILD_ prefix are reserved for use by AWS.
|
27
27
|
def initialize(
|
28
28
|
additional_channel: ENV['CBN_ADDITIONAL_CHANNEL'],
|
29
|
+
default_strategy: ENV['CBN_DEFAULT_NOTIFY_STRATEGY'] || 'fail_or_status_change',
|
29
30
|
dynamo_table: ENV['CBN_DYNAMO_TABLE'] || 'branch-build-status',
|
30
31
|
region: ENV['CBN_AWS_REGION'] || ENV['AWS_REGION'],
|
31
32
|
slack_admins: ENV['CBN_SLACK_ADMIN_USERNAMES'],
|
32
33
|
slack_secret_name: ENV['CBN_SLACK_SECRET_NAME'] || 'slack/codebuild',
|
34
|
+
strategy_overrides: ENV['CBN_OVERRIDE_NOTIFY_STRATEGY'],
|
33
35
|
whitelist_branches: ENV['CBN_WHITELIST_BRANCHES']
|
34
36
|
)
|
35
37
|
@additional_channel = additional_channel
|
38
|
+
@default_strategy = default_strategy
|
36
39
|
@dynamo_table = dynamo_table
|
37
40
|
@region = region
|
38
41
|
@slack_admins = slack_admins&.split(',') || []
|
39
42
|
@slack_secret_name = slack_secret_name
|
43
|
+
@strategy_overrides = strategy_overrides&.split(',') || []
|
40
44
|
@whitelist_branches = whitelist_branches&.split(',') || DEFAULT_WHITELIST
|
41
45
|
end
|
42
46
|
|
47
|
+
def strategy_for_branch(branch_name)
|
48
|
+
lookup = @strategy_overrides.map { |override| override.split(':') }.to_h
|
49
|
+
lookup.fetch(branch_name, default_strategy)
|
50
|
+
end
|
51
|
+
|
43
52
|
# Match the format of the CodeBuild trigger variable
|
44
53
|
def non_pr_branch_ids
|
45
54
|
whitelist_branches.map { |name| "branch/#{name}" }
|
@@ -18,6 +18,7 @@
|
|
18
18
|
module CodeBuildNotifier
|
19
19
|
class CurrentBuild
|
20
20
|
attr_reader :build_id, :commit_hash, :git_repo_url, :status_code, :trigger
|
21
|
+
attr_accessor :previous_build
|
21
22
|
|
22
23
|
# Default values are extracted from CODEBUILD_* ENV vars present in each
|
23
24
|
# CodeBuild # job container.
|
@@ -25,6 +26,7 @@ module CodeBuildNotifier
|
|
25
26
|
build_id: ENV['CODEBUILD_BUILD_ID'],
|
26
27
|
commit_hash: ENV['CODEBUILD_RESOLVED_SOURCE_VERSION'],
|
27
28
|
git_repo: ENV['CODEBUILD_SOURCE_REPO_URL'],
|
29
|
+
head_ref: ENV['CODEBUILD_WEBHOOK_HEAD_REF'],
|
28
30
|
status_code: ENV['CODEBUILD_BUILD_SUCCEEDING'],
|
29
31
|
trigger: ENV['CODEBUILD_WEBHOOK_TRIGGER']
|
30
32
|
)
|
@@ -32,10 +34,22 @@ module CodeBuildNotifier
|
|
32
34
|
@commit_hash = commit_hash
|
33
35
|
# Handle repos specified with and without optional .git suffix.
|
34
36
|
@git_repo_url = git_repo.to_s.gsub(/\.git\z/, '')
|
37
|
+
@head_ref = head_ref
|
35
38
|
@status_code = status_code
|
36
39
|
@trigger = trigger
|
37
40
|
end
|
38
41
|
|
42
|
+
# If launched via retry, the webhook head ref env var is blank,
|
43
|
+
# but if the previous build for this branch has been located,
|
44
|
+
# the branch_name of that build is the same as for this build
|
45
|
+
def branch_name
|
46
|
+
if launched_by_retry?
|
47
|
+
previous_build&.branch_name
|
48
|
+
else
|
49
|
+
@head_ref.to_s.gsub(%r{^refs/heads/}, '')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
39
53
|
def status
|
40
54
|
status_code.to_s == '1' ? 'SUCCEEDED' : 'FAILED'
|
41
55
|
end
|
@@ -63,7 +77,25 @@ module CodeBuildNotifier
|
|
63
77
|
# multiple projects, for example, with different buildspec files for
|
64
78
|
# different ruby versions, or for rspec vs cucumber.
|
65
79
|
def source_id
|
66
|
-
|
80
|
+
# If launched via retry, trigger is blank, but if the previous
|
81
|
+
# build for this branch has been located, the source_id of that
|
82
|
+
# build is the same as for this build
|
83
|
+
if launched_by_retry?
|
84
|
+
previous_build&.source_id
|
85
|
+
else
|
86
|
+
"#{project_code}:#{trigger}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def source_ref
|
91
|
+
# If launched via retry, trigger is blank, but if the previous
|
92
|
+
# build for this branch has been located, the source_ref of that
|
93
|
+
# build is the same as for this build
|
94
|
+
if launched_by_retry?
|
95
|
+
previous_build&.source_ref
|
96
|
+
else
|
97
|
+
trigger
|
98
|
+
end
|
67
99
|
end
|
68
100
|
end
|
69
101
|
end
|
@@ -18,12 +18,13 @@
|
|
18
18
|
module CodeBuildNotifier
|
19
19
|
class SlackMessage
|
20
20
|
attr_reader :author_email, :author_name, :build, :committer_email,
|
21
|
-
:commit_message_subject, :config, :short_hash
|
21
|
+
:commit_message_subject, :config, :short_hash
|
22
22
|
|
23
|
-
|
23
|
+
delegate :source_ref, to: :build
|
24
|
+
|
25
|
+
def initialize(build, config)
|
24
26
|
@build = build
|
25
27
|
@config = config
|
26
|
-
@source_ref = source_ref
|
27
28
|
@short_hash, @author_name, @author_email,
|
28
29
|
@committer_email, @commit_message_subject = git_info
|
29
30
|
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.
|
4
|
+
version: 0.3.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:
|
11
|
+
date: 2019-02-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|