Commit c4aca6df authored by Shinya Maeda's avatar Shinya Maeda

Support Resrouce Group in Cross-Project pipelines

This commit supports resource groups in cross-project
pipelines.
parent 2783d34d
......@@ -27,7 +27,7 @@ module Ci
# rubocop:enable Cop/ActiveRecordSerialize
state_machine :status do
after_transition [:created, :manual] => :pending do |bridge|
after_transition [:created, :manual, :waiting_for_resource] => :pending do |bridge|
next unless bridge.downstream_project
bridge.run_after_commit do
......@@ -156,6 +156,10 @@ module Ci
false
end
def any_unmet_prerequisites?
false
end
def expanded_environment_name
end
......
---
title: Pipeline-level concurrency control with Cross-Project/Parent-Child pipelines
merge_request: 53007
author:
type: added
......@@ -3930,6 +3930,61 @@ It can't start or end with `/`.
For more information, see [Deployments Safety](../environments/deployment_safety.md).
#### Pipeline-level concurrency control with Cross-Project/Parent-Child pipelines
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39057) in GitLab 13.9.
You can define `resource_group` for downstream pipelines that are sensitive to
concurrent executions. Downstream pipelines can be triggered by [`trigger` keyword](#trigger)
and [`resource_group` keyword](#resource_group) can co-exist with it. This is useful to control the
concurency for deployment pipelines, while running non-sensitive jobs concurrently.
In ths following example, we have two pipeline configurations in a project.
When a pipeline started running, non-sensitive jobs are executed at first and they
won't be affected by the concurrent executions in the other pipelines.
However, when it's about to trigger a deployment (child) pipeline, GitLab ensures that
there are no other deployment pipelines running, and if it's conflicted,
the pipeline will wait until it's finished.
```yaml
# .gitlab-ci.yml (parent pipeline)
build:
stage: build
script: echo "Building..."
test:
stage: test
script: echo "Testing..."
deploy:
stage: deploy
trigger:
include: deploy.gitlab-ci.yml
strategy: depend
resource_group: AWS-production
```
```yaml
# deploy.gitlab-ci.yml (child pipeline)
stages:
- provision
- deploy
provision:
stage: provision
script: echo "Provisioning..."
deployment:
stage: deploy
script: echo "Deploying..."
```
Please note that [`strategy: depend`](#linking-pipelines-with-triggerstrategy)
must be defined with the `trigger` keyword. This ensures that the lock won't
be relesed until the downstream pipeline has finished.
### `release`
> [Introduced](https://gitlab.com/gitlab-org/gitlab/merge_requests/19298) in GitLab 13.2.
......
......@@ -73,15 +73,26 @@ module Gitlab
def to_resource
strong_memoize(:resource) do
processable = initialize_processable
assign_resource_group(processable)
processable
end
end
def initialize_processable
if bridge?
::Ci::Bridge.new(attributes)
else
::Ci::Build.new(attributes).tap do |build|
build.assign_attributes(self.class.environment_attributes_for(build))
build.resource_group = Seed::Build::ResourceGroup.new(build, @resource_group_key).to_resource
end
end
end
def assign_resource_group(processable)
processable.resource_group =
Seed::Processable::ResourceGroup.new(processable, @resource_group_key)
.to_resource
end
def self.environment_attributes_for(build)
......
......@@ -4,7 +4,7 @@ module Gitlab
module Ci
module Pipeline
module Seed
class Build
module Processable
class ResourceGroup < Seed::Base
include Gitlab::Utils::StrongMemoize
......
......@@ -8,6 +8,7 @@ module Gitlab
def self.extended_statuses
[[Status::Bridge::Failed],
[Status::Bridge::Manual],
[Status::Bridge::WaitingForResource],
[Status::Bridge::Play],
[Status::Bridge::Action]]
end
......
# frozen_string_literal: true
module Gitlab
module Ci
module Status
module Bridge
class WaitingForResource < Status::Processable::WaitingForResource
end
end
end
end
end
......@@ -4,22 +4,7 @@ module Gitlab
module Ci
module Status
module Build
class WaitingForResource < Status::Extended
##
# TODO: image is shared with 'pending'
# until we get a dedicated one
#
def illustration
{
image: 'illustrations/pending_job_empty.svg',
size: 'svg-430',
title: _('This job is waiting for resource: ') + subject.resource_group.key
}
end
def self.matches?(build, _)
build.waiting_for_resource?
end
class WaitingForResource < Status::Processable::WaitingForResource
end
end
end
......
# frozen_string_literal: true
module Gitlab
module Ci
module Status
module Processable
class WaitingForResource < Status::Extended
##
# TODO: image is shared with 'pending'
# until we get a dedicated one
#
def illustration
{
image: 'illustrations/pending_job_empty.svg',
size: 'svg-430',
title: _('This job is waiting for resource: ') + subject.resource_group.key
}
end
def self.matches?(build, _)
build.waiting_for_resource?
end
end
end
end
end
end
......@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Ci::Pipeline::Seed::Build::ResourceGroup do
RSpec.describe Gitlab::Ci::Pipeline::Seed::Processable::ResourceGroup do
let_it_be(:project) { create(:project) }
let(:job) { build(:ci_build, project: project) }
let(:seed) { described_class.new(job, resource_group_key) }
......
......@@ -89,8 +89,6 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
YAML
end
# TODO: This test will be properly implemented in the next MR
# for https://gitlab.com/gitlab-org/gitlab/-/issues/39057.
it 'creates bridge job but still resource group is no-op', :aggregate_failures do
pipeline = create_pipeline!
......@@ -98,7 +96,7 @@ RSpec.describe Ci::CreatePipelineService, '#execute' do
expect(pipeline).to be_persisted
expect(test).to be_a Ci::Bridge
expect(project.resource_groups.count).to eq(0)
expect(project.resource_groups.count).to eq(1)
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