performa 0.1.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 +7 -0
- data/.gitignore +16 -0
- data/.rspec +3 -0
- data/.rubocop.yml +33 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +62 -0
- data/README.md +15 -0
- data/Rakefile +8 -0
- data/bin/console +16 -0
- data/bin/setup +8 -0
- data/exe/performa +41 -0
- data/lib/performa.rb +17 -0
- data/lib/performa/configuration.rb +54 -0
- data/lib/performa/container_id.rb +18 -0
- data/lib/performa/container_registry.rb +30 -0
- data/lib/performa/coordinator.rb +34 -0
- data/lib/performa/environment.rb +37 -0
- data/lib/performa/images.rb +65 -0
- data/lib/performa/logger.rb +24 -0
- data/lib/performa/results_helper.rb +48 -0
- data/lib/performa/shell_helper.rb +43 -0
- data/lib/performa/stages.rb +17 -0
- data/lib/performa/version.rb +5 -0
- data/performa.gemspec +31 -0
- metadata +87 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f6435a998ab87cdad87f5dceb1ff410c8f081aabe5ef10fc360479d7bd1e97fc
|
4
|
+
data.tar.gz: 2f3a401bae1c21ef9d3bb42d084b19b79dc4e61486028f2a42b9e7dc44d632e9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7792a8296acd422c3d6cd0819f00b509311f57de99b042917e99232d31be9c8c17f76805dd6d501dd28b19ab128b81dd69b4ca7eb0046145bac9be8df21cb405
|
7
|
+
data.tar.gz: fe0205c9b1cf8cfb9bacf9b5b2afaa0a1f077f54e1ba5faa591c1613b67adf29eb82b362782696473c5910e0174b917c3ef41a4557c139adb29a214c2b8aefdd
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.6
|
3
|
+
|
4
|
+
Metrics/LineLength:
|
5
|
+
Max: 130
|
6
|
+
AllowHeredoc: true
|
7
|
+
AllowURI: true
|
8
|
+
IgnoreCopDirectives: true
|
9
|
+
Exclude:
|
10
|
+
- "spec/**/*"
|
11
|
+
|
12
|
+
# This cop checks the line count inside blocks.
|
13
|
+
# All RSpec code is in the same block for each file.
|
14
|
+
# Enabling this for spec/ would require cutting up the spec files in several parts.
|
15
|
+
|
16
|
+
Metrics/BlockLength:
|
17
|
+
Exclude:
|
18
|
+
- "spec/**/*"
|
19
|
+
|
20
|
+
Style/StringLiterals:
|
21
|
+
Enabled: true
|
22
|
+
EnforcedStyle: "double_quotes"
|
23
|
+
|
24
|
+
# This cop checks for missing top-level documentation of classes and modules.
|
25
|
+
# Classes with no body are exempt from the check and so are namespace modules -
|
26
|
+
# modules that have nothing in their bodies except classes, other modules,
|
27
|
+
# or constant definitions.
|
28
|
+
|
29
|
+
Style/Documentation:
|
30
|
+
Enabled: false
|
31
|
+
|
32
|
+
Metrics/MethodLength:
|
33
|
+
Max: 30
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.6.0-dev
|
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
6
|
+
|
7
|
+
# Specify your gem's dependencies in performa.gemspec
|
8
|
+
gemspec
|
9
|
+
|
10
|
+
gem "bundler"
|
11
|
+
gem "byebug"
|
12
|
+
gem "rake"
|
13
|
+
gem "rspec"
|
14
|
+
gem "rubocop", github: "rubocop-hq/rubocop"
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
GIT
|
2
|
+
remote: https://github.com/rubocop-hq/rubocop
|
3
|
+
revision: e74002ce0cf4367b3cebd580523b07ea2a59bf55
|
4
|
+
specs:
|
5
|
+
rubocop (0.60.0)
|
6
|
+
jaro_winkler (~> 1.5.1)
|
7
|
+
parallel (~> 1.10)
|
8
|
+
parser (>= 2.5, != 2.5.1.1)
|
9
|
+
powerpack (~> 0.1)
|
10
|
+
rainbow (>= 2.2.2, < 4.0)
|
11
|
+
ruby-progressbar (~> 1.7)
|
12
|
+
unicode-display_width (~> 1.4.0)
|
13
|
+
|
14
|
+
PATH
|
15
|
+
remote: .
|
16
|
+
specs:
|
17
|
+
performa (0.1.0)
|
18
|
+
colorize (~> 0.8)
|
19
|
+
|
20
|
+
GEM
|
21
|
+
remote: https://rubygems.org/
|
22
|
+
specs:
|
23
|
+
ast (2.4.0)
|
24
|
+
byebug (10.0.2)
|
25
|
+
colorize (0.8.1)
|
26
|
+
diff-lcs (1.3)
|
27
|
+
jaro_winkler (1.5.1)
|
28
|
+
parallel (1.12.1)
|
29
|
+
parser (2.5.3.0)
|
30
|
+
ast (~> 2.4.0)
|
31
|
+
powerpack (0.1.2)
|
32
|
+
rainbow (3.0.0)
|
33
|
+
rake (10.5.0)
|
34
|
+
rspec (3.8.0)
|
35
|
+
rspec-core (~> 3.8.0)
|
36
|
+
rspec-expectations (~> 3.8.0)
|
37
|
+
rspec-mocks (~> 3.8.0)
|
38
|
+
rspec-core (3.8.0)
|
39
|
+
rspec-support (~> 3.8.0)
|
40
|
+
rspec-expectations (3.8.2)
|
41
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
42
|
+
rspec-support (~> 3.8.0)
|
43
|
+
rspec-mocks (3.8.0)
|
44
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
45
|
+
rspec-support (~> 3.8.0)
|
46
|
+
rspec-support (3.8.0)
|
47
|
+
ruby-progressbar (1.10.0)
|
48
|
+
unicode-display_width (1.4.0)
|
49
|
+
|
50
|
+
PLATFORMS
|
51
|
+
ruby
|
52
|
+
|
53
|
+
DEPENDENCIES
|
54
|
+
bundler
|
55
|
+
byebug
|
56
|
+
performa!
|
57
|
+
rake
|
58
|
+
rspec
|
59
|
+
rubocop!
|
60
|
+
|
61
|
+
BUNDLED WITH
|
62
|
+
2.0.0.pre.1
|
data/README.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Performa
|
2
|
+
|
3
|
+
Automate scripts on multiple docker setups.
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
TODO: ...
|
8
|
+
|
9
|
+
## Development
|
10
|
+
|
11
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
12
|
+
|
13
|
+
## Contributing
|
14
|
+
|
15
|
+
Bug reports and pull requests are welcome on GitHub at [https://github.com/christophemaximin/performa](https://github.com/christophemaximin/performa).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "performa"
|
6
|
+
require "byebug"
|
7
|
+
|
8
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
9
|
+
# with your gem easier. You can also use a different console, if you like.
|
10
|
+
|
11
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
12
|
+
# require "pry"
|
13
|
+
# Pry.start
|
14
|
+
|
15
|
+
require "irb"
|
16
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/exe/performa
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
lib = File.expand_path("../lib", __dir__)
|
5
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
6
|
+
|
7
|
+
require "byebug" if ENV["DEBUG"]
|
8
|
+
require "performa"
|
9
|
+
require "optionparser"
|
10
|
+
|
11
|
+
options = Struct.new(:config_file).new
|
12
|
+
|
13
|
+
OptionParser.new do |opts|
|
14
|
+
opts.banner = [
|
15
|
+
"Usage: performa [-c config-file.yml]",
|
16
|
+
"Default config files considered: #{Performa::Configuration::DEFAULT_FILES.join(', ')}\n\n"
|
17
|
+
].join("\n")
|
18
|
+
|
19
|
+
opts.on("-c", "--config-file [file]", "Performa config file to use") do |file|
|
20
|
+
options.config_file = file
|
21
|
+
end
|
22
|
+
|
23
|
+
opts.on("--clear-cached", "Remove all Performa generated docker images (#{Performa::Images::CACHED_IMAGES_NAME}:*)") do
|
24
|
+
Performa::Images.clear_cached
|
25
|
+
exit 0
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on("-h", "--help", "Prints this help") do
|
29
|
+
puts opts
|
30
|
+
exit 0
|
31
|
+
end
|
32
|
+
end.parse!
|
33
|
+
|
34
|
+
begin
|
35
|
+
config = Performa::Configuration.new(options.config_file)
|
36
|
+
Performa::Coordinator.run(config)
|
37
|
+
rescue StandardError => e
|
38
|
+
Performa::LOG.error(e.message)
|
39
|
+
Performa::LOG.error(e.backtrace.join("\n")) if ENV["DEBUG"]
|
40
|
+
exit 1
|
41
|
+
end
|
data/lib/performa.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "performa/version"
|
4
|
+
require "performa/logger"
|
5
|
+
require "performa/configuration"
|
6
|
+
require "performa/shell_helper"
|
7
|
+
require "performa/container_registry"
|
8
|
+
require "performa/environment"
|
9
|
+
require "performa/container_id"
|
10
|
+
require "performa/images"
|
11
|
+
require "performa/stages"
|
12
|
+
require "performa/coordinator"
|
13
|
+
require "performa/results_helper"
|
14
|
+
|
15
|
+
module Performa
|
16
|
+
Error = Class.new(StandardError)
|
17
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
|
5
|
+
module Performa
|
6
|
+
class Configuration
|
7
|
+
DEFAULT_FILES = %w[
|
8
|
+
performa.yml config/performa.yml
|
9
|
+
spec/performa.yml test/performa.yml
|
10
|
+
].freeze
|
11
|
+
|
12
|
+
ERR_READING_CONFIG_FILE = "Could not read config file %s (%s)"
|
13
|
+
ERR_INVALID_FILE = "Invalid YAML file %s: %s"
|
14
|
+
ERR_NO_FILE = "Could not find a default config file (#{DEFAULT_FILES.join(', ')})"
|
15
|
+
|
16
|
+
InvalidDataError = Class.new(StandardError)
|
17
|
+
|
18
|
+
attr_reader :data
|
19
|
+
|
20
|
+
def initialize(config_file)
|
21
|
+
config_file ||= find_default_config_file
|
22
|
+
raise(Error, ERR_NO_FILE) unless config_file
|
23
|
+
|
24
|
+
@data = load_config_file(config_file)
|
25
|
+
validate_data
|
26
|
+
end
|
27
|
+
|
28
|
+
def load_config_file(config_file)
|
29
|
+
YAML.safe_load(File.read(config_file))
|
30
|
+
rescue Errno::EACCES => error
|
31
|
+
raise Error, format(ERR_READING_CONFIG_FILE, config_file, error.message)
|
32
|
+
rescue Psych::SyntaxError => error
|
33
|
+
raise Error, format(ERR_INVALID_FILE, config_file, error.message)
|
34
|
+
end
|
35
|
+
|
36
|
+
def find_default_config_file
|
37
|
+
DEFAULT_FILES.find do |file|
|
38
|
+
File.exist?(file)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def validate_data
|
43
|
+
raise InvalidDataError if @data["version"].nil? ||
|
44
|
+
!@data["images"]&.is_a?(Array) ||
|
45
|
+
@data["command"]&.empty?
|
46
|
+
rescue InvalidDataError
|
47
|
+
raise Error, "Invalid config"
|
48
|
+
end
|
49
|
+
|
50
|
+
def [](name)
|
51
|
+
@data[name]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Performa
|
4
|
+
class ContainerId < String
|
5
|
+
attr_accessor :from_cache
|
6
|
+
|
7
|
+
def initialize(*args)
|
8
|
+
@from_cache = false
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.from_cache(string)
|
13
|
+
str = new(string)
|
14
|
+
str.from_cache = true
|
15
|
+
str
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "set"
|
4
|
+
|
5
|
+
module Performa
|
6
|
+
module ContainerRegistry
|
7
|
+
module_function
|
8
|
+
|
9
|
+
extend ShellHelper
|
10
|
+
|
11
|
+
def add(container_id)
|
12
|
+
containers << container_id
|
13
|
+
end
|
14
|
+
|
15
|
+
def kill_all
|
16
|
+
containers.each do |container_id|
|
17
|
+
kill(container_id)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def kill(container_id)
|
22
|
+
run_command("docker kill #{container_id}")
|
23
|
+
containers.delete(container_id)
|
24
|
+
end
|
25
|
+
|
26
|
+
def containers
|
27
|
+
Thread.current[:performa_containers] ||= Set.new
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Performa
|
4
|
+
module Coordinator
|
5
|
+
module_function
|
6
|
+
|
7
|
+
extend ShellHelper
|
8
|
+
|
9
|
+
def run(config)
|
10
|
+
envs = Environment.all(config)
|
11
|
+
results = {}
|
12
|
+
|
13
|
+
envs.each do |env|
|
14
|
+
results[env.name] = process_env(env, config: config)
|
15
|
+
end
|
16
|
+
|
17
|
+
ResultsHelper.process(results, config: config)
|
18
|
+
ensure
|
19
|
+
ContainerRegistry.kill_all
|
20
|
+
end
|
21
|
+
|
22
|
+
def process_env(env, config:)
|
23
|
+
container_id = Images.process(env, config: config)
|
24
|
+
unless container_id.from_cache
|
25
|
+
Stages.process(env, container_id: container_id)
|
26
|
+
Images.cache_container(container_id, tag: env.hash) unless config["cache_environments"] == false
|
27
|
+
end
|
28
|
+
|
29
|
+
result = run_command("docker container exec #{container_id} #{config['command']}")
|
30
|
+
ContainerRegistry.kill(container_id)
|
31
|
+
result
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "digest"
|
4
|
+
|
5
|
+
module Performa
|
6
|
+
class Environment
|
7
|
+
def self.all(config)
|
8
|
+
unless config["stages"]
|
9
|
+
return config["images"].map do |image|
|
10
|
+
new(image: image, volumes: config["volumes"])
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
config["images"].product(config["stages"].to_a).map do |image, stage|
|
15
|
+
new(image: image, stage: stage, volumes: config["volumes"])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :image, :stage, :volumes, :name, :hash
|
20
|
+
|
21
|
+
def initialize(image:, stage: nil, volumes: nil)
|
22
|
+
@image = image
|
23
|
+
@stage = stage
|
24
|
+
@volumes = volumes || []
|
25
|
+
assign_name
|
26
|
+
assign_hash
|
27
|
+
end
|
28
|
+
|
29
|
+
def assign_name
|
30
|
+
@name = @image.tr(":", "_") + ("-#{@stage[0]}" if @stage).to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
def assign_hash
|
34
|
+
@hash = Digest::SHA1.hexdigest(@image + @stage.to_s)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Performa
|
4
|
+
module Images
|
5
|
+
module_function
|
6
|
+
|
7
|
+
extend ShellHelper
|
8
|
+
CACHED_IMAGES_NAME = "performa_env"
|
9
|
+
|
10
|
+
def process(env, config:)
|
11
|
+
unless config["cache_environments"] == false
|
12
|
+
container_id = container_id_for_cached_image(env)
|
13
|
+
return container_id if container_id
|
14
|
+
end
|
15
|
+
|
16
|
+
pull_if_missing(env.image)
|
17
|
+
id = start_image_container(env.image, volumes: env.volumes)
|
18
|
+
ContainerId.new(id)
|
19
|
+
end
|
20
|
+
|
21
|
+
def container_id_for_cached_image(env)
|
22
|
+
cached_image = "#{CACHED_IMAGES_NAME}:#{env.hash}"
|
23
|
+
return unless exists?(cached_image)
|
24
|
+
|
25
|
+
id = start_image_container(cached_image, volumes: env.volumes)
|
26
|
+
ContainerId.from_cache(id)
|
27
|
+
end
|
28
|
+
|
29
|
+
def pull(image)
|
30
|
+
run_command("docker pull #{image}", no_capture: true)
|
31
|
+
end
|
32
|
+
|
33
|
+
def pull_if_missing(image)
|
34
|
+
pull(image) unless exists?(image)
|
35
|
+
end
|
36
|
+
|
37
|
+
def exists?(image)
|
38
|
+
!run_command("docker images -q #{image}").empty?
|
39
|
+
end
|
40
|
+
|
41
|
+
def start_image_container(image, volumes: [])
|
42
|
+
volumes_options = volumes.map do |volume|
|
43
|
+
volume[0] = Dir.pwd if volume[0] == "."
|
44
|
+
" -v #{volume}"
|
45
|
+
end.join
|
46
|
+
|
47
|
+
command = "docker run #{volumes_options} -d #{image} tail -f /dev/null"
|
48
|
+
|
49
|
+
run_command(command).strip.tap do |container_id|
|
50
|
+
ContainerRegistry.add(container_id)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def cache_container(container_id, tag:)
|
55
|
+
run_command("docker commit #{container_id} #{CACHED_IMAGES_NAME}:#{tag}")
|
56
|
+
end
|
57
|
+
|
58
|
+
def clear_cached
|
59
|
+
ids = run_command("docker images --filter=reference='#{CACHED_IMAGES_NAME}' --format '{{.ID}}'").split("\n")
|
60
|
+
ids.each do |id|
|
61
|
+
run_command("docker rmi -f #{id.strip}")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "logger"
|
4
|
+
require "time"
|
5
|
+
require "colorize"
|
6
|
+
|
7
|
+
module Performa
|
8
|
+
LOG = Logger.new(STDOUT)
|
9
|
+
LOG.level = Logger::INFO
|
10
|
+
LOG.formatter = proc do |severity, datetime, _progname, message|
|
11
|
+
line = "[#{datetime.strftime('%Y-%m-%d %H:%M:%S')}] #{severity} -- #{message}\n"
|
12
|
+
|
13
|
+
case severity
|
14
|
+
when "ERROR"
|
15
|
+
line.colorize(:red)
|
16
|
+
else
|
17
|
+
line
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def LOG.success(message)
|
22
|
+
LOG.info(message.colorize(:green))
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "fileutils"
|
4
|
+
require "colorize"
|
5
|
+
|
6
|
+
module Performa
|
7
|
+
module ResultsHelper
|
8
|
+
module_function
|
9
|
+
|
10
|
+
def process(results, config:)
|
11
|
+
if config["output"].nil? || config["output"] == "STDOUT"
|
12
|
+
output_to_stdout(results)
|
13
|
+
else
|
14
|
+
output_to_directory(results, directory: config["output"])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def output_to_stdout(results)
|
19
|
+
results.each_pair do |env_name, result|
|
20
|
+
puts
|
21
|
+
puts "== Output for #{env_name}".colorize(:green)
|
22
|
+
puts
|
23
|
+
puts result
|
24
|
+
end
|
25
|
+
puts
|
26
|
+
end
|
27
|
+
|
28
|
+
def output_to_directory(results, directory:)
|
29
|
+
FileUtils.mkdir_p(directory)
|
30
|
+
filenames = []
|
31
|
+
results.each_pair do |env_name, result|
|
32
|
+
filename = File.join(directory, env_name + ".txt")
|
33
|
+
filenames << filename
|
34
|
+
|
35
|
+
File.open(filename, "w+") do |file|
|
36
|
+
file.write(result)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
message = +"Command outputs are now present in the following files:\n"
|
41
|
+
message << filenames.join("\n")
|
42
|
+
|
43
|
+
puts
|
44
|
+
puts message.colorize(:green)
|
45
|
+
puts
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pty"
|
4
|
+
require "English"
|
5
|
+
|
6
|
+
module Performa
|
7
|
+
module ShellHelper
|
8
|
+
def run_command(command, success_only: true, no_capture: false)
|
9
|
+
LOG.success("Running `#{command}` ...")
|
10
|
+
|
11
|
+
if no_capture
|
12
|
+
system(command)
|
13
|
+
result = ""
|
14
|
+
else
|
15
|
+
result = pty_spawn(command)
|
16
|
+
end
|
17
|
+
|
18
|
+
raise "(non-zero exit code)" if success_only && !$CHILD_STATUS.success?
|
19
|
+
|
20
|
+
result
|
21
|
+
rescue StandardError => e
|
22
|
+
raise Error, <<~MSG
|
23
|
+
Error running the command `#{command}`:
|
24
|
+
=> error: #{e.message}
|
25
|
+
=> command output: #{result}
|
26
|
+
MSG
|
27
|
+
end
|
28
|
+
|
29
|
+
def pty_spawn(command)
|
30
|
+
result = +""
|
31
|
+
PTY.spawn(command) do |stdout, _stdin, _pid|
|
32
|
+
stdout.each do |line|
|
33
|
+
LOG.info(line.strip)
|
34
|
+
result << line
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Process.wait unless $CHILD_STATUS.exited?
|
39
|
+
|
40
|
+
result
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Performa
|
4
|
+
module Stages
|
5
|
+
module_function
|
6
|
+
|
7
|
+
extend ShellHelper
|
8
|
+
|
9
|
+
def process(env, container_id:)
|
10
|
+
return unless env.stage
|
11
|
+
|
12
|
+
env.stage[1].each do |command|
|
13
|
+
run_command("docker container exec #{container_id} #{command}")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/performa.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require "performa/version"
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "performa"
|
9
|
+
spec.version = Performa::VERSION
|
10
|
+
spec.authors = ["Christophe Maximin"]
|
11
|
+
spec.email = ["christophe.maximin@gmail.com"]
|
12
|
+
|
13
|
+
spec.summary = "PLACEHOLDER"
|
14
|
+
spec.description = "PLACEHOLDER"
|
15
|
+
spec.homepage = "https://github.com/christophemaximin/performa"
|
16
|
+
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
+
spec.metadata["source_code_uri"] = "https://github.com/christophemaximin/performa"
|
19
|
+
spec.metadata["changelog_uri"] = "https://github.com/christophemaximin/performa/CHANGELOG.md"
|
20
|
+
|
21
|
+
# Specify which files should be added to the gem when it is released.
|
22
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
23
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
24
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
+
end
|
26
|
+
spec.bindir = "exe"
|
27
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
28
|
+
spec.require_paths = ["lib"]
|
29
|
+
|
30
|
+
spec.add_runtime_dependency "colorize", "~> 0.8"
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: performa
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Christophe Maximin
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-11-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: colorize
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.8'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.8'
|
27
|
+
description: PLACEHOLDER
|
28
|
+
email:
|
29
|
+
- christophe.maximin@gmail.com
|
30
|
+
executables:
|
31
|
+
- performa
|
32
|
+
extensions: []
|
33
|
+
extra_rdoc_files: []
|
34
|
+
files:
|
35
|
+
- ".gitignore"
|
36
|
+
- ".rspec"
|
37
|
+
- ".rubocop.yml"
|
38
|
+
- ".ruby-version"
|
39
|
+
- ".travis.yml"
|
40
|
+
- CHANGELOG.md
|
41
|
+
- Gemfile
|
42
|
+
- Gemfile.lock
|
43
|
+
- README.md
|
44
|
+
- Rakefile
|
45
|
+
- bin/console
|
46
|
+
- bin/setup
|
47
|
+
- exe/performa
|
48
|
+
- lib/performa.rb
|
49
|
+
- lib/performa/configuration.rb
|
50
|
+
- lib/performa/container_id.rb
|
51
|
+
- lib/performa/container_registry.rb
|
52
|
+
- lib/performa/coordinator.rb
|
53
|
+
- lib/performa/environment.rb
|
54
|
+
- lib/performa/images.rb
|
55
|
+
- lib/performa/logger.rb
|
56
|
+
- lib/performa/results_helper.rb
|
57
|
+
- lib/performa/shell_helper.rb
|
58
|
+
- lib/performa/stages.rb
|
59
|
+
- lib/performa/version.rb
|
60
|
+
- performa.gemspec
|
61
|
+
homepage: https://github.com/christophemaximin/performa
|
62
|
+
licenses: []
|
63
|
+
metadata:
|
64
|
+
homepage_uri: https://github.com/christophemaximin/performa
|
65
|
+
source_code_uri: https://github.com/christophemaximin/performa
|
66
|
+
changelog_uri: https://github.com/christophemaximin/performa/CHANGELOG.md
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options: []
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
requirements: []
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 3.0.0.beta2
|
84
|
+
signing_key:
|
85
|
+
specification_version: 4
|
86
|
+
summary: PLACEHOLDER
|
87
|
+
test_files: []
|