travis-api/lib/travis/model/build/matrix.rb
Aakriti Gupta 65f1a29d86 Move travis-core files from /vendor to /lib.
- Re-factor
- Remove code for notifications
- Remove addons
- Remove travis-core gem.
- Ignore logs directory only
- Move core tests to spec/lib
2016-07-20 11:22:25 +02:00

115 lines
3.6 KiB
Ruby

require 'active_support/concern'
require 'active_support/core_ext/hash/keys'
require 'core_ext/hash/deep_symbolize_keys'
class Build
# A Build contains a number of Job::Test instances that make up the build
# matrix.
#
# The matrix is defined in the build configuration (`.travis.yml`) and
# expanded (evaluated and instantiated) when the Build is created.
#
# A build matrix has 1 to 3 dimensions and can be defined by specifying
# multiple values for either of:
#
# * a language/vm variant (e.g. 1.9.2, rbx, jruby for a Ruby build)
# * a dependency definition (e.g. a Gemfile for a Ruby build)
# * an arbitrary env key that can be used from within the test suite in
# order to branch out specific variations of the test run
module Matrix
extend ActiveSupport::Concern
def matrix_finished?
if matrix_config.fast_finish?
required_jobs.all?(&:finished?) || required_jobs.any?(&:finished_unsuccessfully?)
else
matrix.all?(&:finished?)
end
end
def matrix_duration
matrix_finished? ? matrix.inject(0) { |duration, job| duration + job.duration.to_i } : nil
end
def matrix_state
if required_jobs.blank?
:passed
elsif required_jobs.any?(&:canceled?)
:canceled
elsif required_jobs.any?(&:errored?)
:errored
elsif required_jobs.any?(&:failed?)
:failed
elsif required_jobs.all?(&:passed?)
:passed
else
raise InvalidMatrixStateException.new(matrix)
end
end
# expand the matrix (i.e. create test jobs) and update the config for each job
def expand_matrix
matrix_config.expand.each_with_index do |row, ix|
attributes = self.attributes.slice(*Job.column_names - ['status', 'result']).symbolize_keys
attributes.merge!(
owner: owner,
number: "#{number}.#{ix + 1}",
config: row,
log: Log.new
)
matrix.build(attributes)
end
matrix_allow_failures # TODO should be able to join this with the loop above
matrix
end
def expand_matrix!
expand_matrix
save!
end
# Return only the child builds whose config matches against as passed hash
# e.g. build.filter_matrix(rvm: '1.8.7', env: 'DB=postgresql')
def filter_matrix(config)
config.blank? ? matrix : matrix.select { |job| job.matches_config?(config) }
end
private
def matrix_config
@matrix_config ||= Config::Matrix.new(config, multi_os: repository.multi_os_enabled?, dist_group_expansion: repository.dist_group_expansion_enabled?)
end
def matrix_allow_failures
configs = matrix_config.allow_failure_configs
jobs = configs.map { |config| filter_matrix(config) }.flatten
jobs.each { |job| job.allow_failure = true }
end
def required_jobs
@required_jobs ||= matrix.reject { |test| test.allow_failure? }
end
end
class InvalidMatrixStateException < StandardError
attr_reader :matrix
def initialize(matrix)
@matrix = matrix
end
def to_s
sanitized = matrix.map do |job|
"\n\tid: #{job.id}, repository: #{job.repository.slug}, state: #{job.state}, " +
"allow_failure: #{job.allow_failure}, " +
"created_at: #{job.created_at.inspect}, queued_at: #{job.queued_at.inspect}, " +
"started_at: #{job.started_at.inspect}, finished_at: #{job.finished_at.inspect}, " +
"canceled_at: #{job.canceled_at.inspect}, updated_at: #{job.updated_at.inspect}"
end.join
"Invalid build matrix state detected.\nMatrix: #{sanitized}"
end
end
end