-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
build-ci
executable file
·135 lines (111 loc) · 3.19 KB
/
build-ci
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
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'fileutils'
require 'pathname'
class Project
include FileUtils
attr_reader :name, :title, :weight, :status
ROOT = Pathname("#{__dir__}/..").expand_path.freeze
def initialize(name, test_type: :rspec, title: nil, weight:)
@name = name
@title = title || name
@test_type = test_type
@weight = weight
@status = :pending
end
def self.all
[
new('admin', weight: 102),
new('api', weight: 69),
new('backend', weight: 282),
new('backend', test_type: :teaspoon, title: "backend JS", weight: 18),
new('core', weight: 266),
new('sample', weight: 28),
new('legacy_promotions', weight: 63)
]
end
# Return the projects active on the current node
#
# @return [Array<Project>]
def self.weighted_projects(node_total:, node_index:)
unallocated = all.sort_by(&:weight).reverse
nodes = Array.new(node_total) { [] }
while project = unallocated.shift
nodes.min_by { |projects| projects.sum(&:weight) } << project
end
nodes[node_index].tap do |projects|
warn("Selected #{projects.length} projects(s) on node #{node_index.succ} / #{node_total}")
projects.each { warn("- #{_1.name}") }
end
end
# Run projects specs
# @param [Array<Project>] projects
# @return [Boolean] success of the run
def self.run(projects = current_projects)
warn("=" * 80)
warn("Running projects: #{projects.map(&:name).join(', ')}")
projects.each do |project|
warn("=" * 80)
warn("Building: #{project.name}")
project.run
end
warn("=" * 80)
warn("Results:")
projects.each do |project|
warn("- #{project.name} #{project.status.to_s.upcase}")
end
warn("=" * 80)
projects.all? { _1.status == :success }
end
# Run specs for the project
def run
@status = :running
chdir ROOT.join(name) do
@status = send(:"run_#{@test_type}") ? :success : :failure
end
rescue Interrupt
@status = :interrupted
rescue StandardError => e
warn(e)
@status = :error
end
private
def run_rspec
run_test_cmd(%W[
bundle exec rspec
--profile 10
--format documentation
--require rspec_junit_formatter --format RspecJunitFormatter --out #{report_dir}/#{name}.xml
])
end
def run_teaspoon
run_test_cmd(%W[
bundle exec teaspoon
--require=spec/teaspoon_env.rb
--format=documentation,junit>#{report_dir}/#{name}_js.xml
])
end
def run_test_cmd(args)
puts "Run: #{args.join(' ')}"
system(*args).tap { puts(_1 ? "Success" : "Failed") }
end
def report_dir
base_dir = Pathname(ENV['CIRCLE_TEST_REPORTS'] || ROOT.join("tmp/test-reports/#{@test_type}"))
base_dir.join('rspec').tap { mkdir_p _1 }
end
end
if ENV['CIRCLE_NODE_INDEX'] # Run projects on a CI node
projects = Project.weighted_projects(
node_total: Integer(ENV.fetch('CIRCLE_NODE_TOTAL', 1)),
node_index: Integer(ENV.fetch('CIRCLE_NODE_INDEX', 0)),
)
else
projects = Project.all
end
# Run a single project if requested
projects.select! { _1.title == ARGV.first } if ARGV.first
if projects.empty?
warn("No projects to run")
exit 0
end
exit Project.run(projects)