Commit aa4a3349 authored by Marius Bobin's avatar Marius Bobin Committed by Fabio Pitino

Allow includes:file with project in parent-child pipelines

Allow to include project files in parent-child pipelines

```yaml
my-job:
  trigger:
    strategy: depend
    include:
      - project: 'my-group/my-pipeline-library'
        ref: 'master'
        file: 'path/to/child-pipeline.yml'
```
parent b5379076
---
title: Allow to include project files in parent-child pipelines
merge_request: 43404
author:
type: fixed
......@@ -71,6 +71,18 @@ microservice_a:
- template: Security/SAST.gitlab-ci.yml
```
In [GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/205157) and later,
you can use [`include:file`](yaml/README.md#includefile) to trigger child pipelines
with a configuration file in a different project:
```yaml
microservice_a:
trigger:
include:
- project: 'my-group/my-pipeline-library'
file: 'path/to/ci-config.yml'
```
NOTE: **Note:**
The max number of entries that are accepted for `trigger:include:` is three.
......
......@@ -3733,6 +3733,22 @@ child-pipeline:
The `generated-config.yml` is extracted from the artifacts and used as the configuration
for triggering the child pipeline.
##### Trigger child pipeline with files from another project
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/205157) in GitLab 13.5.
To trigger child pipelines with files from another private project under the same
GitLab instance, use [`include:file`](#includefile):
```yaml
child-pipeline:
trigger:
include:
- project: 'my-group/my-pipeline-library'
ref: 'master'
file: '/path/to/child-pipeline.yml'
```
#### Linking pipelines with `trigger:strategy`
By default, the `trigger` job completes with the `success` status
......
......@@ -10,7 +10,7 @@ module Gitlab
class Include < ::Gitlab::Config::Entry::Node
include ::Gitlab::Config::Entry::Validatable
ALLOWED_KEYS = %i[local file remote template artifact job].freeze
ALLOWED_KEYS = %i[local file remote template artifact job project ref].freeze
validations do
validates :config, hash_or_string: true
......@@ -22,6 +22,10 @@ module Gitlab
if config[:artifact] && config[:job].blank?
errors.add(:config, "must specify the job where to fetch the artifact from")
end
if config[:project] && config[:file].blank?
errors.add(:config, "must specify the file where to fetch the config from")
end
end
end
end
......
......@@ -61,6 +61,31 @@ RSpec.describe ::Gitlab::Ci::Config::Entry::Include do
end
end
end
context 'when using "project"' do
context 'and specifying "ref" and "file"' do
let(:config) { { project: 'my-group/my-pipeline-library', ref: 'master', file: 'test.yml' } }
it { is_expected.to be_valid }
end
context 'without "ref"' do
let(:config) { { project: 'my-group/my-pipeline-library', file: 'test.yml' } }
it { is_expected.to be_valid }
end
context 'without "file"' do
let(:config) { { project: 'my-group/my-pipeline-library' } }
it { is_expected.not_to be_valid }
it 'has specific error' do
expect(include_entry.errors)
.to include('include config must specify the file where to fetch the config from')
end
end
end
end
context 'when value is something else' do
......
......@@ -2240,47 +2240,49 @@ module Gitlab
end
describe 'with parent-child pipeline' do
let(:config) do
YAML.dump({
build1: { stage: 'build', script: 'test' },
test1: {
stage: 'test',
trigger: {
include: includes
}
}
})
end
context 'when artifact and job are specified' do
let(:config) do
YAML.dump({
build1: { stage: 'build', script: 'test' },
test1: { stage: 'test', trigger: {
include: [{ artifact: 'generated.yml', job: 'build1' }]
} }
})
end
let(:includes) { [{ artifact: 'generated.yml', job: 'build1' }] }
it { is_expected.to be_valid }
end
context 'when job is not specified specified while artifact is' do
let(:config) do
YAML.dump({
build1: { stage: 'build', script: 'test' },
test1: { stage: 'test', trigger: {
include: [{ artifact: 'generated.yml' }]
} }
})
end
context 'when job is not specified while artifact is' do
let(:includes) { [{ artifact: 'generated.yml' }] }
it_behaves_like 'returns errors', /include config must specify the job where to fetch the artifact from/
end
context 'when include is a string' do
let(:config) do
YAML.dump({
build1: { stage: 'build', script: 'test' },
test1: {
stage: 'test',
trigger: {
include: 'generated.yml'
}
}
})
context 'when project and file are specified' do
let(:includes) do
[{ file: 'generated.yml', project: 'my-namespace/my-project' }]
end
it { is_expected.to be_valid }
end
context 'when file is not specified while project is' do
let(:includes) { [{ project: 'something' }] }
it_behaves_like 'returns errors', /include config must specify the file where to fetch the config from/
end
context 'when include is a string' do
let(:includes) { 'generated.yml' }
it { is_expected.to be_valid }
end
end
describe "Error handling" do
......
......@@ -22,7 +22,7 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
end
shared_examples 'successful creation' do
it 'creates bridge jobs correctly' do
it 'creates bridge jobs correctly', :aggregate_failures do
pipeline = create_pipeline!
test = pipeline.statuses.find_by(name: 'test')
......@@ -221,6 +221,65 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
end
end
end
context 'when including configs from a project' do
context 'when specifying all attributes' do
let(:config) do
<<~YAML
test:
script: rspec
deploy:
variables:
CROSS: downstream
stage: deploy
trigger:
include:
- project: my-namespace/my-project
file: 'path/to/child.yml'
ref: 'master'
YAML
end
it_behaves_like 'successful creation' do
let(:expected_bridge_options) do
{
'trigger' => {
'include' => [
{
'file' => 'path/to/child.yml',
'project' => 'my-namespace/my-project',
'ref' => 'master'
}
]
}
}
end
end
end
context 'without specifying file' do
let(:config) do
<<~YAML
test:
script: rspec
deploy:
variables:
CROSS: downstream
stage: deploy
trigger:
include:
- project: my-namespace/my-project
ref: 'master'
YAML
end
it_behaves_like 'creation failure' do
let(:expected_error) do
/include config must specify the file where to fetch the config from/
end
end
end
end
end
def create_pipeline!
......
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