Commit 9c0c4fd0 authored by Kamil Trzciński's avatar Kamil Trzciński
Browse files

Merge branch 'rename-type-to-stage' into 'master'

Rename type to stage

However, make the `type` and `types` as alias for `stage` and `stages`.

/cc @vsizov @sytses 

See merge request !222
parents bc0c94e7 d013642b
......@@ -10,7 +10,7 @@ class LintsController < ApplicationController
@error = "Please provide content of .gitlab-ci.yml"
else
@config_processor = GitlabCiYamlProcessor.new params[:content]
@types = @config_processor.types
@stages = @config_processor.stages
@builds = @config_processor.builds
@status = true
end
......
......@@ -93,17 +93,17 @@ class Commit < ActiveRecord::Base
recipients.uniq
end
def job_type
def stage
return unless config_processor
job_types = builds_without_retry.select(&:active?).map(&:job_type)
config_processor.types.find { |job_type| job_types.include? job_type }
stages = builds_without_retry.select(&:active?).map(&:stage)
config_processor.stages.find { |stage| stages.include? stage }
end
def create_builds_for_type(job_type)
def create_builds_for_stage(stage)
return if skip_ci?
return unless config_processor
builds_attrs = config_processor.builds_for_type_and_ref(job_type, ref, tag)
builds_attrs = config_processor.builds_for_stage_and_ref(stage, ref, tag)
builds_attrs.map do |build_attrs|
builds.create!({
project: project,
......@@ -112,7 +112,7 @@ class Commit < ActiveRecord::Base
tag_list: build_attrs[:tags],
options: build_attrs[:options],
allow_failure: build_attrs[:allow_failure],
job_type: build_attrs[:type]
stage: build_attrs[:stage]
})
end
end
......@@ -121,10 +121,10 @@ class Commit < ActiveRecord::Base
return if skip_ci?
return unless config_processor
build_types = builds.group_by(&:job_type)
stages = builds.group_by(&:stage)
config_processor.types.any? do |job_type|
!build_types.include?(job_type) && create_builds_for_type(job_type).present?
config_processor.stages.any? do |stage|
!stages.include?(stage) && create_builds_for_stage(stage).present?
end
end
......@@ -132,8 +132,8 @@ class Commit < ActiveRecord::Base
return if skip_ci?
return unless config_processor
config_processor.types.any? do |job_type|
create_builds_for_type(job_type).present?
config_processor.stages.any? do |stage|
create_builds_for_stage(stage).present?
end
end
......@@ -150,9 +150,9 @@ class Commit < ActiveRecord::Base
def builds_without_retry_sorted
return builds_without_retry unless config_processor
job_types = config_processor.types
stages = config_processor.stages
builds_without_retry.sort_by do |build|
[job_types.index(build.job_type) || -1, build.name || ""]
[stages.index(build.stage) || -1, build.name || ""]
end
end
......
......@@ -7,7 +7,7 @@
%strong Build ##{build.id}
%td
= build.job_type
= build.stage
%td
= build.name
......
......@@ -3,7 +3,7 @@
= commit.status
- if commit.running?
&middot;
= commit.job_type
= commit.stage
%td.build-link
......
......@@ -49,7 +49,7 @@
- unless @commit.push_data[:ci_yaml_file]
.bs-callout.bs-callout-warning
\.gitlab-ci.yml not found in this commit
%h3 Status
.build.alert{class: commit_status_alert_class(@commit)}
......@@ -68,7 +68,7 @@
%tr
%th Status
%th Build ID
%th Type
%th Stage
%th Name
%th Duration
%th Finished at
......@@ -86,7 +86,7 @@
%tr
%th Status
%th Build ID
%th Type
%th Stage
%th Name
%th Duration
%th Finished at
......
......@@ -10,10 +10,10 @@
%th Parameter
%th Value
%tbody
- @types.each do |type|
- @builds.select { |build| build[:type] == type }.each do |build|
- @stages.each do |stage|
- @builds.select { |build| build[:stage] == stage }.each do |build|
%tr
%td #{type.capitalize} Job - #{build[:name]}
%td #{stage.capitalize} Job - #{build[:name]}
%td
%pre
= simple_format build[:script]
......
class RenameJobTypeToStageBuilds < ActiveRecord::Migration
def up
rename_column :builds, :job_type, :stage
end
def down
rename_column :builds, :stage, :job_type
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150729145246) do
ActiveRecord::Schema.define(version: 20150803142346) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
......@@ -40,7 +40,7 @@ ActiveRecord::Schema.define(version: 20150729145246) do
t.boolean "deploy", default: false
t.text "options"
t.boolean "allow_failure", default: false, null: false
t.string "job_type"
t.string "stage"
end
add_index "builds", ["commit_id"], name: "index_builds_on_commit_id", using: :btree
......
......@@ -31,13 +31,13 @@ services:
before_script:
- bundle_install
types:
stages:
- build
- test
- deploy
job1:
type: build
stage: build
script:
- execute-script-for-job1
only:
......@@ -52,7 +52,8 @@ There are a few `keywords` that can't be used as job names:
|---------------|----------|-------------|
| image | optional | Use docker image, covered in [Use Docker](../docker/README.md) |
| services | optional | Use docker services, covered in [Use Docker](../docker/README.md) |
| types | optional | Define build types |
| stages | optional | Define build stages |
| types | optional | Alias for `stages` |
| before_script | optional | Define commands prepended for each job's script |
### image and services
......@@ -62,18 +63,18 @@ The configuration of this feature is covered in separate document: [Use Docker](
### before_script
`before_script` is used to define the command that should be run before all builds, including deploy builds. This can be an array or a multiline string.
### types
`types` is used to define build types that can be used by jobs.
The specification of `types` allows for having flexible multi stage pipelines.
### stages
`stages` is used to define build stages that can be used by jobs.
The specification of `stages` allows for having flexible multi stage pipelines.
The ordering of elements in `types` defines the ordering of builds' execution:
The ordering of elements in `stages` defines the ordering of builds' execution:
1. Builds of the same type are run in parallel.
1. Builds of next type are run after success.
1. Builds of the same stage are run in parallel.
1. Builds of next stage are run after success.
Let's consider the following example, which defines 3 types:
Let's consider the following example, which defines 3 stages:
```
types:
stages:
- build
- test
- deploy
......@@ -83,12 +84,15 @@ types:
1. If all jobs of `build` succeeds, the `test` jobs are executed in parallel.
1. If all jobs of `test` succeeds, the `deploy` jobs are executed in parallel.
1. If all jobs of `deploy` succeeds, the commit is marked as `success`.
1. If any of the previous jobs fails, the commit is marked as `failed` and no jobs of further type are executed.
1. If any of the previous jobs fails, the commit is marked as `failed` and no jobs of further stage are executed.
There are also two edge cases worth mentioning:
1. If no `types` is defined in `.gitlab-ci.yml`, then the types `build`, `test` and `deploy` are allowed to be used as job's type by default.
2. If a job doesn't specify `type`, the job is assigned the `test` type.
1. If no `stages` is defined in `.gitlab-ci.yml`, then by default the `build`, `test` and `deploy` are allowed to be used as job's stage by default.
2. If a job doesn't specify `stage`, the job is assigned the `test` stage.
### types
Alias for [stages](#stages).
## Jobs
`.gitlab-ci.yml` allows you to specify an unlimited number of jobs.
......@@ -100,7 +104,7 @@ job_name:
script:
- rake spec
- coverage
type: test
stage: test
only:
- master
except:
......@@ -114,7 +118,8 @@ job_name:
| keyword | required | description |
|---------------|----------|-------------|
| script | required | Defines a shell script which is executed by runner |
| type | optional (default: test) | Defines a build type |
| stage | optional (default: test) | Defines a build stage |
| type | optional | Alias for `stage` |
| only | optional | Defines a list of git refs for which build is created |
| except | optional | Defines a list of git refs for which build is not created |
| tags | optional | Defines a list of tags which are used to select runner |
......@@ -136,9 +141,9 @@ job:
- bundle exec rspec
```
### type
`type` allows to group build into different stages. Builds of the same `type` are executed in `parallel`.
For more info about the use of `type` please check the [types](#types).
### stage
`stage` allows to group build into different stages. Builds of the same `stage` are executed in `parallel`.
For more info about the use of `stage` please check the [stages](#stages).
### only and except
This are two parameters that allow for setting a refs policy to limit when jobs are built:
......
class GitlabCiYamlProcessor
class ValidationError < StandardError;end
DEFAULT_TYPES = %w(build test deploy)
DEFAULT_TYPE = 'test'
ALLOWED_JOB_KEYS = [:tags, :script, :only, :except, :type, :image, :services, :allow_failure, :type]
DEFAULT_STAGES = %w(build test deploy)
DEFAULT_STAGE = 'test'
ALLOWED_JOB_KEYS = [:tags, :script, :only, :except, :type, :image, :services, :allow_failure, :type, :stage]
attr_reader :before_script, :image, :services
......@@ -21,8 +21,8 @@ class GitlabCiYamlProcessor
validate!
end
def builds_for_type_and_ref(type, ref, tag = false)
builds.select{|build| build[:type] == type && process?(build[:only], build[:except], ref, tag)}
def builds_for_stage_and_ref(stage, ref, tag = false)
builds.select{|build| build[:stage] == stage && process?(build[:only], build[:except], ref, tag)}
end
def builds
......@@ -31,8 +31,8 @@ class GitlabCiYamlProcessor
end
end
def types
@types || DEFAULT_TYPES
def stages
@stages || DEFAULT_STAGES
end
private
......@@ -41,8 +41,8 @@ class GitlabCiYamlProcessor
@before_script = @config[:before_script] || []
@image = @config[:image]
@services = @config[:services]
@types = @config[:types]
@config.except!(:before_script, :image, :services, :types)
@stages = @config[:stages] || @config[:types]
@config.except!(:before_script, :image, :services, :types, :stages)
@config.each do |name, param|
raise ValidationError, "Unknown parameter: #{name}" unless param.is_a?(Hash)
......@@ -54,7 +54,8 @@ class GitlabCiYamlProcessor
@jobs = {}
@config.each do |key, job|
@jobs[key] = { type: DEFAULT_TYPE }.merge(job)
stage = job[:stage] || job[:type] || DEFAULT_STAGE
@jobs[key] = { stage: stage }.merge(job)
end
end
......@@ -80,7 +81,7 @@ class GitlabCiYamlProcessor
def build_job(name, job)
{
type: job[:type],
stage: job[:stage],
script: "#{@before_script.join("\n")}\n#{normalize_script(job[:script])}",
tags: job[:tags] || [],
name: name,
......@@ -123,8 +124,8 @@ class GitlabCiYamlProcessor
raise ValidationError, "services should be an array of strings"
end
unless @types.nil? || validate_array_of_strings(@types)
raise ValidationError, "types should be an array of strings"
unless @stages.nil? || validate_array_of_strings(@stages)
raise ValidationError, "stages should be an array of strings"
end
@jobs.each do |name, job|
......@@ -141,12 +142,10 @@ class GitlabCiYamlProcessor
end
end
unless job[:type].is_a?(String)
raise ValidationError, "#{name}: type should be a string"
end
unless job[:type].in?(types)
raise ValidationError, "#{name}: type parameter should be #{types.join(", ")}"
if job[:stage]
unless job[:stage].is_a?(String) && job[:stage].in?(stages)
raise ValidationError, "#{name}: stage parameter should be #{stages.join(", ")}"
end
end
if job[:image] && !job[:image].is_a?(String)
......
......@@ -13,9 +13,9 @@ describe GitlabCiYamlProcessor do
config_processor = GitlabCiYamlProcessor.new(config)
config_processor.builds_for_type_and_ref(type, "master").size.should == 1
config_processor.builds_for_type_and_ref(type, "master").first.should == {
type: "test",
config_processor.builds_for_stage_and_ref(type, "master").size.should == 1
config_processor.builds_for_stage_and_ref(type, "master").first.should == {
stage: "test",
except: nil,
name: :rspec,
only: nil,
......@@ -34,7 +34,7 @@ describe GitlabCiYamlProcessor do
config_processor = GitlabCiYamlProcessor.new(config)
config_processor.builds_for_type_and_ref(type, "master").size.should == 0
config_processor.builds_for_stage_and_ref(type, "master").size.should == 0
end
it "does not return builds if only has regexp with another branch" do
......@@ -45,7 +45,7 @@ describe GitlabCiYamlProcessor do
config_processor = GitlabCiYamlProcessor.new(config)
config_processor.builds_for_type_and_ref(type, "master").size.should == 0
config_processor.builds_for_stage_and_ref(type, "master").size.should == 0
end
it "returns builds if only has specified this branch" do
......@@ -56,7 +56,7 @@ describe GitlabCiYamlProcessor do
config_processor = GitlabCiYamlProcessor.new(config)
config_processor.builds_for_type_and_ref(type, "master").size.should == 1
config_processor.builds_for_stage_and_ref(type, "master").size.should == 1
end
it "does not build tags" do
......@@ -67,7 +67,7 @@ describe GitlabCiYamlProcessor do
config_processor = GitlabCiYamlProcessor.new(config)
config_processor.builds_for_type_and_ref(type, "0-1", true).size.should == 0
config_processor.builds_for_stage_and_ref(type, "0-1", true).size.should == 0
end
it "returns builds if only has a list of branches including specified" do
......@@ -78,7 +78,7 @@ describe GitlabCiYamlProcessor do
config_processor = GitlabCiYamlProcessor.new(config)
config_processor.builds_for_type_and_ref(type, "deploy").size.should == 1
config_processor.builds_for_stage_and_ref(type, "deploy").size.should == 1
end
it "returns build only for specified type" do
......@@ -93,9 +93,9 @@ describe GitlabCiYamlProcessor do
config_processor = GitlabCiYamlProcessor.new(config)
config_processor.builds_for_type_and_ref("production", "deploy").size.should == 0
config_processor.builds_for_type_and_ref(type, "deploy").size.should == 1
config_processor.builds_for_type_and_ref("deploy", "deploy").size.should == 2
config_processor.builds_for_stage_and_ref("production", "deploy").size.should == 0
config_processor.builds_for_stage_and_ref(type, "deploy").size.should == 1
config_processor.builds_for_stage_and_ref("deploy", "deploy").size.should == 2
end
end
......@@ -110,10 +110,10 @@ describe GitlabCiYamlProcessor do
config_processor = GitlabCiYamlProcessor.new(config)
config_processor.builds_for_type_and_ref("test", "master").size.should == 1
config_processor.builds_for_type_and_ref("test", "master").first.should == {
config_processor.builds_for_stage_and_ref("test", "master").size.should == 1
config_processor.builds_for_stage_and_ref("test", "master").first.should == {
except: nil,
type: "test",
stage: "test",
name: :rspec,
only: nil,
script: "pwd\nrspec",
......@@ -136,10 +136,10 @@ describe GitlabCiYamlProcessor do
config_processor = GitlabCiYamlProcessor.new(config)
config_processor.builds_for_type_and_ref("test", "master").size.should == 1
config_processor.builds_for_type_and_ref("test", "master").first.should == {
config_processor.builds_for_stage_and_ref("test", "master").size.should == 1
config_processor.builds_for_stage_and_ref("test", "master").first.should == {
except: nil,
type: "test",
stage: "test",
name: :rspec,
only: nil,
script: "pwd\nrspec",
......@@ -235,39 +235,39 @@ describe GitlabCiYamlProcessor do
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: allow_failure parameter should be an boolean")
end
it "returns errors if job type is not a string" do
config = YAML.dump({rspec: {script: "test", type: false, allow_failure: "string"}})
it "returns errors if job stage is not a string" do
config = YAML.dump({rspec: {script: "test", type: 1, allow_failure: "string"}})
expect do
GitlabCiYamlProcessor.new(config)
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: type should be a string")
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: stage parameter should be build, test, deploy")
end
it "returns errors if job type is not a pre-defined type" do
it "returns errors if job stage is not a pre-defined stage" do
config = YAML.dump({rspec: {script: "test", type: "acceptance", allow_failure: "string"}})
expect do
GitlabCiYamlProcessor.new(config)
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: type parameter should be build, test, deploy")
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: stage parameter should be build, test, deploy")
end
it "returns errors if job type is not a defined type" do
it "returns errors if job stage is not a defined stage" do
config = YAML.dump({types: ["build", "test"], rspec: {script: "test", type: "acceptance", allow_failure: "string"}})
expect do
GitlabCiYamlProcessor.new(config)
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: type parameter should be build, test")
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: stage parameter should be build, test")
end
it "returns errors if types is not an array" do
it "returns errors if stages is not an array" do
config = YAML.dump({types: "test", rspec: {script: "test"}})
expect do
GitlabCiYamlProcessor.new(config)
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "types should be an array of strings")
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "stages should be an array of strings")
end
it "returns errors if types is not an array of strings" do
it "returns errors if stages is not an array of strings" do
config = YAML.dump({types: [true, "test"], rspec: {script: "test"}})
expect do
GitlabCiYamlProcessor.new(config)
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "types should be an array of strings")
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "stages should be an array of strings")
end
end
end
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment