Building test-runners
This commit is contained in:
@@ -5,4 +5,6 @@ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
|||||||
require "pipeline"
|
require "pipeline"
|
||||||
|
|
||||||
Pipeline.load_config(File.expand_path('../../config/pipeline.yml', __FILE__))
|
Pipeline.load_config(File.expand_path('../../config/pipeline.yml', __FILE__))
|
||||||
Pipeline.daemon
|
# Pipeline.daemon
|
||||||
|
# Pipeline.build_analyzer "ruby"
|
||||||
|
Pipeline.build_test_runner "ruby"
|
||||||
|
|||||||
@@ -8,17 +8,18 @@ pipeline = PipelineClient.new
|
|||||||
lang = ARGV[0] || "ruby"
|
lang = ARGV[0] || "ruby"
|
||||||
|
|
||||||
pipeline.build_test_runner(lang)
|
pipeline.build_test_runner(lang)
|
||||||
exit
|
|
||||||
|
|
||||||
# pipeline.release_latest(lang)
|
# pipeline.release_latest(lang)
|
||||||
# exit
|
# exit
|
||||||
r = pipeline.analyze(lang, "two-fer", "soln-42", "s3://exercism-dev/iterations/fff07700-e1c3-402d-8937-823aeefb159f")
|
# r = pipeline.analyze(lang, "two-fer", "soln-42", "s3://exercism-dev/iterations/fff07700-e1c3-402d-8937-823aeefb159f")
|
||||||
puts r
|
# puts r
|
||||||
if r["logs"]
|
# if r["logs"]
|
||||||
r["logs"].each do |log_line|
|
# r["logs"].each do |log_line|
|
||||||
puts "+ #{log_line["cmd"]}"
|
# puts "+ #{log_line["cmd"]}"
|
||||||
puts log_line["stdout"]
|
# puts log_line["stdout"]
|
||||||
puts log_line["stderr"]
|
# puts log_line["stderr"]
|
||||||
end
|
# end
|
||||||
end
|
# end
|
||||||
|
#
|
||||||
puts r["result"]
|
# puts r["result"]
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ module Pipeline
|
|||||||
if (latest_tag.nil?)
|
if (latest_tag.nil?)
|
||||||
latest_tag = "master"
|
latest_tag = "master"
|
||||||
end
|
end
|
||||||
Pipeline::Build::AnalyzerBuild.(latest_tag, track_slug)
|
Pipeline::Build::AnalyzerBuild.(latest_tag, track_slug, repo)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.build_test_runner(track_slug)
|
def self.build_test_runner(track_slug)
|
||||||
@@ -43,7 +43,7 @@ module Pipeline
|
|||||||
if (latest_tag.nil?)
|
if (latest_tag.nil?)
|
||||||
latest_tag = "master"
|
latest_tag = "master"
|
||||||
end
|
end
|
||||||
Pipeline::Build::AnalyzerBuild.(latest_tag, track_slug)
|
Pipeline::Build::TestRunnerBuild.(latest_tag, track_slug, repo)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.release(language_slug)
|
def self.release(language_slug)
|
||||||
@@ -82,6 +82,7 @@ end
|
|||||||
|
|
||||||
require "pipeline/rpc_server"
|
require "pipeline/rpc_server"
|
||||||
require "pipeline/analyzer_repo"
|
require "pipeline/analyzer_repo"
|
||||||
|
require "pipeline/container_repo"
|
||||||
require "pipeline/validation/check_invokable"
|
require "pipeline/validation/check_invokable"
|
||||||
require "pipeline/validation/check_environment_invariants"
|
require "pipeline/validation/check_environment_invariants"
|
||||||
require "pipeline/validation/check_fixtures"
|
require "pipeline/validation/check_fixtures"
|
||||||
@@ -95,6 +96,8 @@ require "pipeline/util/external_command"
|
|||||||
require "pipeline/util/log_collector"
|
require "pipeline/util/log_collector"
|
||||||
require "pipeline/build/build_image"
|
require "pipeline/build/build_image"
|
||||||
require "pipeline/build/publish_image"
|
require "pipeline/build/publish_image"
|
||||||
|
require "pipeline/build/container_build"
|
||||||
require "pipeline/build/analyzer_build"
|
require "pipeline/build/analyzer_build"
|
||||||
|
require "pipeline/build/test_runner_build"
|
||||||
require "pipeline/runtime/runtime_environment"
|
require "pipeline/runtime/runtime_environment"
|
||||||
require "pipeline/runtime/analysis_run"
|
require "pipeline/runtime/analysis_run"
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class Pipeline::AnalyzerRepo
|
|||||||
end
|
end
|
||||||
|
|
||||||
def self.test_runner_for_track(track_slug)
|
def self.test_runner_for_track(track_slug)
|
||||||
repo_url = "https://github.com/exercism/#{track_slug}-analyzer"
|
repo_url = "https://github.com/exercism/#{track_slug}-test-runner"
|
||||||
Pipeline::AnalyzerRepo.new(repo_url)
|
Pipeline::AnalyzerRepo.new(repo_url)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,56 +1,10 @@
|
|||||||
module Pipeline::Build
|
module Pipeline::Build
|
||||||
class AnalyzerBuild
|
class AnalyzerBuild < ContainerBuild
|
||||||
include Mandate
|
|
||||||
|
|
||||||
attr_accessor :img, :target_sha, :image_tag
|
|
||||||
|
|
||||||
initialize_with :build_tag, :track_slug
|
|
||||||
|
|
||||||
def call
|
|
||||||
setup_utilities
|
|
||||||
check_tag_exists
|
|
||||||
build
|
|
||||||
validate
|
|
||||||
publish
|
|
||||||
{
|
|
||||||
track: track_slug,
|
|
||||||
image: image_name,
|
|
||||||
image_tag: image_tag,
|
|
||||||
git_sha: target_sha,
|
|
||||||
git_tag: build_tag,
|
|
||||||
logs: img.logs.inspect
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def setup_utilities
|
|
||||||
@img = Pipeline::Util::ImgWrapper.new
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_tag_exists
|
|
||||||
return if build_tag == "master"
|
|
||||||
raise "Build tag does not exist" unless repo.tags[build_tag]
|
|
||||||
end
|
|
||||||
|
|
||||||
def build
|
|
||||||
@image_tag = Pipeline::Build::BuildImage.(build_tag, image_name, repo, img)
|
|
||||||
end
|
|
||||||
|
|
||||||
def validate
|
|
||||||
Pipeline::Validation::ValidateBuild.(image_tag, "fixtures/#{track_slug}")
|
|
||||||
end
|
|
||||||
|
|
||||||
def publish
|
|
||||||
Pipeline::Build::PublishImage.(img, image_name, image_tag, build_tag)
|
|
||||||
end
|
|
||||||
|
|
||||||
def image_name
|
def image_name
|
||||||
suffix = "-dev" unless ENV["env"] == "production"
|
suffix = "-dev" unless ENV["env"] == "production"
|
||||||
"#{track_slug}-analyzer#{suffix}"
|
"#{track_slug}-analyzer#{suffix}"
|
||||||
end
|
end
|
||||||
|
|
||||||
memoize
|
|
||||||
def repo
|
|
||||||
Pipeline::AnalyzerRepo.for_track(track_slug)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -10,15 +10,17 @@ module Pipeline::Build
|
|||||||
repo.fetch!
|
repo.fetch!
|
||||||
checkout
|
checkout
|
||||||
build
|
build
|
||||||
local_tag
|
@target_sha
|
||||||
end
|
end
|
||||||
|
|
||||||
def checkout
|
def checkout
|
||||||
@target_sha = repo.checkout(build_tag)
|
target_sha = repo.checkout(build_tag)
|
||||||
|
@target_sha = "sha-#{target_sha}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def build
|
def build
|
||||||
Dir.chdir(repo.workdir) do
|
Dir.chdir(repo.workdir) do
|
||||||
|
img.reset_hub_login
|
||||||
img.build(local_tag)
|
img.build(local_tag)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
82
lib/pipeline/build/container_build.rb
Normal file
82
lib/pipeline/build/container_build.rb
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
module Pipeline::Build
|
||||||
|
class ContainerBuild
|
||||||
|
include Mandate
|
||||||
|
|
||||||
|
attr_accessor :img, :local_tag, :image_tag, :container_repo
|
||||||
|
|
||||||
|
initialize_with :build_tag, :track_slug, :repo
|
||||||
|
|
||||||
|
def call
|
||||||
|
setup_utilities
|
||||||
|
setup_remote_repo
|
||||||
|
check_tag_exists
|
||||||
|
if already_built?
|
||||||
|
puts "already_built"
|
||||||
|
return {
|
||||||
|
status: "ignored",
|
||||||
|
message: "Already built",
|
||||||
|
track: track_slug,
|
||||||
|
image: image_name,
|
||||||
|
image_tag: image_tag
|
||||||
|
}
|
||||||
|
end
|
||||||
|
build
|
||||||
|
validate
|
||||||
|
publish
|
||||||
|
{
|
||||||
|
status: "built",
|
||||||
|
message: "Successfully built",
|
||||||
|
track: track_slug,
|
||||||
|
image: image_name,
|
||||||
|
image_tag: image_tag,
|
||||||
|
git_tag: build_tag,
|
||||||
|
logs: img.logs.inspect
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def setup_utilities
|
||||||
|
@logs = Pipeline::Util::LogCollector.new
|
||||||
|
@img = Pipeline::Util::ImgWrapper.new(@logs)
|
||||||
|
end
|
||||||
|
|
||||||
|
def setup_remote_repo
|
||||||
|
@container_repo = Pipeline::ContainerRepo.new(image_name)
|
||||||
|
@container_repo.create_if_required
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_tag_exists
|
||||||
|
return if build_tag == "master"
|
||||||
|
raise "Build tag does not exist" unless repo.tags[build_tag]
|
||||||
|
end
|
||||||
|
|
||||||
|
def already_built?
|
||||||
|
puts "Already built?"
|
||||||
|
puts "image_name: #{image_name}"
|
||||||
|
puts "build_tag: #{build_tag}"
|
||||||
|
puts "current: #{@container_repo.git_shas}"
|
||||||
|
puts "repo: #{repo}"
|
||||||
|
current_tags = @container_repo.git_shas
|
||||||
|
repo.fetch!
|
||||||
|
target_sha = repo.checkout(build_tag)
|
||||||
|
puts target_sha
|
||||||
|
current_tags.include? target_sha
|
||||||
|
end
|
||||||
|
|
||||||
|
def build
|
||||||
|
@local_tag = Pipeline::Build::BuildImage.(build_tag, image_name, repo, img)
|
||||||
|
@image_tag = "#{image_name}:#{local_tag}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate
|
||||||
|
Pipeline::Validation::ValidateBuild.(image_tag, "fixtures/#{track_slug}")
|
||||||
|
end
|
||||||
|
|
||||||
|
def publish
|
||||||
|
Pipeline::Build::PublishImage.(img, container_repo, local_tag, build_tag)
|
||||||
|
end
|
||||||
|
|
||||||
|
def image_name
|
||||||
|
raise "Image not implemented"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -2,77 +2,62 @@ module Pipeline::Build
|
|||||||
class PublishImage
|
class PublishImage
|
||||||
include Mandate
|
include Mandate
|
||||||
|
|
||||||
initialize_with :img, :image_name, :image_tag, :build_tag
|
initialize_with :img, :container_repo, :local_tag, :build_tag
|
||||||
|
|
||||||
|
attr_reader :repository_url
|
||||||
|
|
||||||
def call
|
def call
|
||||||
puts "PUBLISHING #{image_tag}"
|
puts "PUBLISHING #{image_tag}"
|
||||||
puts "Login to repo"
|
puts "Login to repo"
|
||||||
create_repository
|
|
||||||
login_to_repository
|
login_to_repository
|
||||||
tag_build
|
tag_build
|
||||||
push_build
|
push_build
|
||||||
logout
|
logout
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_repository
|
|
||||||
puts "Checking if repository exists"
|
|
||||||
begin
|
|
||||||
ecr.describe_repositories({
|
|
||||||
repository_names: [image_name]
|
|
||||||
})
|
|
||||||
return
|
|
||||||
rescue Aws::ECR::Errors::RepositoryNotFoundException
|
|
||||||
puts "Repository #{image_name} not found"
|
|
||||||
end
|
|
||||||
puts "Creating repository"
|
|
||||||
ecr.create_repository({
|
|
||||||
repository_name: image_name,
|
|
||||||
image_tag_mutability: "MUTABLE"
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
def login_to_repository
|
def login_to_repository
|
||||||
authorization_token = ecr.get_authorization_token.authorization_data[0].authorization_token
|
@repository_url = container_repo.repository_url
|
||||||
plain = Base64.decode64(authorization_token)
|
user, password = container_repo.create_login_token
|
||||||
user,password = plain.split(":")
|
img.login("AWS", password, repository_url)
|
||||||
img.login("AWS", password, registry_endpoint)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def logout
|
def logout
|
||||||
img.logout(registry_endpoint)
|
img.logout(repository_url)
|
||||||
end
|
end
|
||||||
|
|
||||||
def tag_build
|
def tag_build
|
||||||
img.tag(image_tag, remote_tag)
|
img.tag(image_tag, remote_tag)
|
||||||
|
img.tag(image_tag, remote_tag_timestamped)
|
||||||
img.tag(image_tag, remote_human_tag) unless build_tag.nil?
|
img.tag(image_tag, remote_human_tag) unless build_tag.nil?
|
||||||
img.tag(image_tag, remote_latest_tag)
|
img.tag(image_tag, remote_latest_tag)
|
||||||
end
|
end
|
||||||
|
|
||||||
def push_build
|
def push_build
|
||||||
img.push(remote_tag)
|
img.push(remote_tag)
|
||||||
|
img.push(remote_tag_timestamped)
|
||||||
img.push(remote_human_tag) unless build_tag.nil?
|
img.push(remote_human_tag) unless build_tag.nil?
|
||||||
img.push(remote_latest_tag)
|
img.push(remote_latest_tag)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def image_tag
|
||||||
|
"#{container_repo.image_name}:#{local_tag}"
|
||||||
|
end
|
||||||
|
|
||||||
def remote_tag
|
def remote_tag
|
||||||
"#{registry_endpoint}/#{image_tag}"
|
"#{repository_url}:#{local_tag}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def remote_human_tag
|
def remote_human_tag
|
||||||
"#{registry_endpoint}/#{image_name}:#{build_tag}"
|
"#{repository_url}:#{build_tag}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def remote_latest_tag
|
def remote_latest_tag
|
||||||
"#{registry_endpoint}/#{image_name}:latest"
|
"#{repository_url}:latest"
|
||||||
end
|
|
||||||
|
|
||||||
def registry_endpoint
|
|
||||||
Pipeline.config["registry_endpoint"]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
memoize
|
memoize
|
||||||
def ecr
|
def remote_tag_timestamped
|
||||||
Aws::ECR::Client.new(region: 'eu-west-1')
|
"#{remote_tag}-#{Time.now.to_i}"
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
15
lib/pipeline/build/test_runner_build.rb
Normal file
15
lib/pipeline/build/test_runner_build.rb
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
module Pipeline::Build
|
||||||
|
class TestRunnerBuild < ContainerBuild
|
||||||
|
|
||||||
|
def image_name
|
||||||
|
suffix = "-dev" unless ENV["env"] == "production"
|
||||||
|
"#{track_slug}-test-runner#{suffix}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def validate
|
||||||
|
# No validation implemented for this yet
|
||||||
|
# Pipeline::Validation::ValidateBuild.(image_tag, "fixtures/#{track_slug}")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
61
lib/pipeline/container_repo.rb
Normal file
61
lib/pipeline/container_repo.rb
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
class Pipeline::ContainerRepo
|
||||||
|
|
||||||
|
attr_reader :image_name
|
||||||
|
|
||||||
|
def initialize(image_name)
|
||||||
|
@image_name = image_name
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_if_required
|
||||||
|
puts "Checking if repository exists"
|
||||||
|
begin
|
||||||
|
return lookup_repo
|
||||||
|
rescue Aws::ECR::Errors::RepositoryNotFoundException
|
||||||
|
puts "Repository #{image_name} not found"
|
||||||
|
end
|
||||||
|
puts "Creating repository"
|
||||||
|
ecr.create_repository({
|
||||||
|
repository_name: image_name,
|
||||||
|
image_tag_mutability: "MUTABLE"
|
||||||
|
})
|
||||||
|
lookup_repo
|
||||||
|
end
|
||||||
|
|
||||||
|
def lookup_repo
|
||||||
|
repos = ecr.describe_repositories({
|
||||||
|
repository_names: [image_name]
|
||||||
|
})
|
||||||
|
repos.repositories.first
|
||||||
|
end
|
||||||
|
|
||||||
|
def repository_url
|
||||||
|
lookup_repo.repository_uri
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_login_token
|
||||||
|
authorization_token = ecr.get_authorization_token.authorization_data[0].authorization_token
|
||||||
|
plain = Base64.decode64(authorization_token)
|
||||||
|
user,password = plain.split(":")
|
||||||
|
end
|
||||||
|
|
||||||
|
def git_shas
|
||||||
|
images = ecr.list_images({
|
||||||
|
repository_name: image_name
|
||||||
|
})
|
||||||
|
tags = []
|
||||||
|
images.image_ids.each do |image|
|
||||||
|
tag = image.image_tag
|
||||||
|
# Only return git-based shas
|
||||||
|
if tag.start_with?("sha-")
|
||||||
|
tag = tag.gsub(/sha-/, "")
|
||||||
|
tags << tag unless tag.include?("-")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
tags.uniq
|
||||||
|
end
|
||||||
|
|
||||||
|
def ecr
|
||||||
|
@ecr ||= Aws::ECR::Client.new(region: 'eu-west-1')
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -23,6 +23,10 @@ module Pipeline::Util
|
|||||||
exec_cmd "#{binary_path} login -u #{user} -p \"#{password}\" #{registry_endpoint}"
|
exec_cmd "#{binary_path} login -u #{user} -p \"#{password}\" #{registry_endpoint}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def reset_hub_login
|
||||||
|
exec_cmd "#{binary_path} logout"
|
||||||
|
end
|
||||||
|
|
||||||
def logout(registry_endpoint)
|
def logout(registry_endpoint)
|
||||||
exec_cmd "#{binary_path} logout #{registry_endpoint}"
|
exec_cmd "#{binary_path} logout #{registry_endpoint}"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -34,8 +34,9 @@ class Pipeline::Validation::ValidateBuild
|
|||||||
|
|
||||||
memoize
|
memoize
|
||||||
def container_driver
|
def container_driver
|
||||||
img = Pipeline::Util::ImgWrapper.new
|
@logs = Pipeline::Util::LogCollector.new
|
||||||
runc = Pipeline::Util::RuncWrapper.new
|
img = Pipeline::Util::ImgWrapper.new(@logs)
|
||||||
|
runc = Pipeline::Util::RuncWrapper.new(@logs)
|
||||||
configurator = Pipeline::Util::RuncConfigurator.new
|
configurator = Pipeline::Util::RuncConfigurator.new
|
||||||
configurator.seed_from_env
|
configurator.seed_from_env
|
||||||
Pipeline::Util::ContainerDriver.new(runc, img, configurator, workdir)
|
Pipeline::Util::ContainerDriver.new(runc, img, configurator, workdir)
|
||||||
|
|||||||
@@ -7,8 +7,10 @@ module Pipeline
|
|||||||
def test_build_and_validate_realish_image
|
def test_build_and_validate_realish_image
|
||||||
demo_analyzer_repo = "https://github.com/exercism/stub-analyzer.git"
|
demo_analyzer_repo = "https://github.com/exercism/stub-analyzer.git"
|
||||||
repo = Pipeline::AnalyzerRepo.new(demo_analyzer_repo)
|
repo = Pipeline::AnalyzerRepo.new(demo_analyzer_repo)
|
||||||
img = Pipeline::Util::ImgWrapper.new
|
logs = Pipeline::Util::LogCollector.new
|
||||||
image_tag = Pipeline::Build::BuildImage.("master", "demo", repo, img)
|
img = Pipeline::Util::ImgWrapper.new(logs)
|
||||||
|
local_tag = Pipeline::Build::BuildImage.("master", "demo", repo, img)
|
||||||
|
image_tag = "demo:#{local_tag}"
|
||||||
Pipeline::Validation::ValidateBuild.(image_tag, "test-fixtures/demo")
|
Pipeline::Validation::ValidateBuild.(image_tag, "test-fixtures/demo")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ module Pipeline::Validation
|
|||||||
configurator = Pipeline::Util::RuncConfigurator.new
|
configurator = Pipeline::Util::RuncConfigurator.new
|
||||||
configurator.seed_from_env
|
configurator.seed_from_env
|
||||||
|
|
||||||
image_tag = Pipeline::Build::BuildImage.("master", track_slug, repo, img)
|
local_tag = Pipeline::Build::BuildImage.("master", track_slug, repo, img)
|
||||||
|
image_tag = "#{track_slug}:#{local_tag}"
|
||||||
|
|
||||||
@container_driver = Pipeline::Util::ContainerDriver.new(runc, img, configurator, workdir)
|
@container_driver = Pipeline::Util::ContainerDriver.new(runc, img, configurator, workdir)
|
||||||
container_driver.prepare_workdir
|
container_driver.prepare_workdir
|
||||||
|
|||||||
Reference in New Issue
Block a user