diff --git a/lib/buildkite/config/docker_build.rb b/lib/buildkite/config/docker_build.rb index b43f630..13dbd26 100644 --- a/lib/buildkite/config/docker_build.rb +++ b/lib/buildkite/config/docker_build.rb @@ -43,12 +43,23 @@ def prepare end dsl do - def builder(ruby) + def builder(ruby, compose: nil) build_context = context.extensions.find(BuildContext) build_context.ruby = ruby return unless build_context.ruby.build? command do + compose_options = { + build: "base", + config: ".buildkite/docker-compose.yml", + env: %w[PRE_STEPS RACK], + "image-name" => build_context.ruby.image_name_for(build_context.build_id), + "cache-from" => cache_from(build_context), + push: build_push(build_context), + "image-repository" => build_context.image_base, + } + compose_options.merge!(compose) if compose + label ":docker: #{build_context.ruby.prefix}#{build_context.ruby.version}" key "docker-image-#{build_context.ruby.image_key}" plugin :artifacts, { @@ -66,16 +77,7 @@ def builder(ruby) compressed: ".buildkite.tgz" } - plugin :docker_compose, { - build: "base", - config: ".buildkite/docker-compose.yml", - env: %w[PRE_STEPS RACK], - "image-name" => build_context.ruby.image_name_for(build_context.build_id), - "cache-from" => cache_from(build_context), - push: build_push(build_context), - "image-repository" => build_context.image_base, - } - + plugin :docker_compose, compose_options env({ BUNDLER: build_context.bundler, RUBYGEMS: build_context.rubygems, diff --git a/lib/buildkite/config/rake_command.rb b/lib/buildkite/config/rake_command.rb index 7c78a9f..3c6d480 100644 --- a/lib/buildkite/config/rake_command.rb +++ b/lib/buildkite/config/rake_command.rb @@ -20,7 +20,7 @@ def build_env(build_context, pre_steps, env) env ||= {} pre_steps ||= [] - env[:IMAGE_NAME] = build_context.image_name_for(build_context.build_id, prefix: nil) + env[:IMAGE_NAME] ||= build_context.image_name_for(build_context.build_id, prefix: nil) if build_context.ruby.yjit_enabled? env[:RUBY_YJIT_ENABLE] = "1" @@ -33,7 +33,17 @@ def build_env(build_context, pre_steps, env) env end - def install_plugins(service = "default", env = nil, dir = ".") + def install_plugins(service = "default", env = nil, dir = ".", compose: nil) + compose_options = { + "env" => env, + "run" => service, + "pull" => service, + "pull-retries" => 3, + "config" => ".buildkite/docker-compose.yml", + "shell" => ["runner", *dir], + } + compose_options.merge!(compose) if compose + plugin :artifacts, { download: ".dockerignore" } @@ -49,14 +59,7 @@ def install_plugins(service = "default", env = nil, dir = ".") compressed: ".buildkite.tgz" } - plugin :docker_compose, { - "env" => env, - "run" => service, - "pull" => service, - "pull-retries" => 3, - "config" => ".buildkite/docker-compose.yml", - "shell" => ["runner", *dir], - }.compact + plugin :docker_compose, compose_options.compact end end @@ -65,7 +68,7 @@ def prepare end dsl do - def bundle(command, label:, env: nil) + def bundle(command, label:, env: nil, compose: nil) build_context = context.extensions.find(BuildContext) command do @@ -73,7 +76,7 @@ def bundle(command, label:, env: nil) depends_on "docker-image-#{build_context.ruby.image_key}" command command - install_plugins + install_plugins(compose: compose) env build_env(build_context, nil, env) @@ -85,7 +88,7 @@ def bundle(command, label:, env: nil) end end - def rake(dir, task: "test", label: nil, service: "default", pre_steps: nil, env: nil, retry_on: nil, soft_fail: nil, parallelism: nil) + def rake(dir, task: "test", label: nil, service: "default", pre_steps: nil, env: nil, retry_on: nil, soft_fail: nil, parallelism: nil, compose: nil) build_context = context.extensions.find(BuildContext) if task.start_with?("mysql2:") || (build_context.rails_version >= Gem::Version.new("7.1.0.alpha") && task.start_with?("trilogy:")) @@ -99,7 +102,7 @@ def rake(dir, task: "test", label: nil, service: "default", pre_steps: nil, env: depends_on "docker-image-#{build_context.ruby.image_key}" command "rake #{task}" - install_plugins(service, %w[PRE_STEPS RACK], dir) + install_plugins(service, %w[PRE_STEPS RACK], dir, compose: compose) env build_env(build_context, pre_steps, env) diff --git a/test/buildkite_config/test_docker_build.rb b/test/buildkite_config/test_docker_build.rb index e97dde3..8c209bb 100644 --- a/test/buildkite_config/test_docker_build.rb +++ b/test/buildkite_config/test_docker_build.rb @@ -153,4 +153,32 @@ def test_builder_gem_version assert_equal ["base:buildkite-config-base:ruby-1-9-3-br-main"], compose["cache-from"] assert_equal ["base:buildkite-config-base:ruby-1-9-3-br-"], compose["push"] end + + def test_builder_compose_options + pipeline = PipelineFixture.new do + use Buildkite::Config::DockerBuild + + build_context.stub(:rails_version, Gem::Version.new("7.1")) do + builder Buildkite::Config::RubyConfig.new(version: "3.2"), compose: { + "cli_version": "2", + "image-name": "buildkite_base", + "cache-from": ["buildkite_base"], + "push": "", + "image-repository": "", + } + end + end + + plugins = pipeline.to_h["steps"][0]["plugins"] + + compose = plugins.find { |plugin| + plugin.key?("docker-compose#v1.0") + }.fetch("docker-compose#v1.0") + + assert_equal "2", compose["cli_version"] + assert_equal "buildkite_base", compose["image-name"] + assert_equal ["buildkite_base"], compose["cache-from"] + assert_equal "", compose["push"] + assert_equal "", compose["image-repository"] + end end diff --git a/test/buildkite_config/test_rake_command.rb b/test/buildkite_config/test_rake_command.rb index 7792453..ab1def4 100644 --- a/test/buildkite_config/test_rake_command.rb +++ b/test/buildkite_config/test_rake_command.rb @@ -147,6 +147,21 @@ def test_env assert_equal "buildkite-config-base:ruby-3-2-local", pipeline.to_h["steps"][0]["env"]["IMAGE_NAME"] end + def test_env_image_name + pipeline = PipelineFixture.new do + build_context.ruby = Buildkite::Config::RubyConfig.new(prefix: "ruby:", version: Gem::Version.new("3.2")) + use Buildkite::Config::RakeCommand + + build_context.stub(:rails_version, Gem::Version.new("7.1")) do + rake "test", task: "test:all", env: { "IMAGE_NAME": "override-at-command-definition" } + end + end + + assert_includes pipeline.to_h["steps"][0], "env" + assert_includes pipeline.to_h["steps"][0]["env"], "IMAGE_NAME" + assert_equal "override-at-command-definition", pipeline.to_h["steps"][0]["env"]["IMAGE_NAME"] + end + def test_timeout_in_minutes pipeline = PipelineFixture.new do build_context.ruby = Buildkite::Config::RubyConfig.new(prefix: "ruby:", version: Gem::Version.new("3.2")) @@ -220,6 +235,39 @@ def test_compose assert_equal ["runner", "test"], compose["shell"] end + def test_compose_options + pipeline = PipelineFixture.new do + build_context.ruby = Buildkite::Config::RubyConfig.new(prefix: "ruby:", version: Gem::Version.new("3.2")) + use Buildkite::Config::RakeCommand + + build_context.stub(:rails_version, Gem::Version.new("7.1")) do + rake "test", task: "test:all", compose: { + "cli_version": "2", + "pull": "", + } + end + end + + plugins = pipeline.to_h["steps"][0]["plugins"] + + compose = plugins.find { |plugin| + plugin.key?("docker-compose#v1.0") + }.fetch("docker-compose#v1.0") + + %w[env run pull config shell].each do |key| + assert_includes compose, key + end + + assert_includes compose["env"], "PRE_STEPS" + assert_includes compose["env"], "RACK" + + assert_equal "2", compose["cli_version"] + assert_equal "default", compose["run"] + assert_equal "", compose["pull"] + assert_equal ".buildkite/docker-compose.yml", compose["config"] + assert_equal ["runner", "test"], compose["shell"] + end + def test_multiple pipeline = PipelineFixture.new do build_context.ruby = Buildkite::Config::RubyConfig.new(version: Gem::Version.new("3.2")) @@ -462,4 +510,41 @@ def test_bundle_command assert_equal ["test-reports/*/*.xml"], step["artifact_paths"] assert_equal 30, step["timeout_in_minutes"] end + + def test_bundle_command_options + pipeline = PipelineFixture.new do + build_context.ruby = Buildkite::Config::RubyConfig.new(prefix: "ruby:", version: Gem::Version.new("3.2")) + use Buildkite::Config::RakeCommand + + build_context.stub(:rails_version, Gem::Version.new("7.1")) do + bundle "rubocop", label: "rubocop", compose: { + "cli_version": "2", + "pull": "", + }, env: { + "IMAGE_NAME": "override-at-command-definition", + } + end + end + + step = pipeline.to_h["steps"][0] + assert_equal "override-at-command-definition", step["env"]["IMAGE_NAME"] + + plugins = step["plugins"] + + compose = plugins.find { |plugin| + plugin.key?("docker-compose#v1.0") + }.fetch("docker-compose#v1.0") + + %w[run pull config shell].each do |key| + assert_includes compose, key + end + + assert_predicate compose["env"], :nil? + + assert_equal "2", compose["cli_version"] + assert_equal "default", compose["run"] + assert_equal "", compose["pull"] + assert_equal ".buildkite/docker-compose.yml", compose["config"] + assert_equal ["runner", "."], compose["shell"] + end end