jackal-nellie 0.1.10 → 0.1.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +31 -0
- data/lib/jackal-nellie/formatter.rb +11 -4
- data/lib/jackal-nellie/formatter/github_commit_status.rb +43 -0
- data/lib/jackal-nellie/formatter/slack_comment.rb +2 -2
- data/lib/jackal-nellie/processor.rb +76 -11
- data/lib/jackal-nellie/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b75d4681c23715ca2f5c2778af3ad04f526d50c8
|
4
|
+
data.tar.gz: f31c526030005cb15e6ba1eff4e22c8d082f3968
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c21247741e97b33c48523dd8d09b164613eaaa9a23bf31906c686900a4ddf380f7c0d18518fc470a0598acceceb34d13d1a4c30cd7284727d809f227fcc1695
|
7
|
+
data.tar.gz: 484ecdfff4016b31ae1c2348dd5cc8492b0de8d01e2350c01bee801858b784e17b89354f8702591d07df57b05d8b7ceef004cc2f88895724a5c96827ce3d9187
|
data/README.md
CHANGED
@@ -9,7 +9,38 @@ fetcher service.
|
|
9
9
|
|
10
10
|
## Configuration
|
11
11
|
|
12
|
+
Available configuration options:
|
12
13
|
|
14
|
+
* `working_directory` - working directory on host system
|
15
|
+
* `script_name` - file name of nellie file (defaults to `.nellie`)
|
16
|
+
* `max_execution_time` - maximum number of seconds to allow execution
|
17
|
+
|
18
|
+
## Nellie file structure
|
19
|
+
|
20
|
+
Nellie supports two file styles:
|
21
|
+
|
22
|
+
1. Executable
|
23
|
+
2. JSON
|
24
|
+
|
25
|
+
### Executable format
|
26
|
+
|
27
|
+
If the file is not in a JSON format, nellie will attempt to execute
|
28
|
+
it using the `bash` shell.
|
29
|
+
|
30
|
+
### JSON format
|
31
|
+
|
32
|
+
Nellie also supports a JSON file with the following structure:
|
33
|
+
|
34
|
+
```json
|
35
|
+
{
|
36
|
+
"commands": [
|
37
|
+
"touch /tmp/test.txt"
|
38
|
+
],
|
39
|
+
"environment": {
|
40
|
+
"MY_VAR": "MY_VALUE"
|
41
|
+
}
|
42
|
+
}
|
43
|
+
```
|
13
44
|
|
14
45
|
# Info
|
15
46
|
|
@@ -13,7 +13,7 @@ module Jackal
|
|
13
13
|
payload.get(:data, :code_fetcher, :info, :name)
|
14
14
|
].join('/')
|
15
15
|
sha = payload.get(:data, :code_fetcher, :info, :commit_sha)
|
16
|
-
"[
|
16
|
+
"[#{app_config.fetch(:branding, :name, 'Nellie')}]: Job completed successfully! (#{repo}@#{sha})"
|
17
17
|
end
|
18
18
|
|
19
19
|
# Message for failure results
|
@@ -21,17 +21,23 @@ module Jackal
|
|
21
21
|
# @param payload [Smash]
|
22
22
|
# @return [String]
|
23
23
|
def failure_message(payload)
|
24
|
-
msg = ['
|
24
|
+
msg = ["[#{app_config.fetch(:branding, :name, 'Nellie')}]: Failure encountered:"]
|
25
25
|
msg << ''
|
26
26
|
failed_history = payload.fetch(:data, :nellie, :history, {}).detect do |i|
|
27
27
|
i[:exit_code] != 0
|
28
28
|
end
|
29
29
|
if(failed_history)
|
30
|
+
stdout = asset_store.get(failed_history.get(:logs, :stdout))
|
31
|
+
stdout_pos = stdout.size - 1024
|
32
|
+
stdout.seek(stdout_pos < 0 ? 0 : stdout_pos)
|
33
|
+
stderr = asset_store.get(failed_history.get(:logs, :stderr))
|
34
|
+
stderr_pos = stderr.size - 1034
|
35
|
+
stderr.seek(stderr_pos < 0 ? 0 : stderr_pos)
|
30
36
|
msg << '* STDOUT:' << '' << '```'
|
31
|
-
msg <<
|
37
|
+
msg << stdout.read
|
32
38
|
msg << '```' << ''
|
33
39
|
msg << '* STDERR:' << '' << '```'
|
34
|
-
msg <<
|
40
|
+
msg << stderr.read
|
35
41
|
msg << '```'
|
36
42
|
else
|
37
43
|
msg << '```' << 'Failed to locate logs' << '```'
|
@@ -44,5 +50,6 @@ module Jackal
|
|
44
50
|
end
|
45
51
|
end
|
46
52
|
|
53
|
+
require 'jackal-nellie/formatter/github_commit_status'
|
47
54
|
require 'jackal-nellie/formatter/github_commit_comment'
|
48
55
|
require 'jackal-nellie/formatter/slack_comment'
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'jackal'
|
2
|
+
|
3
|
+
module Jackal
|
4
|
+
module Nellie
|
5
|
+
module Formatter
|
6
|
+
|
7
|
+
class GithubCommitStatus < Jackal::Formatter
|
8
|
+
|
9
|
+
include MessageExtract
|
10
|
+
|
11
|
+
# Source service
|
12
|
+
SOURCE = :nellie
|
13
|
+
# Destination service
|
14
|
+
DESTINATION = :github_kit
|
15
|
+
|
16
|
+
# Format payload to provide output status to GitHub
|
17
|
+
#
|
18
|
+
# @param payload [Smash]
|
19
|
+
def format(payload)
|
20
|
+
if(payload.get(:data, :nellie, :status))
|
21
|
+
payload.set(:data, :github_kit, :status,
|
22
|
+
Smash.new(
|
23
|
+
:repository => [
|
24
|
+
payload.get(:data, :code_fetcher, :info, :owner),
|
25
|
+
payload.get(:data, :code_fetcher, :info, :name)
|
26
|
+
].join('/'),
|
27
|
+
:reference => payload.get(:data, :code_fetcher, :info, :commit_sha),
|
28
|
+
:state => payload.get(:data, :nellie, :status) == 'success' ? 'success' : 'failure',
|
29
|
+
:extras => {
|
30
|
+
:context => 'nellie',
|
31
|
+
:description => payload.get(:data, :nellie, :status) == 'success' ?
|
32
|
+
"#{app_config.fetch(:branding, :name, 'Nellie')} completed successfully" :
|
33
|
+
"#{app_config.fetch(:branding, :name, 'Nellie')} failed to complete"
|
34
|
+
}
|
35
|
+
)
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -21,13 +21,13 @@ module Jackal
|
|
21
21
|
msgs = payload.fetch(:data, :slack, :messages, [])
|
22
22
|
if(payload.get(:data, :nellie, :result, :complete))
|
23
23
|
msgs << Smash.new(
|
24
|
-
:description => 'Nellie job result:
|
24
|
+
:description => "#{app_config.fetch(:branding, :name, 'Nellie')} job result:",
|
25
25
|
:message => success_message(payload),
|
26
26
|
:color => :good
|
27
27
|
)
|
28
28
|
else
|
29
29
|
msgs << Smash.new(
|
30
|
-
:description => 'Nellie job result:
|
30
|
+
:description => "#{app_config.fetch(:branding, :name, 'Nellie')} job result:",
|
31
31
|
:message => failure_message(payload),
|
32
32
|
:color => :bad
|
33
33
|
)
|
@@ -47,13 +47,18 @@ module Jackal
|
|
47
47
|
failure_wrap(message) do |payload|
|
48
48
|
debug "Processing nellie payload!"
|
49
49
|
nellie_cwd = fetch_code(payload)
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
50
|
+
begin
|
51
|
+
unless(payload.get(:data, :nellie, :commands))
|
52
|
+
extract_nellie_commands(nellie_cwd, payload)
|
53
|
+
end
|
54
|
+
if(payload.get(:data, :nellie, :commands))
|
55
|
+
execute_commands(nellie_cwd, payload)
|
56
|
+
else
|
57
|
+
warn "No nellie commands found for execution on message! (#{message})"
|
58
|
+
end
|
59
|
+
ensure
|
60
|
+
debug "Removing nellie job working directory: `#{nellie_cwd}`"
|
61
|
+
FileUtils.rm_rf(File.dirname(nellie_cwd))
|
57
62
|
end
|
58
63
|
job_completed(:nellie, payload, message)
|
59
64
|
end
|
@@ -76,8 +81,17 @@ module Jackal
|
|
76
81
|
payload.set(:data, :nellie, :history, results)
|
77
82
|
payload[:data][:nellie].delete(:commands)
|
78
83
|
payload[:data][:nellie].delete(:environment)
|
84
|
+
if(payload.get(:data, :nellie, :cleanup))
|
85
|
+
debug "Cleanup commands detected. Running now."
|
86
|
+
cleanup_results = run_commands(payload[:data][:nellie].delete(:cleanup), process_environment, payload, nellie_cwd)
|
87
|
+
payload.set(:data, :nellie, :cleanup_history, cleanup_results)
|
88
|
+
debug "Cleanup commands have completed."
|
89
|
+
end
|
79
90
|
unless(payload.get(:data, :nellie, :result, :failed))
|
80
91
|
payload.set(:data, :nellie, :result, :complete, true)
|
92
|
+
if(payload.get(:data, :nellie, :release_assets))
|
93
|
+
set_github_release_assets(payload, nellie_cwd)
|
94
|
+
end
|
81
95
|
end
|
82
96
|
payload.set(:data, :nellie, :status,
|
83
97
|
payload.get(:data, :nellie, :result, :complete) ? 'success' : 'error'
|
@@ -85,6 +99,47 @@ module Jackal
|
|
85
99
|
true
|
86
100
|
end
|
87
101
|
|
102
|
+
# Populate for pushing github release assets
|
103
|
+
#
|
104
|
+
# @param payload [Smash]
|
105
|
+
# @param nellie_cwd [String] working directory of repo
|
106
|
+
# @return [NilClass]
|
107
|
+
def set_github_release_assets(payload, nellie_cwd)
|
108
|
+
release_assets = Dir.glob(File.join(nellie_cwd, payload.get(:data, :nellie, :release_assets)))
|
109
|
+
unless(release_assets.empty?)
|
110
|
+
debug "Release assets detected: #{release_assets}"
|
111
|
+
release_asset_keys = release_assets.map do |asset|
|
112
|
+
asset_key = "nellie/release-assets/#{payload[:id]}/#{File.basename(asset)}"
|
113
|
+
asset_store.put(asset_key, File.open(asset, 'rb'))
|
114
|
+
asset_key
|
115
|
+
end
|
116
|
+
if(payload.get(:data, :code_fetcher, :info, :ref).to_s.include?('/tags/'))
|
117
|
+
version = payload.get(:data, :code_fetcher, :info, :ref).to_s.sub(/^.*\/tags\//, '')
|
118
|
+
else
|
119
|
+
version = payload.get(:data, :code_fetcher, :info, :commit_sha).to_s[0,6]
|
120
|
+
prerelease = true
|
121
|
+
end
|
122
|
+
payload.set(:data, :github_kit, :release,
|
123
|
+
Smash.new(
|
124
|
+
:repository => [
|
125
|
+
payload.get(:data, :code_fetcher, :info, :owner),
|
126
|
+
payload.get(:data, :code_fetcher, :info, :name)
|
127
|
+
].join('/'),
|
128
|
+
:reference => payload.get(:data, :code_fetcher, :info, :commit_sha),
|
129
|
+
:tag_name => version,
|
130
|
+
:name => [
|
131
|
+
payload.get(:data, :code_fetcher, :info, :name),
|
132
|
+
version
|
133
|
+
].join('-'),
|
134
|
+
:body => "Release - #{payload.get(:data, :code_fetcher, :info, :name)} <#{version}>",
|
135
|
+
:prerelease => prerelease,
|
136
|
+
:assets => release_asset_keys
|
137
|
+
)
|
138
|
+
)
|
139
|
+
nil
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
88
143
|
# Run collection of commands
|
89
144
|
#
|
90
145
|
# @param commands [Array<String>] commands to execute
|
@@ -96,9 +151,10 @@ module Jackal
|
|
96
151
|
results = []
|
97
152
|
commands.each do |command|
|
98
153
|
process_manager.process(payload[:id], command) do |process|
|
154
|
+
info "Running command `#{command}` in `#{process_cwd}`"
|
99
155
|
result = Smash.new
|
100
|
-
stdout = process_manager.create_io_tmp(
|
101
|
-
stderr = process_manager.create_io_tmp(
|
156
|
+
stdout = process_manager.create_io_tmp(payload[:id], 'stdout')
|
157
|
+
stderr = process_manager.create_io_tmp(payload[:id], 'stderr')
|
102
158
|
process.io.stdout = stdout
|
103
159
|
process.io.stderr = stderr
|
104
160
|
process.cwd = process_cwd
|
@@ -123,6 +179,8 @@ module Jackal
|
|
123
179
|
io.close
|
124
180
|
File.delete(io.path)
|
125
181
|
end
|
182
|
+
info "Completed command `#{command}` in `#{process_cwd}`. " \
|
183
|
+
"Runtime: #{result[:stop_time] - result[:start_time]} seconds"
|
126
184
|
results << result
|
127
185
|
unless(process.exit_code == 0)
|
128
186
|
payload.set(:data, :nellie, :result, :failed, true)
|
@@ -146,6 +204,8 @@ module Jackal
|
|
146
204
|
debug "Nellie file is structured data. Populating commands into payload. (#{script_path})"
|
147
205
|
payload[:data].set(:nellie, :commands, nellie_cmds[:commands])
|
148
206
|
payload[:data].set(:nellie, :environment, nellie_cmds.fetch(:environment, {}))
|
207
|
+
payload[:data].set(:nellie, :cleanup, Array(nellie_cmds[:cleanup])) if nellie_cmds[:cleanup]
|
208
|
+
payload[:data].set(:nellie, :release_assets, nellie_cmds[:release]) if nellie_cmds[:release]
|
149
209
|
rescue => e
|
150
210
|
debug "Parsing nellie file failed. Assuming direct execution. (#{script_path})"
|
151
211
|
payload[:data].set(:nellie, :commands,
|
@@ -167,17 +227,22 @@ module Jackal
|
|
167
227
|
repository_path = File.join(
|
168
228
|
working_directory,
|
169
229
|
payload[:id],
|
170
|
-
payload.get(:data, :code_fetcher, :asset)
|
230
|
+
payload.get(:data, :code_fetcher, :asset).sub(/\..*$/, '')
|
171
231
|
)
|
172
232
|
if(File.directory?(repository_path))
|
173
233
|
warn "Existing path detected for repository unpack. Removing! (#{repository_path})"
|
174
234
|
FileUtils.rm_rf(repository_path)
|
175
235
|
end
|
176
236
|
FileUtils.mkdir_p(File.dirname(repository_path))
|
237
|
+
code_asset = asset_store.get(payload.get(:data, :code_fetcher, :asset))
|
238
|
+
packed_code_asset_path = File.join(working_directory, "code-asset-#{payload[:id]}.zip")
|
239
|
+
FileUtils.cp(code_asset.path, packed_code_asset_path)
|
240
|
+
packed_code_asset = File.open(packed_code_asset_path, 'rb')
|
177
241
|
asset_store.unpack(
|
178
|
-
|
242
|
+
packed_code_asset,
|
179
243
|
repository_path
|
180
244
|
)
|
245
|
+
File.unlink(packed_code_asset_path)
|
181
246
|
repository_path
|
182
247
|
end
|
183
248
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jackal-nellie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Roberts
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-01-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: jackal
|
@@ -86,6 +86,7 @@ files:
|
|
86
86
|
- lib/jackal-nellie.rb
|
87
87
|
- lib/jackal-nellie/formatter.rb
|
88
88
|
- lib/jackal-nellie/formatter/github_commit_comment.rb
|
89
|
+
- lib/jackal-nellie/formatter/github_commit_status.rb
|
89
90
|
- lib/jackal-nellie/formatter/slack_comment.rb
|
90
91
|
- lib/jackal-nellie/processor.rb
|
91
92
|
- lib/jackal-nellie/version.rb
|
@@ -114,4 +115,3 @@ signing_key:
|
|
114
115
|
specification_version: 4
|
115
116
|
summary: Message processing helper
|
116
117
|
test_files: []
|
117
|
-
has_rdoc:
|