diff options
author | Kamil Trzciński <ayufan@ayufan.eu> | 2015-07-06 11:31:52 +0000 |
---|---|---|
committer | Kamil Trzciński <ayufan@ayufan.eu> | 2015-07-06 11:31:52 +0000 |
commit | 574e71ce3eda70add20b27ccd935e07186a5d7b0 (patch) | |
tree | 3df4fa18482559d69db0c63587f17bbce1c8e59e | |
parent | b27f990de8a1b53974eb9aa0bd6bdde18f93d6db (diff) | |
parent | aaa08b5f48488fc7b6436e04f26a5680d9aebb09 (diff) | |
download | gitlab-ci-574e71ce3eda70add20b27ccd935e07186a5d7b0.tar.gz |
Merge branch 'docker-image' into 'master'
Added support for image and services in YAML
- [x] Prepare changes for GitLab CI
- [x] Prepare documentation (70% done): https://gitlab.com/gitlab-org/gitlab-ci/merge_requests/178
- [x] Prepare GitLab Runner - changes are pushed to bleeding edge
/cc @vsizov
See merge request !181
-rw-r--r-- | CHANGELOG | 1 | ||||
-rw-r--r-- | app/models/build.rb | 4 | ||||
-rw-r--r-- | app/models/commit.rb | 4 | ||||
-rw-r--r-- | db/migrate/20150630091815_add_options_to_build.rb | 5 | ||||
-rw-r--r-- | db/schema.rb | 1 | ||||
-rw-r--r-- | lib/api/entities.rb | 2 | ||||
-rw-r--r-- | lib/gitlab_ci_yaml_processor.rb | 56 | ||||
-rw-r--r-- | spec/factories/builds.rb | 7 | ||||
-rw-r--r-- | spec/lib/gitlab_ci_yaml_processor_spec.rb | 98 | ||||
-rw-r--r-- | spec/models/build_spec.rb | 15 | ||||
-rw-r--r-- | spec/requests/api/builds_spec.rb | 10 | ||||
-rw-r--r-- | spec/support/gitlab_stubs/gitlab_ci.yml | 10 |
12 files changed, 189 insertions, 24 deletions
@@ -1,4 +1,5 @@ v7.13.0 + - Allow to specify image and services in yml that can be used with docker - Fix: No runner notification can see managers only - Ability to cancel all builds in commit at once - Disable colors in rake tasks automatically (if IO is not a TTY) diff --git a/app/models/build.rb b/app/models/build.rb index 6124c8f..62540ca 100644 --- a/app/models/build.rb +++ b/app/models/build.rb @@ -14,6 +14,7 @@ # commit_id :integer # coverage :float # commands :text +# options :text # class Build < ActiveRecord::Base @@ -23,6 +24,8 @@ class Build < ActiveRecord::Base belongs_to :project belongs_to :runner + serialize :options + validates :commit, presence: true validates :status, presence: true validates :coverage, numericality: true, allow_blank: true @@ -63,6 +66,7 @@ class Build < ActiveRecord::Base def retry(build) new_build = Build.new(status: :pending) + new_build.options = build.options new_build.commands = build.commands new_build.tag_list = build.tag_list new_build.commit_id = build.commit_id diff --git a/app/models/commit.rb b/app/models/commit.rb index 73e485a..dae2658 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -108,7 +108,8 @@ class Commit < ActiveRecord::Base project: project, name: build_attrs[:name], commands: build_attrs[:script], - tag_list: build_attrs[:tags] + tag_list: build_attrs[:tags], + options: build_attrs[:options] }) end end @@ -145,6 +146,7 @@ class Commit < ActiveRecord::Base name: build_attrs[:name], commands: build_attrs[:script], tag_list: build_attrs[:tags], + options: build_attrs[:options], deploy: true }) end diff --git a/db/migrate/20150630091815_add_options_to_build.rb b/db/migrate/20150630091815_add_options_to_build.rb new file mode 100644 index 0000000..68ed3fa --- /dev/null +++ b/db/migrate/20150630091815_add_options_to_build.rb @@ -0,0 +1,5 @@ +class AddOptionsToBuild < ActiveRecord::Migration + def change + add_column :builds, :options, :text + end +end diff --git a/db/schema.rb b/db/schema.rb index f3e9e40..1525d74 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -31,6 +31,7 @@ ActiveRecord::Schema.define(version: 20150706103229) do t.integer "job_id" t.string "name" t.boolean "deploy", default: false + t.text "options" end add_index "builds", ["commit_id"], name: "index_builds_on_commit_id", using: :btree diff --git a/lib/api/entities.rb b/lib/api/entities.rb index 2f6565a..2f7ca0f 100644 --- a/lib/api/entities.rb +++ b/lib/api/entities.rb @@ -13,7 +13,7 @@ module API class Build < Grape::Entity expose :id, :commands, :path, :ref, :sha, :project_id, :repo_url, - :before_sha, :timeout, :allow_git_fetch, :project_name + :before_sha, :timeout, :allow_git_fetch, :project_name, :options expose :variables, using: Variable end diff --git a/lib/gitlab_ci_yaml_processor.rb b/lib/gitlab_ci_yaml_processor.rb index 20cfef0..00fceda 100644 --- a/lib/gitlab_ci_yaml_processor.rb +++ b/lib/gitlab_ci_yaml_processor.rb @@ -1,7 +1,7 @@ class GitlabCiYamlProcessor class ValidationError < StandardError;end - attr_reader :before_script + attr_reader :before_script, :image, :services def initialize(config) @config = YAML.load(config) @@ -27,25 +27,13 @@ class GitlabCiYamlProcessor def builds @jobs.map do |name, job| - { - script: "#{@before_script.join("\n")}\n#{normalize_script(job[:script])}", - tags: job[:tags] || [], - name: name, - only: job[:only], - except: job[:except] - } + build_job(name, job) end end def deploy_builds @deploy_jobs.map do |name, job| - { - script: "#{@before_script.join("\n")}\n#{normalize_script(job[:script])}", - tags: job[:tags] || [], - name: name, - only: job[:only], - except: job[:except] - } + build_job(name, job) end end @@ -53,7 +41,9 @@ class GitlabCiYamlProcessor def initial_parsing @before_script = @config[:before_script] || [] - @config.delete(:before_script) + @image = @config[:image] + @services = @config[:services] + @config.except!(:before_script, :image, :services) @config.each do |name, param| raise ValidationError, "Unknown parameter: #{name}" unless param.is_a?(Hash) @@ -87,6 +77,20 @@ class GitlabCiYamlProcessor end end + def build_job(name, job) + { + script: "#{@before_script.join("\n")}\n#{normalize_script(job[:script])}", + tags: job[:tags] || [], + name: name, + only: job[:only], + except: job[:except], + options: { + image: job[:image] || @image, + services: job[:services] || @services + }.compact + } + end + def match_ref?(pattern, ref) if pattern.first == "/" && pattern.last == "/" Regexp.new(pattern[1...-1]) =~ ref @@ -108,6 +112,14 @@ class GitlabCiYamlProcessor raise ValidationError, "before_script should be an array" end + unless @image.nil? || @image.is_a?(String) + raise ValidationError, "image should be a string" + end + + unless @services.nil? || @services.is_a?(Array) && @services.all? {|service| service.is_a?(String)} + raise ValidationError, "services should be an array of strings" + end + @jobs.each do |name, job| validate_job!("#{name} job", job) end @@ -121,11 +133,21 @@ class GitlabCiYamlProcessor def validate_job!(name, job) job.keys.each do |key| - unless [:tags, :script, :only, :except, :type].include? key + unless [:tags, :script, :only, :except, :type, :image, :services].include? key raise ValidationError, "#{name}: unknown parameter #{key}" end end + if job[:image] && !job[:image].is_a?(String) + raise ValidationError, "#{name}: image should be a string" + end + + if job[:services] + unless job[:services].is_a?(Array) && job[:services].all? {|service| service.is_a?(String)} + raise ValidationError, "#{name}: services should be an array of strings" + end + end + if job[:tags] && !job[:tags].is_a?(Array) raise ValidationError, "#{name}: tags parameter should be an array" end diff --git a/spec/factories/builds.rb b/spec/factories/builds.rb index 724cd5f..92f9f05 100644 --- a/spec/factories/builds.rb +++ b/spec/factories/builds.rb @@ -14,6 +14,7 @@ # commit_id :integer # coverage :float # commands :text +# options :text # # Read about factories at https://github.com/thoughtbot/factory_girl @@ -23,6 +24,12 @@ FactoryGirl.define do started_at 'Di 29. Okt 09:51:28 CET 2013' finished_at 'Di 29. Okt 09:53:28 CET 2013' commands 'ls -a' + options do + { + image: "ruby:2.1", + services: ["postgres"] + } + end factory :not_started_build do started_at nil diff --git a/spec/lib/gitlab_ci_yaml_processor_spec.rb b/spec/lib/gitlab_ci_yaml_processor_spec.rb index 465ee9e..9c9fde9 100644 --- a/spec/lib/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/gitlab_ci_yaml_processor_spec.rb @@ -17,7 +17,8 @@ describe GitlabCiYamlProcessor do name: :rspec, only: nil, script: "pwd\nrspec", - tags: [] + tags: [], + options: {} } end @@ -81,7 +82,8 @@ describe GitlabCiYamlProcessor do name: :rspec, only: nil, script: "pwd\nrspec", - tags: [] + tags: [], + options: {} } end @@ -130,6 +132,56 @@ describe GitlabCiYamlProcessor do end end + describe "Image and service handling" do + it "returns image and service when defined" do + config = YAML.dump({ + image: "ruby:2.1", + services: ["mysql"], + before_script: ["pwd"], + rspec: {script: "rspec"} + }) + + config_processor = GitlabCiYamlProcessor.new(config) + + config_processor.builds_for_ref("master").size.should == 1 + config_processor.builds_for_ref("master").first.should == { + except: nil, + name: :rspec, + only: nil, + script: "pwd\nrspec", + tags: [], + options: { + image: "ruby:2.1", + services: ["mysql"] + } + } + end + + it "returns image and service when overridden for job" do + config = YAML.dump({ + image: "ruby:2.1", + services: ["mysql"], + before_script: ["pwd"], + rspec: {image: "ruby:2.5", services: ["postgresql"], script: "rspec"} + }) + + config_processor = GitlabCiYamlProcessor.new(config) + + config_processor.builds_for_ref("master").size.should == 1 + config_processor.builds_for_ref("master").first.should == { + except: nil, + name: :rspec, + only: nil, + script: "pwd\nrspec", + tags: [], + options: { + image: "ruby:2.5", + services: ["postgresql"] + } + } + end + end + describe "Error handling" do it "indicates that object is invalid" do expect{GitlabCiYamlProcessor.new("invalid_yaml\n!ccdvlf%612334@@@@")}.to raise_error(GitlabCiYamlProcessor::ValidationError) @@ -149,6 +201,48 @@ describe GitlabCiYamlProcessor do end.to raise_error(GitlabCiYamlProcessor::ValidationError, "before_script should be an array") end + it "returns errors if image parameter is invalid" do + config = YAML.dump({image: ["test"], rspec: {script: "test"}}) + expect do + GitlabCiYamlProcessor.new(config) + end.to raise_error(GitlabCiYamlProcessor::ValidationError, "image should be a string") + end + + it "returns errors if job image parameter is invalid" do + config = YAML.dump({rspec: {image: ["test"]}}) + expect do + GitlabCiYamlProcessor.new(config) + end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: image should be a string") + end + + it "returns errors if services parameter is not an array" do + config = YAML.dump({services: "test", rspec: {script: "test"}}) + expect do + GitlabCiYamlProcessor.new(config) + end.to raise_error(GitlabCiYamlProcessor::ValidationError, "services should be an array of strings") + end + + it "returns errors if services parameter is not an array of strings" do + config = YAML.dump({services: [10, "test"], rspec: {script: "test"}}) + expect do + GitlabCiYamlProcessor.new(config) + end.to raise_error(GitlabCiYamlProcessor::ValidationError, "services should be an array of strings") + end + + it "returns errors if job services parameter is not an array" do + config = YAML.dump({rspec: {services: "test"}}) + expect do + GitlabCiYamlProcessor.new(config) + end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: services should be an array of strings") + end + + it "returns errors if job services parameter is not an array of strings" do + config = YAML.dump({rspec: {services: [10, "test"]}}) + expect do + GitlabCiYamlProcessor.new(config) + end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: services should be an array of strings") + end + it "returns errors if there are unknown parameters" do config = YAML.dump({extra: "bundle update"}) expect do diff --git a/spec/models/build_spec.rb b/spec/models/build_spec.rb index d996689..b7e9672 100644 --- a/spec/models/build_spec.rb +++ b/spec/models/build_spec.rb @@ -14,6 +14,7 @@ # commit_id :integer # coverage :float # commands :text +# options :text # require 'spec_helper' @@ -167,6 +168,20 @@ describe Build do end end + describe :options do + let(:options) { + { + :image => "ruby:2.1", + :services => [ + "postgres" + ] + } + } + + subject { build.options } + it { should eq(options) } + end + describe :ref do subject { build.ref } diff --git a/spec/requests/api/builds_spec.rb b/spec/requests/api/builds_spec.rb index 64d00bf..b44798b 100644 --- a/spec/requests/api/builds_spec.rb +++ b/spec/requests/api/builds_spec.rb @@ -51,6 +51,16 @@ describe API::API do response.status.should == 404 end + it "returns options" do + commit = FactoryGirl.create(:commit, project: project) + commit.create_builds + + post api("/builds/register"), token: runner.token, info: {platform: :darwin} + + response.status.should == 201 + json_response["options"].should == {"image" => "ruby:2.1", "services" => ["postgres"]} + end + it "returns variables" do commit = FactoryGirl.create(:commit, project: project) commit.create_builds diff --git a/spec/support/gitlab_stubs/gitlab_ci.yml b/spec/support/gitlab_stubs/gitlab_ci.yml index 5de4e6d..4f0f106 100644 --- a/spec/support/gitlab_stubs/gitlab_ci.yml +++ b/spec/support/gitlab_stubs/gitlab_ci.yml @@ -1,9 +1,13 @@ -before_script: +image: ruby:2.1 +services: + - postgres + +before_script: - gem install bundler - bundle install - bundle exec rake db:create -rspec: +rspec: script: "rake spec" tags: - ruby @@ -19,7 +23,7 @@ spinach: except: - tags -staging: +staging: script: "cap deploy stating" type: deploy tags: |