cyclid 0.2.5 → 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/app/cyclid/controllers/users.rb +2 -2
- data/app/cyclid/controllers/users/document.rb +2 -1
- data/app/cyclid/job/evaluator.rb +102 -0
- data/app/cyclid/job/job.rb +22 -1
- data/app/cyclid/job/runner.rb +29 -5
- data/app/cyclid/job/stage.rb +1 -1
- data/app/cyclid/monkey_patches.rb +32 -5
- data/app/cyclid/plugins/action/command.rb +3 -3
- data/app/cyclid/plugins/action/email.rb +3 -3
- data/app/cyclid/plugins/action/log.rb +1 -1
- data/app/cyclid/plugins/action/script.rb +3 -3
- data/app/cyclid/plugins/action/slack.rb +3 -3
- data/app/cyclid/plugins/api/github/helpers.rb +33 -9
- data/app/cyclid/plugins/api/github/pull_request.rb +45 -13
- data/app/cyclid/plugins/api/github/push.rb +4 -4
- data/app/cyclid/plugins/provisioner/debian.rb +3 -3
- data/app/cyclid/plugins/provisioner/ubuntu.rb +5 -5
- data/app/cyclid/plugins/source/git.rb +1 -1
- data/lib/cyclid/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e7112455a4780d7e09049b9a7e248d41e70e4558
|
4
|
+
data.tar.gz: 5e7423b5c082b494a05d98ce46d87f1a72540111
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 48fedf1d7150d25fa45787d1e47dc07568488f92151d3237440ecc69d6f71586edc4687eaad16d706758295905d4bda58b860e72422821e0df6462a994f40f92
|
7
|
+
data.tar.gz: a95452bf58313dec14d44e8c9c277c9e42c7d0222dd7ed453bd0f730121b2ee5fdf994c827811a4e2c731dc5e05aae84594466b029b523613e4012bf289e2d49
|
@@ -23,9 +23,9 @@ module Cyclid
|
|
23
23
|
class UserController < ControllerBase
|
24
24
|
helpers do
|
25
25
|
# Remove sensitive data from the users data
|
26
|
-
def sanitize_user(user)
|
26
|
+
def sanitize_user(user, keys = %w(password secret))
|
27
27
|
user.delete_if do |key, _value|
|
28
|
-
|
28
|
+
keys.include? key
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
@@ -78,7 +78,8 @@ module Cyclid
|
|
78
78
|
user_hash = user.serializable_hash
|
79
79
|
user_hash['organizations'] = user.organizations.map(&:name)
|
80
80
|
|
81
|
-
|
81
|
+
# DO provide the users HMAC secret, in this instance
|
82
|
+
user_hash = sanitize_user(user_hash, ['password'])
|
82
83
|
|
83
84
|
return user_hash.to_json
|
84
85
|
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Copyright 2017 Liqwyd Ltd.
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
|
16
|
+
# Top level module for the core Cyclid code.
|
17
|
+
module Cyclid
|
18
|
+
# Module for the Cyclid API
|
19
|
+
module API
|
20
|
+
# Module for Cyclid Job related classes
|
21
|
+
module Job
|
22
|
+
# Evaluator exception class
|
23
|
+
class EvalException < RuntimeError
|
24
|
+
end
|
25
|
+
|
26
|
+
# Evalute an expression for "only_if" & "not_if"
|
27
|
+
class Evaluator
|
28
|
+
class << self
|
29
|
+
def only_if(statement, vars)
|
30
|
+
evaluate(statement, vars)
|
31
|
+
end
|
32
|
+
|
33
|
+
def not_if(statement, vars)
|
34
|
+
not evaluate(statement, vars) # rubocop:disable Style/Not
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def compare(lvalue, operator, rvalue)
|
40
|
+
case operator
|
41
|
+
# Loose (case insensitive) comparision
|
42
|
+
when '=='
|
43
|
+
lvalue.downcase == rvalue.downcase # rubocop:disable Performance/Casecmp
|
44
|
+
# Case sensitive/value comparision
|
45
|
+
when '===', 'eq'
|
46
|
+
lvalue == rvalue
|
47
|
+
# Not-equal
|
48
|
+
when '!=', 'ne'
|
49
|
+
lvalue != rvalue
|
50
|
+
# Less than
|
51
|
+
when '<', 'lt'
|
52
|
+
lvalue.to_f < rvalue.to_f
|
53
|
+
# Greater than
|
54
|
+
when '>', 'gt'
|
55
|
+
lvalue.to_f > rvalue.to_f
|
56
|
+
# Less than or equal
|
57
|
+
when '<=', 'le'
|
58
|
+
lvalue.to_f <= rvalue.to_f
|
59
|
+
# Greater than or equal
|
60
|
+
when '>=', 'ge'
|
61
|
+
lvalue.to_f >= rvalue.to_f
|
62
|
+
# Not an operator we know
|
63
|
+
else
|
64
|
+
raise EvalException, "unknown operator: #{operator}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def evaluate(statement, vars)
|
69
|
+
# Replace single % characters with escaped versions and interpolate
|
70
|
+
expr = statement.gsub(/%([^{])/, '%%\1') ** vars
|
71
|
+
|
72
|
+
# Evaluate for both string comparisons:
|
73
|
+
#
|
74
|
+
# 'string1' == 'string2'
|
75
|
+
#
|
76
|
+
# and numbers:
|
77
|
+
#
|
78
|
+
# 1 < 2
|
79
|
+
#
|
80
|
+
# Numbers can be integers, floats or percentages
|
81
|
+
#
|
82
|
+
# Only the ==, != and === operators are recognised for strings. All
|
83
|
+
# operators, including == & != are valid for Numbers: === is not a valid
|
84
|
+
# operator for numbers.
|
85
|
+
|
86
|
+
# rubocop:disable Metrics/LineLength
|
87
|
+
case expr
|
88
|
+
when /\A'(.*)' (==|!=|===) '(.*)'\Z/,
|
89
|
+
/\A([0-9]*|[0-9]*\.[0-9]*)%? (==|eq|!=|ne|<|lt|>|gt|<=|le|>=|ge) ([0-9]*|[0-9]*\.[0-9]*)%?\Z/
|
90
|
+
compare(Regexp.last_match[1],
|
91
|
+
Regexp.last_match[2],
|
92
|
+
Regexp.last_match[3])
|
93
|
+
else
|
94
|
+
raise EvalException, "unable to evaluate #{expr}"
|
95
|
+
end
|
96
|
+
# rubocop:enable Metrics/LineLength
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
data/app/cyclid/job/job.rb
CHANGED
@@ -134,14 +134,27 @@ module Cyclid
|
|
134
134
|
job_sequence << stage_success \
|
135
135
|
unless job_stage[:on_success].nil? or \
|
136
136
|
stage?(job_sequence, job_stage[:on_success])
|
137
|
-
stage_view.on_success = job_stage[:on_success]
|
138
137
|
|
138
|
+
# Set the on_success handler; if no explicit hander is defined, use
|
139
|
+
# the next stage in the sequence
|
140
|
+
success_stage = if job_stage[:on_success]
|
141
|
+
job_stage[:on_success]
|
142
|
+
else
|
143
|
+
next_stage(job_sequence, job_stage)
|
144
|
+
end
|
145
|
+
stage_view.on_success = success_stage
|
146
|
+
|
147
|
+
# Now set the on_failure failure
|
139
148
|
stage_failure = { stage: job_stage[:on_failure] }
|
140
149
|
job_sequence << stage_failure \
|
141
150
|
unless job_stage[:on_failure].nil? or \
|
142
151
|
stage?(job_sequence, job_stage[:on_failure])
|
143
152
|
stage_view.on_failure = job_stage[:on_failure]
|
144
153
|
|
154
|
+
# Merge in any modifiers
|
155
|
+
stage_view.only_if = job_stage[:only_if]
|
156
|
+
stage_view.not_if = job_stage[:not_if]
|
157
|
+
|
145
158
|
# Store the modified StageView
|
146
159
|
stages[stage_view.name.to_sym] = stage_view
|
147
160
|
end
|
@@ -158,6 +171,14 @@ module Cyclid
|
|
158
171
|
end
|
159
172
|
return found
|
160
173
|
end
|
174
|
+
|
175
|
+
# Get the directly proceeding stage in the sequence
|
176
|
+
def next_stage(sequence, stage)
|
177
|
+
idx = sequence.index stage
|
178
|
+
|
179
|
+
next_stage = sequence.at(idx + 1)
|
180
|
+
next_stage.nil? ? nil : next_stage['stage']
|
181
|
+
end
|
161
182
|
end
|
162
183
|
end
|
163
184
|
end
|
data/app/cyclid/job/runner.rb
CHANGED
@@ -124,13 +124,37 @@ module Cyclid
|
|
124
124
|
stage_definition = stages[sequence.to_sym]
|
125
125
|
stage = Oj.load(stage_definition, symbol_keys: true)
|
126
126
|
|
127
|
-
|
128
|
-
|
127
|
+
# Evaluate any only_if/not_if expressions. Always run the stage if there are no
|
128
|
+
# modifiers.
|
129
|
+
do_run = if stage.only_if
|
130
|
+
Evaluator.only_if(stage.only_if, @ctx)
|
131
|
+
elsif stage.not_if
|
132
|
+
Evaluator.not_if(stage.not_if, @ctx)
|
133
|
+
else
|
134
|
+
true
|
135
|
+
end
|
136
|
+
|
137
|
+
if do_run
|
138
|
+
@notifier.write "#{'-' * 79}\n#{Time.now} : " \
|
139
|
+
"Running stage #{stage.name} v#{stage.version}\n"
|
140
|
+
|
141
|
+
# Run the stage
|
142
|
+
success, rc = run_stage(stage)
|
143
|
+
|
144
|
+
Cyclid.logger.info "stage #{(success ? 'succeeded' : 'failed')} and returned #{rc}"
|
145
|
+
else
|
146
|
+
@notifier.write "#{'-' * 79}\n#{Time.now} : " \
|
147
|
+
"Skipping stage #{stage.name} v#{stage.version}\n"
|
129
148
|
|
130
|
-
|
131
|
-
|
149
|
+
# Skip this stage; assume success
|
150
|
+
success = true
|
151
|
+
rc = 0
|
132
152
|
|
133
|
-
|
153
|
+
# rubocop:disable Style/MultilineTernaryOperator
|
154
|
+
Cyclid.logger.info "stage skipped due to #{stage.only_if ? \
|
155
|
+
"only_if #{stage.only_if}" : "not_if #{stage.not_if}"}"
|
156
|
+
# rubocop:enable Style/MultilineTernaryOperator
|
157
|
+
end
|
134
158
|
|
135
159
|
# Decide which stage to run next depending on the outcome of this
|
136
160
|
# one
|
data/app/cyclid/job/stage.rb
CHANGED
@@ -25,7 +25,7 @@ module Cyclid
|
|
25
25
|
# the database object.
|
26
26
|
class StageView
|
27
27
|
attr_reader :name, :version, :steps
|
28
|
-
attr_accessor :on_success, :on_failure
|
28
|
+
attr_accessor :on_success, :on_failure, :only_if, :not_if
|
29
29
|
|
30
30
|
def initialize(arg)
|
31
31
|
if arg.is_a? Cyclid::API::Stage
|
@@ -9,10 +9,10 @@ class Hash
|
|
9
9
|
end
|
10
10
|
|
11
11
|
# Interpolate the data in the ctx hash into any String values
|
12
|
-
def
|
12
|
+
def %(other)
|
13
13
|
hmap do |key, value|
|
14
14
|
if value.is_a? String
|
15
|
-
{ key => value
|
15
|
+
{ key => value ** other }
|
16
16
|
else
|
17
17
|
{ key => value }
|
18
18
|
end
|
@@ -23,15 +23,42 @@ end
|
|
23
23
|
# Add a method to Array
|
24
24
|
class Array
|
25
25
|
# Interpolate the data in the ctx hash for each String & Hash item
|
26
|
-
def
|
26
|
+
def %(other)
|
27
27
|
map do |entry|
|
28
28
|
if entry.is_a? Hash
|
29
|
-
entry
|
29
|
+
entry % other
|
30
30
|
elsif entry.is_a? String
|
31
|
-
entry
|
31
|
+
entry ** other
|
32
32
|
else
|
33
33
|
entry
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
37
37
|
end
|
38
|
+
|
39
|
+
# Add a method to String
|
40
|
+
class String
|
41
|
+
# Provide a "safe" version of the % (interpolation) operator; if a key does
|
42
|
+
# not exist in arg, catch the KeyError and insert it as a nil value, and
|
43
|
+
# continue.
|
44
|
+
#
|
45
|
+
# We're using the ** operator as it's one that isn't already used by String,
|
46
|
+
# and it's abusing % already so hey, why not. FTP
|
47
|
+
def **(other)
|
48
|
+
res = nil
|
49
|
+
arg = other ? other.dup : {}
|
50
|
+
|
51
|
+
begin
|
52
|
+
res = self % arg
|
53
|
+
rescue KeyError => ex
|
54
|
+
# Extract the key name from the exception message (sigh)
|
55
|
+
match = ex.message.match(/\Akey{(.*)} not found\Z/)
|
56
|
+
key = match[1]
|
57
|
+
|
58
|
+
# Inject key with a default value and try again
|
59
|
+
arg[key.to_sym] = nil
|
60
|
+
end while res.nil? # rubocop:disable Lint/Loop
|
61
|
+
|
62
|
+
return res
|
63
|
+
end
|
64
|
+
end
|
@@ -55,7 +55,7 @@ module Cyclid
|
|
55
55
|
def perform(log)
|
56
56
|
begin
|
57
57
|
# Export the environment data to the build host, if necesary
|
58
|
-
env = @env
|
58
|
+
env = @env % @ctx if @env
|
59
59
|
@transport.export_env(env)
|
60
60
|
|
61
61
|
# Log the command being run (and the working directory, if one is
|
@@ -64,11 +64,11 @@ module Cyclid
|
|
64
64
|
log.write(@path.nil? ? "$ #{cmd_args}\n" : "$ #{@path} : #{cmd_args}\n")
|
65
65
|
|
66
66
|
# Interpolate any data from the job context
|
67
|
-
cmd_args = cmd_args
|
67
|
+
cmd_args = cmd_args ** @ctx
|
68
68
|
|
69
69
|
# Interpolate the path if one is set
|
70
70
|
path = @path
|
71
|
-
path = path
|
71
|
+
path = path ** @ctx unless path.nil?
|
72
72
|
|
73
73
|
# Run the command
|
74
74
|
success = @transport.exec(cmd_args, path)
|
@@ -51,9 +51,9 @@ module Cyclid
|
|
51
51
|
"as #{email_config[:from]}"
|
52
52
|
|
53
53
|
# Add the job context
|
54
|
-
to = @to
|
55
|
-
subject = @subject
|
56
|
-
message = @message
|
54
|
+
to = @to ** @ctx
|
55
|
+
subject = @subject ** @ctx
|
56
|
+
message = @message ** @ctx
|
57
57
|
|
58
58
|
# Create a binding for the text & HTML ERB templates
|
59
59
|
info = { color: @color, title: subject }
|
@@ -56,12 +56,12 @@ module Cyclid
|
|
56
56
|
def perform(log)
|
57
57
|
begin
|
58
58
|
# Export the environment data to the build host, if necesary
|
59
|
-
env = @env
|
59
|
+
env = @env % @ctx if @env
|
60
60
|
@transport.export_env(env)
|
61
61
|
|
62
62
|
# Add context data
|
63
|
-
script = @script
|
64
|
-
path = @path
|
63
|
+
script = @script ** @ctx
|
64
|
+
path = @path ** @ctx
|
65
65
|
|
66
66
|
# Create an IO object containing the script and upload it to the
|
67
67
|
# build host
|
@@ -43,15 +43,15 @@ module Cyclid
|
|
43
43
|
Cyclid.logger.debug "using plugin config #{plugin_data}"
|
44
44
|
config = plugin_data['config']
|
45
45
|
|
46
|
-
subject = @subject
|
46
|
+
subject = @subject ** @ctx
|
47
47
|
|
48
48
|
url = @url || config['webhook_url']
|
49
49
|
raise 'no webhook URL given' if url.nil?
|
50
50
|
|
51
|
-
url = url
|
51
|
+
url = url ** @ctx
|
52
52
|
Cyclid.logger.debug "sending notification to #{url}"
|
53
53
|
|
54
|
-
message_text = @message
|
54
|
+
message_text = @message ** @ctx if @message
|
55
55
|
|
56
56
|
# Create a binding for the template
|
57
57
|
bind = binding
|
@@ -33,8 +33,8 @@ module Cyclid
|
|
33
33
|
@pr_head ||= pull_request['head']
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
37
|
-
|
36
|
+
def pr_base
|
37
|
+
@pr_base ||= pull_request['base']
|
38
38
|
end
|
39
39
|
|
40
40
|
def pr_sha
|
@@ -45,22 +45,29 @@ module Cyclid
|
|
45
45
|
pr_head['ref']
|
46
46
|
end
|
47
47
|
|
48
|
-
def
|
49
|
-
@
|
48
|
+
def pr_base_repo
|
49
|
+
@pr_base_repo ||= pr_base['repo']
|
50
50
|
end
|
51
51
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
52
|
+
def pr_base_url
|
53
|
+
pr_base_repo['html_url']
|
54
|
+
end
|
55
|
+
|
56
|
+
def pr_head_repo
|
57
|
+
@pr_head_repo ||= pr_head['repo']
|
58
|
+
end
|
59
|
+
|
60
|
+
def pr_head_url
|
61
|
+
pr_head_repo['html_url']
|
55
62
|
end
|
56
63
|
|
57
64
|
def pr_trees_url
|
58
|
-
url =
|
65
|
+
url = pr_head_repo['trees_url']
|
59
66
|
@pr_trees_url ||= url.gsub('{/sha}', "/#{pr_sha}")
|
60
67
|
end
|
61
68
|
|
62
69
|
def pr_repository
|
63
|
-
@repo ||= Octokit::Repository.from_url(
|
70
|
+
@repo ||= Octokit::Repository.from_url(pr_base_url)
|
64
71
|
end
|
65
72
|
|
66
73
|
def push_head_commit
|
@@ -131,6 +138,23 @@ module Cyclid
|
|
131
138
|
state = "#{org.name}:#{org.salt}:#{org.owner_email}"
|
132
139
|
Base64.urlsafe_encode64(Digest::SHA256.digest(state))
|
133
140
|
end
|
141
|
+
|
142
|
+
# Normalize a Github URL into a Cyclid style source definition
|
143
|
+
def normalize(url)
|
144
|
+
uri = URI.parse(url)
|
145
|
+
|
146
|
+
source = {}
|
147
|
+
source['url'] = "#{uri.scheme}://#{uri.host}#{uri.path.gsub(/.git$/, '')}"
|
148
|
+
source['token'] = uri.user if uri.user
|
149
|
+
source['branch'] = uri.fragment if uri.fragment
|
150
|
+
|
151
|
+
source
|
152
|
+
end
|
153
|
+
|
154
|
+
# Extract the "humanish" part from a Git repository URL
|
155
|
+
def humanish(uri)
|
156
|
+
uri.path.split('/').last.gsub('.git', '')
|
157
|
+
end
|
134
158
|
end
|
135
159
|
end
|
136
160
|
end
|
@@ -43,7 +43,7 @@ module Cyclid
|
|
43
43
|
|
44
44
|
# Get the list of files in the root of the repository in the
|
45
45
|
# Pull Request branch
|
46
|
-
clone_url = URI(
|
46
|
+
clone_url = URI(pr_head_url)
|
47
47
|
|
48
48
|
# Get the authentication key
|
49
49
|
auth_token = find_oauth_token(config, clone_url)
|
@@ -78,15 +78,19 @@ module Cyclid
|
|
78
78
|
job_definition = load_job_file(pr_repository, job_sha, job_type)
|
79
79
|
|
80
80
|
# Insert this repository & branch into the sources
|
81
|
+
clone_source = normalize(clone_url.to_s)
|
82
|
+
clone_source['type'] = 'git'
|
83
|
+
clone_source['branch'] = pr_ref
|
84
|
+
clone_source['token'] = auth_token
|
85
|
+
|
86
|
+
# We need to avoid causing a collision between the PR source
|
87
|
+
# (which may be from a forked repo) and any source definitions
|
88
|
+
# which may exist in the job file (which may be the "base"
|
89
|
+
# repository.
|
81
90
|
#
|
82
|
-
#
|
83
|
-
#
|
84
|
-
|
85
|
-
job_sources = job_definition['sources'] || []
|
86
|
-
job_sources << { 'type' => 'git',
|
87
|
-
'url' => clone_url.to_s,
|
88
|
-
'branch' => pr_ref,
|
89
|
-
'token' => auth_token }
|
91
|
+
# Compare everything and try to match any duplicates, and
|
92
|
+
# flatten the sources.
|
93
|
+
job_sources = insert_or_update_source(job_definition['sources'] || [], clone_source)
|
90
94
|
job_definition['sources'] = job_sources
|
91
95
|
|
92
96
|
Cyclid.logger.debug "sources=#{job_definition['sources']}"
|
@@ -110,10 +114,10 @@ module Cyclid
|
|
110
114
|
linkback_url = "#{ui_url}/#{organization_name}"
|
111
115
|
|
112
116
|
# Inject some useful context data
|
113
|
-
ctx = {
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
+
ctx = { github_event: 'pull_request',
|
118
|
+
github_user: pull_request['user']['login'],
|
119
|
+
github_ref: pr_ref,
|
120
|
+
github_comment: pull_request['title'] }
|
117
121
|
|
118
122
|
callback = GithubCallback.new(auth_token, pr_repository, pr_sha, linkback_url)
|
119
123
|
job_from_definition(job_definition, callback, ctx)
|
@@ -126,6 +130,34 @@ module Cyclid
|
|
126
130
|
|
127
131
|
return true
|
128
132
|
end
|
133
|
+
|
134
|
+
# Either insert (append) the Pull Request head repository, or
|
135
|
+
# replace an existing definition; for example if the job contains
|
136
|
+
# a source definition for "https://github.com/foo/bar" and the PR
|
137
|
+
# head is "https://github.com/baz/bar", replace "foo/bar" with
|
138
|
+
# "baz/bar"
|
139
|
+
def insert_or_update_source(sources, new_source)
|
140
|
+
updated = false
|
141
|
+
new_uri = URI.parse(new_source['url'])
|
142
|
+
|
143
|
+
normalized = sources.map do |source|
|
144
|
+
uri = URI.parse(source['url'])
|
145
|
+
next unless uri.scheme =~ /\Ahttps?\z/
|
146
|
+
|
147
|
+
# If the "humanish" components match, use the new definition.
|
148
|
+
if humanish(uri) == humanish(new_uri)
|
149
|
+
updated = true
|
150
|
+
new_source
|
151
|
+
else
|
152
|
+
source
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# If we didn't update an existing source definition, insert the new one
|
157
|
+
normalized << new unless updated
|
158
|
+
|
159
|
+
normalized.compact
|
160
|
+
end
|
129
161
|
end
|
130
162
|
end
|
131
163
|
end
|
@@ -97,10 +97,10 @@ module Cyclid
|
|
97
97
|
linkback_url = "#{ui_url}/#{organization_name}"
|
98
98
|
|
99
99
|
# Inject some useful context data
|
100
|
-
ctx = {
|
101
|
-
|
102
|
-
|
103
|
-
|
100
|
+
ctx = { github_event: 'push',
|
101
|
+
github_user: @payload['sender']['login'],
|
102
|
+
github_ref: push_ref,
|
103
|
+
github_comment: push_head_commit['message'] }
|
104
104
|
|
105
105
|
callback = GithubCallback.new(auth_token, push_repository, push_sha, linkback_url)
|
106
106
|
job_from_definition(job_definition, callback, ctx)
|
@@ -26,7 +26,7 @@ module Cyclid
|
|
26
26
|
transport.export_env('DEBIAN_FRONTEND' => 'noninteractive')
|
27
27
|
|
28
28
|
# Build hosts may require an update before anything can be installed
|
29
|
-
success = transport.exec 'apt-get update'
|
29
|
+
success = transport.exec 'apt-get update -qq'
|
30
30
|
raise 'failed to update repositories' unless success
|
31
31
|
|
32
32
|
if env.key? :repos
|
@@ -44,13 +44,13 @@ module Cyclid
|
|
44
44
|
end
|
45
45
|
|
46
46
|
# We must update again to cache the new repositories
|
47
|
-
success = transport.exec 'apt-get update'
|
47
|
+
success = transport.exec 'apt-get update -q'
|
48
48
|
raise 'failed to update repositories' unless success
|
49
49
|
end
|
50
50
|
|
51
51
|
if env.key? :packages
|
52
52
|
success = transport.exec \
|
53
|
-
"apt-get install -y #{env[:packages].join(' ')}" \
|
53
|
+
"apt-get install -q -y #{env[:packages].join(' ')}" \
|
54
54
|
|
55
55
|
raise "failed to install packages #{env[:packages].join(' ')}" unless success
|
56
56
|
end
|
@@ -26,12 +26,12 @@ module Cyclid
|
|
26
26
|
transport.export_env('DEBIAN_FRONTEND' => 'noninteractive')
|
27
27
|
|
28
28
|
# Build hosts may require an update before anything can be installed
|
29
|
-
success = transport.exec 'apt-get update'
|
29
|
+
success = transport.exec 'apt-get update -qq'
|
30
30
|
raise 'failed to update repositories' unless success
|
31
31
|
|
32
32
|
if env.key? :repos
|
33
|
-
# Ensure apt-
|
34
|
-
transport.exec 'apt-get install -y software-properties-common'
|
33
|
+
# Ensure apt-add-repository is available
|
34
|
+
transport.exec 'apt-get install -qq -y software-properties-common'
|
35
35
|
|
36
36
|
env[:repos].each do |repo|
|
37
37
|
next unless repo.key? :url
|
@@ -50,13 +50,13 @@ module Cyclid
|
|
50
50
|
end
|
51
51
|
|
52
52
|
# We must update again to cache the new repositories
|
53
|
-
success = transport.exec 'apt-get update'
|
53
|
+
success = transport.exec 'apt-get update -q'
|
54
54
|
raise 'failed to update repositories' unless success
|
55
55
|
end
|
56
56
|
|
57
57
|
if env.key? :packages
|
58
58
|
success = transport.exec \
|
59
|
-
"apt-get install -y #{env[:packages].join(' ')}" \
|
59
|
+
"apt-get install -q -y #{env[:packages].join(' ')}" \
|
60
60
|
|
61
61
|
raise "failed to install packages #{env[:packages].join(' ')}" unless success
|
62
62
|
end
|
data/lib/cyclid/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cyclid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kristian Van Der Vliet
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-02-
|
11
|
+
date: 2017-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: oj
|
@@ -374,6 +374,7 @@ files:
|
|
374
374
|
- app/cyclid/controllers/users/document.rb
|
375
375
|
- app/cyclid/health_helpers.rb
|
376
376
|
- app/cyclid/job.rb
|
377
|
+
- app/cyclid/job/evaluator.rb
|
377
378
|
- app/cyclid/job/helpers.rb
|
378
379
|
- app/cyclid/job/job.rb
|
379
380
|
- app/cyclid/job/runner.rb
|