cyclid 0.2.5 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|