-
Notifications
You must be signed in to change notification settings - Fork 422
Expand file tree
/
Copy pathscript.rb
More file actions
527 lines (461 loc) · 16.3 KB
/
script.rb
File metadata and controls
527 lines (461 loc) · 16.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
require 'core_ext/hash/deep_merge'
require 'core_ext/hash/deep_symbolize_keys'
require 'core_ext/object/false'
require 'erb'
require 'rbconfig'
require 'date'
require 'travis/build/addons'
require 'travis/build/appliances'
require 'travis/build/errors'
require 'travis/vcs'
require 'travis/build/helpers'
require 'travis/build/stages'
require 'travis/build/script/android'
require 'travis/build/script/c'
require 'travis/build/script/clojure'
require 'travis/build/script/cpp'
require 'travis/build/script/crystal'
require 'travis/build/script/csharp'
require 'travis/build/script/d'
require 'travis/build/script/dart'
require 'travis/build/script/erlang'
require 'travis/build/script/elixir'
require 'travis/build/script/go'
require 'travis/build/script/groovy'
require 'travis/build/script/generic'
require 'travis/build/script/haskell'
require 'travis/build/script/haxe'
require 'travis/build/script/julia'
require 'travis/build/script/matlab'
require 'travis/build/script/nix'
require 'travis/build/script/node_js'
require 'travis/build/script/elm'
require 'travis/build/script/objective_c'
require 'travis/build/script/perl'
require 'travis/build/script/perl6'
require 'travis/build/script/php'
require 'travis/build/script/pure_java'
require 'travis/build/script/python'
require 'travis/build/script/r'
require 'travis/build/script/ruby'
require 'travis/build/script/rust'
require 'travis/build/script/scala'
require 'travis/build/script/smalltalk'
require 'travis/build/script/shared/directory_cache'
require 'travis/build/script/shared/workspace'
module Travis
module Build
class Script
DEFAULTS = {}
TRAVIS_FUNCTIONS = %w[
travis_apt_get_update
travis_assert
travis_bash_qsort_numeric
travis_cleanup
travis_cmd
travis_decrypt
travis_download
travis_find_jdk_path
travis_fold
travis_footer
travis_install_jdk
travis_internal_ruby
travis_jigger
travis_jinfo_file
travis_key
travis_nanoseconds
travis_remove_from_path
travis_result
travis_retry
travis_setup_env
travis_setup_java
travis_temporary_hacks
travis_terminate
travis_time_finish
travis_time_start
travis_trace_span
travis_vers2int
travis_wait
travis_whereami
].freeze
private_constant :TRAVIS_FUNCTIONS
class << self
def defaults(key, server_type)
if key && self::DEFAULTS.key?(key.to_sym)
Travis::Vcs.defaults(server_type).merge self::DEFAULTS[key.to_sym]
elsif self::DEFAULTS[:default]
Travis::Vcs.defaults(server_type).merge self::DEFAULTS[:default]
else
Travis::Vcs.defaults(server_type).merge self::DEFAULTS
end
end
end
include Module.new do
Travis::Build::Stages::STAGES.map(&:name).flatten.each do |stage|
define_method(stage) {}
end
end
include Travis::Build::Appliances, Travis::Build::Script::DirectoryCache
include Travis::Build::Deprecation, Travis::Build::Bash
attr_reader :sh, :raw_data, :data, :options, :validator, :addons, :stages
attr_reader :root, :home_dir, :build_dir
attr_accessor :setup_cache_has_run_for
def initialize(data)
@raw_data = data.deep_symbolize_keys
raw_config = @raw_data[:config]
server_type = @raw_data.dig(:repository, :server_type) || 'git'
lang_sym = raw_config.fetch(:language,"").to_sym
@data = Data.new({
config: self.class.defaults(raw_config[:os], server_type),
language_default_p: !raw_config[lang_sym]
}.deep_merge(self.raw_data))
@options = {}
tracing_enabled = data[:trace]
@root = '/'
@home_dir = HOME_DIR
@build_dir = BUILD_DIR
@sh = Shell::Builder.new(tracing_enabled)
@addons = Addons.new(self, sh, self.data, config)
@stages = Stages.new(self, sh, config)
@setup_cache_has_run_for = {}
end
def compile(ignore_taint = false)
nodes = sexp
Shell.generate(nodes, ignore_taint)
rescue Travis::Shell::Generator::TaintedOutput => to
log_tainted_nodes(nodes)
raise to
rescue Exception => e
event = Travis::Build.config.sentry_dsn.empty? ? nil : Raven.capture_exception(e)
unless Travis::Build.config.dump_backtrace?
Travis::Build.logger.error(e)
Travis::Build.logger.error(e.backtrace)
end
if ENV['RACK_ENV'] == 'development'
raise e
end
show_compile_error_msg(e, event)
end
def sexp
run
sh.to_sexp
end
def log_tainted_nodes(nodes)
return unless Travis::Build.config.tainted_node_logging_enabled?
tainted_values = nodes.flatten.select(&:tainted?)
Travis::Build.logger.error(
"nodes contain tainted value(s) #{tainted_values.inspect}"
)
end
def cache_slug_keys
plain_env_vars = Array((config[:env] || []).dup).delete_if {|env| env.start_with? 'SECURE '}
[
'cache',
config[:os],
config[:dist],
config[:osx_image],
OpenSSL::Digest::SHA256.hexdigest(plain_env_vars.sort.join('='))
]
end
def cache_slug
cache_slug_keys.compact.join('-')
end
def archive_url_for(bucket, version, lang = lang_name, ext = 'bz2')
file_name = "#{[lang, version].compact.join("-")}.tar.#{ext}"
sh.if "$(uname) = 'Linux'" do
sh.raw "travis_host_os=$(lsb_release -is | tr 'A-Z' 'a-z')"
sh.raw "travis_rel_version=$(lsb_release -rs)"
end
sh.elif "$(uname) = 'Darwin'" do
sh.raw "travis_host_os=osx"
sh.raw "travis_rel=$(sw_vers -productVersion)"
sh.raw "travis_rel_version=${travis_rel%*.*}"
end
sh.elif "$(uname) = 'FreeBSD'" do
sh.raw "travis_host_os=freebsd"
sh.raw "travis_rel_version=$(uname -r | rev | cut -c9- | rev)"
end
lang = 'python' if lang.start_with?('py')
"archive_url=https://#{lang_archive_prefix(lang, bucket)}/binaries/${travis_host_os}/${travis_rel_version}/$(uname -m)/#{file_name}"
end
def lang_archive_prefix(lang, bucket)
custom_archive = ENV["TRAVIS_BUILD_LANG_ARCHIVES_#{lang}".upcase]
unless custom_archive.to_s.empty?
return custom_archive.output_safe
end
case Travis::Build.config.lang_archive_host
when 'gcs'
"storage.googleapis.com/travis-ci-language-archives/#{lang}"
when 's3'
"s3.amazonaws.com/#{bucket}"
when 'cdn'
"language-archives.travis-ci.com/#{lang}"
else
"s3.amazonaws.com/#{bucket}" # explicitly state default
end
end
def debug_build_via_api?
! data.debug_options.empty?
end
def config
data.config
end
def app_host
@app_host ||= Travis::Build.config.app_host.to_s.strip.output_safe
end
def debug_enabled?
Travis::Build.config.enable_debug_tools == '1'
end
private
def debug
if debug_build_via_api?
sh.echo "Debug build initiated by #{data.debug_options[:created_by]}", ansi: :yellow
if debug_quiet?
sh.raw "travis_debug --quiet"
else
sh.raw "travis_debug"
end
sh.newline
sh.echo "All remaining steps, including caching and deploy, will be skipped.", ansi: :yellow
end
end
def run
stages.run if apply :validate
sh.raw 'travis_cleanup'
sh.raw 'travis_footer'
# apply :deprecations
end
def header
sh.raw '#!/bin/bash'
sh.export 'TRAVIS_ROOT', root, echo: false, assert: false
sh.export 'TRAVIS_HOME', home_dir, echo: false, assert: false
sh.export 'TRAVIS_BUILD_DIR', build_dir, echo: false, assert: false
sh.export 'TRAVIS_INTERNAL_RUBY_REGEX', internal_ruby_regex_esc,
echo: false, assert: false
sh.export 'TRAVIS_APP_HOST', app_host,
echo: false, assert: false
sh.export 'TRAVIS_APT_PROXY', apt_proxy,
echo: false, assert: false
if Travis::Build.config.enable_infra_detection?
sh.export 'TRAVIS_ENABLE_INFRA_DETECTION', 'true',
echo: false, assert: false
end
sh.raw bash('travis_preamble')
sh.raw 'travis_preamble'
sh.file '${TRAVIS_HOME}/.travis/functions',
"# travis_.+ functions:\n" +
TRAVIS_FUNCTIONS.map { |f| bash(f) }.join("\n")
sh.file '${TRAVIS_HOME}/.travis/job_stages',
%[source "${TRAVIS_HOME}/.travis/functions"\n]
sh.raw 'source "${TRAVIS_HOME}/.travis/functions"'
sh.raw 'travis_setup_env'
sh.raw 'travis_temporary_hacks'
end
def internal_ruby_regex_esc
@internal_ruby_regex_esc ||= shesc(
Travis::Build.config.internal_ruby_regex.output_safe
)
end
def apt_proxy
@apt_proxy ||= Travis::Build.config.apt_proxy.output_safe
end
def configure
apply :agent
apply :check_unsupported
apply :set_x
apply :show_system_info
apply :rm_riak_source
apply :fix_rwky_redis
apply :wait_for_network
apply :update_apt_keys
apply :fix_hhvm_source
apply :update_mongo_arch
apply :fix_container_based_trusty
apply :fix_sudo_enabled_trusty
apply :update_glibc
apply :update_libssl
apply :clean_up_path
# Issues with cache dns in Focal
# apply :fix_resolv_conf
apply :fix_etc_hosts
apply :fix_mvn_settings_xml
apply :no_ipv6_localhost
apply :fix_etc_mavenrc
apply :etc_hosts_pinning
apply :fix_wwdr_certificate
apply :put_localhost_first
apply :home_paths
apply :disable_initramfs
apply :disable_ssh_roaming
apply :debug_tools
apply :npm_registry
apply :uninstall_oclint
apply :rvm_use
apply :rm_etc_boto_cfg
apply :rm_oraclejdk8_symlink
apply :enable_i386
apply :update_rubygems
apply :ensure_path_components
apply :redefine_curl
apply :nonblock_pipe
apply :apt_get_update
apply :deprecate_xcode_64
apply :update_heroku
apply :shell_session_update
apply :git_v2
apply :set_docker_mtu_and_registry_mirrors
apply :resolvconf
apply :maven_central_mirror
apply :maven_https
apply :disable_windows_defender
check_deprecation
end
def setup_filter
apply :vault_connect
apply :vault_keys
apply :no_world_writable_dirs
apply :setup_filter
end
def checkout
apply :checkout
end
def export
apply :env
end
def prepare
apply :services
apply :fix_ps4 # TODO if this is to fix an rvm issue (as the specs say) then should this go to Rvm instead?
end
def disable_sudo
apply :disable_sudo
end
def reset_state
if debug_build_via_api?
raise "Debug payload does not contain 'previous_state' value." unless previous_state = data.debug_options[:previous_state]
sh.newline
sh.echo "This is a debug build. The build result is reset to its previous value, \\\"#{previous_state}\\\".", ansi: :yellow
case previous_state
when "passed"
sh.export 'TRAVIS_TEST_RESULT', '0', echo: false
when "failed"
sh.export 'TRAVIS_TEST_RESULT', '1', echo: false
when "errored"
sh.raw 'travis_terminate 2'
end
end
end
def config_env_vars
@config_env_vars ||= Build::Env::Config.new(data, config)
Array(@config_env_vars.data[:env])
end
def host_os
case RbConfig::CONFIG["host_os"]
when /^(?i:linux)/
'$(lsb_release -is | tr "A-Z" "a-z")'
when /^(?i:darwin)/
'osx'
end
end
def rel_version
case RbConfig::CONFIG["host_os"]
when /^(?i:linux)/
'$(lsb_release -rs)'
when /^(?i:darwin)/
'${$(sw_vers -productVersion)%*.*}'
end
end
def debug_quiet?
debug_build_via_api? && data.debug_options[:quiet]
end
def error_message_ary(exception, event)
if event
contact_msg = ", or contact us at support@travis-ci.com"
if event.id
contact_msg << " with the error ID: #{event.id}"
end
else
contact_msg = ""
end
if exception.is_a? Travis::Build::CompilationError
msg = [
exception.message
]
doc_path = exception.doc_path
else
msg = [
"Unfortunately, we do not know much about this error."
]
doc_path = ''
end
[
"",
"There was an error in the .travis.yml file from which we could not recover.\n",
*msg,
"",
"Please review https://docs.travis-ci.com#{doc_path}#{contact_msg}"
]
end
def show_compile_error_msg(exception, event)
@sh = Shell::Builder.new
error_message_ary(exception, event).each { |line| sh.raw "echo -e \"\033[31;1m#{line}\033[0m\"" }
sh.raw "exit 2"
Shell.generate(sh.to_sexp)
end
def lang_name
self.class.name.split('::').last.downcase
end
def shesc(str)
Shellwords.escape(str)
end
def check_deprecation
return unless self.class.const_defined?("DEPRECATIONS")
self.class.const_get("DEPRECATIONS").each do |cfg|
if data.language_default_p && DateTime.now < Date.parse(cfg[:cutoff_date])
sh.echo "Using the default #{cfg[:name] || self.class.name} version #{cfg[:current_default]}. " \
"Starting on #{cfg[:cutoff_date]} the default will change to #{cfg[:new_default]}. " \
"If you wish to keep using this version beyond this date, " \
"please explicitly set the #{cfg[:name]} value in configuration.",
ansi: :yellow
end
end
end
def use_workspaces
return unless data.workspaces && data.workspaces.key?(:use)
ws_names = Array(data.workspaces[:use])
sh.fold "workspaces_use" do
ws_names.each do |name|
sh.echo "Fetching workspace #{shesc(name)}", ansi: :green
ws = Travis::Build::Script::Workspace.new(sh, data, name, [], :use)
ws.install_casher
ws.fetch
ws.expand
sh.newline
end
end
end
def create_workspaces
return unless data.workspaces && data.workspaces.key?(:create)
# data.workspaces[:create] is expected to be either:
# 1. a hash with keys :name and :paths, or
# 2. an array of hashes with these keys
ws_config = Array([data.workspaces[:create]]).flatten
sh.fold "workspaces_create" do
sh.echo "Creating workspaces", ansi: :green
ws_config.each do |cfg|
unless cfg.respond_to?(:key?) && cfg.key?(:name) && cfg.key?(:paths)
sh.echo "workspaces.create must be a hash with keys 'name' and 'paths', " \
"or an array of such hashes", ansi: :yellow
next
end
sh.echo "Workspace: #{shesc(cfg[:name])}", ansi: :green
ws = Travis::Build::Script::Workspace.new(sh, data, cfg[:name], cfg[:paths], :create)
ws.install_casher
ws.compress
ws.upload
sh.newline
end
end
end
end
end
end