summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamil Trzciński <ayufan@ayufan.eu>2015-07-06 11:31:52 +0000
committerKamil Trzciński <ayufan@ayufan.eu>2015-07-06 11:31:52 +0000
commit574e71ce3eda70add20b27ccd935e07186a5d7b0 (patch)
tree3df4fa18482559d69db0c63587f17bbce1c8e59e
parentb27f990de8a1b53974eb9aa0bd6bdde18f93d6db (diff)
parentaaa08b5f48488fc7b6436e04f26a5680d9aebb09 (diff)
downloadgitlab-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--CHANGELOG1
-rw-r--r--app/models/build.rb4
-rw-r--r--app/models/commit.rb4
-rw-r--r--db/migrate/20150630091815_add_options_to_build.rb5
-rw-r--r--db/schema.rb1
-rw-r--r--lib/api/entities.rb2
-rw-r--r--lib/gitlab_ci_yaml_processor.rb56
-rw-r--r--spec/factories/builds.rb7
-rw-r--r--spec/lib/gitlab_ci_yaml_processor_spec.rb98
-rw-r--r--spec/models/build_spec.rb15
-rw-r--r--spec/requests/api/builds_spec.rb10
-rw-r--r--spec/support/gitlab_stubs/gitlab_ci.yml10
12 files changed, 189 insertions, 24 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 716770b..e64281d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -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: