Commit 9a271d80 authored by Kamil Trzcinski's avatar Kamil Trzcinski

Allow to define on which builds the current one depends on

parent d300ecf8
...@@ -22,6 +22,7 @@ v 8.6.0 (unreleased) ...@@ -22,6 +22,7 @@ v 8.6.0 (unreleased)
- Add support for cross-project label references - Add support for cross-project label references
- Update documentation to reflect Guest role not being enforced on internal projects - Update documentation to reflect Guest role not being enforced on internal projects
- Allow search for logged out users - Allow search for logged out users
- Allow to define on which builds the current one depends on
- Fix bug where Bitbucket `closed` issues were imported as `opened` (Iuri de Silvio) - Fix bug where Bitbucket `closed` issues were imported as `opened` (Iuri de Silvio)
- Don't show Issues/MRs from archived projects in Groups view - Don't show Issues/MRs from archived projects in Groups view
- Increase the notes polling timeout over time (Roberto Dip) - Increase the notes polling timeout over time (Roberto Dip)
......
...@@ -241,6 +241,7 @@ job_name: ...@@ -241,6 +241,7 @@ job_name:
| tags | no | Defines a list of tags which are used to select runner | | tags | no | Defines a list of tags which are used to select runner |
| allow_failure | no | Allow build to fail. Failed build doesn't contribute to commit status | | allow_failure | no | Allow build to fail. Failed build doesn't contribute to commit status |
| when | no | Define when to run build. Can be `on_success`, `on_failure` or `always` | | when | no | Define when to run build. Can be `on_success`, `on_failure` or `always` |
| dependencies | no | Define a builds that this build depends on |
| artifacts | no | Define list build artifacts | | artifacts | no | Define list build artifacts |
| cache | no | Define list of files that should be cached between subsequent runs | | cache | no | Define list of files that should be cached between subsequent runs |
...@@ -514,6 +515,60 @@ job: ...@@ -514,6 +515,60 @@ job:
untracked: true untracked: true
``` ```
### dependencies
_**Note:** Introduced in GitLab 8.6 and GitLab Runner v1.1.1._
This feature should be used with `artifacts` and allows to define artifacts passing between different builds.
`artifacts` from previous stages are passed by default.
To use a feature define `dependencies` in context of the build and pass
a list of all previous builds from which the artifacts should be downloaded.
You can only define a builds from stages that are executed before this one.
Error will be shown if you define builds from current stage or next stages.
How to use artifacts passing between stages:
```
build:osx:
stage: build
script: ...
artifacts:
paths:
- binaries/
build:linux:
stage: build
script: ...
artifacts:
paths:
- binaries/
test:osx:
stage: test
script: ...
dependencies:
- build:osx
test:linux:
stage: test
script: ...
dependencies:
- build:linux
deploy:
stage: deploy
script: ...
```
The above will create a build artifacts for two jobs: `build:osx` and `build:linux`.
When executing the `test:osx` the artifacts for `build:osx` will be downloaded and extracted in context of the build.
The same happens for `test:linux` and artifacts from `build:linux`.
The job `deploy` will download artifacts from all previous builds.
However, only the `build:osx` and `build:linux` exports artifacts so only these will be downloaded.
### cache ### cache
_**Note:** Introduced in GitLab Runner v0.7.0._ _**Note:** Introduced in GitLab Runner v0.7.0._
......
...@@ -5,7 +5,9 @@ module Ci ...@@ -5,7 +5,9 @@ module Ci
DEFAULT_STAGES = %w(build test deploy) DEFAULT_STAGES = %w(build test deploy)
DEFAULT_STAGE = 'test' DEFAULT_STAGE = 'test'
ALLOWED_YAML_KEYS = [:before_script, :image, :services, :types, :stages, :variables, :cache] ALLOWED_YAML_KEYS = [:before_script, :image, :services, :types, :stages, :variables, :cache]
ALLOWED_JOB_KEYS = [:tags, :script, :only, :except, :type, :image, :services, :allow_failure, :type, :stage, :when, :artifacts, :cache] ALLOWED_JOB_KEYS = [:tags, :script, :only, :except, :type, :image, :services,
:allow_failure, :type, :stage, :when, :artifacts, :cache,
:dependencies]
attr_reader :before_script, :image, :services, :variables, :path, :cache attr_reader :before_script, :image, :services, :variables, :path, :cache
...@@ -145,6 +147,7 @@ module Ci ...@@ -145,6 +147,7 @@ module Ci
validate_job_stage!(name, job) if job[:stage] validate_job_stage!(name, job) if job[:stage]
validate_job_cache!(name, job) if job[:cache] validate_job_cache!(name, job) if job[:cache]
validate_job_artifacts!(name, job) if job[:artifacts] validate_job_artifacts!(name, job) if job[:artifacts]
validate_job_dependencies!(name, job) if job[:dependencies]
end end
private private
...@@ -231,6 +234,22 @@ module Ci ...@@ -231,6 +234,22 @@ module Ci
end end
end end
def validate_job_dependencies!(name, job)
if !validate_array_of_strings(job[:dependencies])
raise ValidationError, "#{name} job: dependencies parameter should be an array of strings"
end
stage_index = stages.index(job[:stage])
job[:dependencies].each do |dependency|
raise ValidationError, "#{name} job: undefined dependency: #{dependency}" unless @jobs[dependency]
unless stages.index(@jobs[dependency][:stage]) < stage_index
raise ValidationError, "#{name} job: dependency #{dependency} is not defined in prior stages"
end
end
end
def validate_array_of_strings(values) def validate_array_of_strings(values)
values.is_a?(Array) && values.all? { |value| validate_string(value) } values.is_a?(Array) && values.all? { |value| validate_string(value) }
end end
......
...@@ -428,6 +428,44 @@ module Ci ...@@ -428,6 +428,44 @@ module Ci
end end
end end
describe "Dependencies" do
let(:config) do
{
build1: { stage: 'build', script: 'test' },
build2: { stage: 'build', script: 'test' },
test1: { stage: 'test', script: 'test', dependencies: dependencies },
test2: { stage: 'test', script: 'test' },
deploy: { stage: 'test', script: 'test' }
}
end
subject { GitlabCiYamlProcessor.new(YAML.dump(config)) }
context 'no dependencies' do
let(:dependencies) { }
it { expect { subject }.to_not raise_error }
end
context 'dependencies to builds' do
let(:dependencies) { [:build1, :build2] }
it { expect { subject }.to_not raise_error }
end
context 'undefined dependency' do
let(:dependencies) { [:undefined] }
it { expect { subject }.to raise_error(GitlabCiYamlProcessor::ValidationError, 'test1 job: undefined dependency: undefined') }
end
context 'dependencies to deploy' do
let(:dependencies) { [:deploy] }
it { expect { subject }.to raise_error(GitlabCiYamlProcessor::ValidationError, 'test1 job: dependency deploy is not defined in prior stages') }
end
end
describe "Hidden jobs" do describe "Hidden jobs" do
let(:config) do let(:config) do
YAML.dump({ YAML.dump({
...@@ -682,6 +720,13 @@ module Ci ...@@ -682,6 +720,13 @@ module Ci
GitlabCiYamlProcessor.new(config) GitlabCiYamlProcessor.new(config)
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: cache:paths parameter should be an array of strings") end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: cache:paths parameter should be an array of strings")
end end
it "returns errors if job dependencies is not an array of strings" do
config = YAML.dump({ types: ["build", "test"], rspec: { script: "test", dependencies: "string" } })
expect do
GitlabCiYamlProcessor.new(config)
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: dependencies parameter should be an array of strings")
end
end end
end end
end end
Markdown is supported
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