Commit e00da96c authored by Kamil Trzcinski's avatar Kamil Trzcinski

Improve manual actions code and add model, service and feature tests

Manual actions are accessible from:
- Pipelines
- Builds
- Environments
- Deployments
parent 3248c9fb
class Projects::BuildsController < Projects::ApplicationController class Projects::BuildsController < Projects::ApplicationController
before_action :build, except: [:index, :cancel_all] before_action :build, except: [:index, :cancel_all]
before_action :authorize_read_build!, except: [:cancel, :cancel_all, :retry] before_action :authorize_read_build!, except: [:cancel, :cancel_all, :retry, :play]
before_action :authorize_update_build!, except: [:index, :show, :status, :raw] before_action :authorize_update_build!, except: [:index, :show, :status, :raw]
layout 'project' layout 'project'
......
...@@ -15,7 +15,7 @@ module Ci ...@@ -15,7 +15,7 @@ module Ci
scope :with_artifacts, ->() { where.not(artifacts_file: nil) } scope :with_artifacts, ->() { where.not(artifacts_file: nil) }
scope :with_expired_artifacts, ->() { with_artifacts.where('artifacts_expire_at < ?', Time.now) } scope :with_expired_artifacts, ->() { with_artifacts.where('artifacts_expire_at < ?', Time.now) }
scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) } scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) }
scope :manual_actions, ->() { where(when: :manual).without_created } scope :manual_actions, ->() { where(when: :manual).relevant }
mount_uploader :artifacts_file, ArtifactUploader mount_uploader :artifacts_file, ArtifactUploader
mount_uploader :artifacts_metadata, ArtifactUploader mount_uploader :artifacts_metadata, ArtifactUploader
...@@ -96,15 +96,19 @@ module Ci ...@@ -96,15 +96,19 @@ module Ci
self.when == 'manual' self.when == 'manual'
end end
def other_actions
pipeline.manual_actions.where.not(id: self)
end
def playable? def playable?
project.builds_enabled? && commands.present? && manual? project.builds_enabled? && commands.present? && manual?
end end
def play(current_user = nil) def play(current_user = nil)
if skipped? # Try to queue a current build
# We can run skipped build if self.queue
new_build.user = current_user self.update(user: current_user)
new_build.queue self
else else
# Otherwise we need to create a duplicate # Otherwise we need to create a duplicate
Ci::Build.retry(self, current_user) Ci::Build.retry(self, current_user)
......
...@@ -34,6 +34,6 @@ class Deployment < ActiveRecord::Base ...@@ -34,6 +34,6 @@ class Deployment < ActiveRecord::Base
end end
def manual_actions def manual_actions
deployable.try(:manual_actions) deployable.try(:other_actions)
end end
end end
...@@ -86,6 +86,6 @@ ...@@ -86,6 +86,6 @@
= link_to retry_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Retry', class: 'btn btn-build' do = link_to retry_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Retry', class: 'btn btn-build' do
= icon('repeat') = icon('repeat')
- elsif build.playable? - elsif build.playable?
= link_to play_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Retry', class: 'btn btn-build' do = link_to play_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Play', class: 'btn btn-build' do
= icon('play') = icon('play')
...@@ -60,16 +60,17 @@ ...@@ -60,16 +60,17 @@
- actions = pipeline.manual_actions - actions = pipeline.manual_actions
- if artifacts.present? || actions.any? - if artifacts.present? || actions.any?
.btn-group.inline .btn-group.inline
- if playable.any? - if actions.any?
.btn-group .btn-group
%a.dropdown-toggle.btn.btn-default{type: 'button', 'data-toggle' => 'dropdown'} %a.dropdown-toggle.btn.btn-default{type: 'button', 'data-toggle' => 'dropdown'}
= icon("play") = icon("play")
%b.caret %b.caret
%ul.dropdown-menu.dropdown-menu-align-right %ul.dropdown-menu.dropdown-menu-align-right
- actions.each do |build|
%li %li
= link_to play_namespace_project_build_path(@project.namespace, @project, build), rel: 'nofollow' do = link_to play_namespace_project_build_path(@project.namespace, @project, build), method: :post, rel: 'nofollow' do
= icon("play") = icon("play")
%span= actions.name.titleize %span= build.name.titleize
- if artifacts.present? - if artifacts.present?
.btn-group .btn-group
%a.dropdown-toggle.btn.btn-default.build-artifacts{type: 'button', 'data-toggle' => 'dropdown'} %a.dropdown-toggle.btn.btn-default.build-artifacts{type: 'button', 'data-toggle' => 'dropdown'}
......
- if can?(current_user, :create_deployment, deployment) && deployment.deployable
.pull-right
- actions = deployment.manual_actions
- if actions.present?
.btn-group.inline
.btn-group
%a.dropdown-toggle.btn.btn-default{type: 'button', 'data-toggle' => 'dropdown'}
= icon("play")
%b.caret
%ul.dropdown-menu.dropdown-menu-align-right
- actions.each do |action|
%li
= link_to [:play, @project.namespace.becomes(Namespace), @project, action], method: :post, rel: 'nofollow' do
= icon("play")
%span= action.name.titleize
- if defined?(allow_rollback) && allow_rollback
= link_to [:retry, @project.namespace.becomes(Namespace), @project, deployment.deployable], method: :post, class: 'btn btn-build' do
- if deployment.last?
Retry
- else
Rollback
...@@ -7,19 +7,11 @@ ...@@ -7,19 +7,11 @@
%td %td
- if deployment.deployable - if deployment.deployable
= link_to namespace_project_build_path(@project.namespace, @project, deployment.deployable) do = link_to [@project.namespace.becomes(Namespace), @project, deployment.deployable] do
= "#{deployment.deployable.name} (##{deployment.deployable.id})" = "#{deployment.deployable.name} (##{deployment.deployable.id})"
%td %td
#{time_ago_with_tooltip(deployment.created_at)} #{time_ago_with_tooltip(deployment.created_at)}
%td %td
- if can?(current_user, :create_deployment, deployment) && deployment.deployable = render 'projects/deployments/actions', deployment: deployment, allow_rollback: true
.pull-right
= link_to retry_namespace_project_build_path(@project.namespace, @project, deployment.deployable), method: :post, class: 'btn btn-build' do
- if deployment.last?
Retry
- else
Rollback
= render 'playable', deployment: deployment
- actions = deployment.manual_actions
- if actions.any?
.btn-group.inline
.btn-group
%a.dropdown-toggle.btn.btn-default{type: 'button', 'data-toggle' => 'dropdown'}
= icon("play")
%b.caret
%ul.dropdown-menu.dropdown-menu-align-right
%li
= link_to play_namespace_project_build_path(@project.namespace, @project, build), rel: 'nofollow' do
= icon("play")
%span= actions.name.titleize
...@@ -17,5 +17,4 @@ ...@@ -17,5 +17,4 @@
#{time_ago_with_tooltip(last_deployment.created_at)} #{time_ago_with_tooltip(last_deployment.created_at)}
%td %td
- if can?(current_user, :create_deployment, last_deployment) && last_deployment.deployable = render 'projects/deployments/actions', deployment: last_deployment
= render 'projects/deployments/playable', deployment: last_deployment
...@@ -28,4 +28,5 @@ ...@@ -28,4 +28,5 @@
%th Environment %th Environment
%th Last deployment %th Last deployment
%th Date %th Date
%th
= render @environments = render @environments
# Description: https://coderwall.com/p/heed_q/rails-routing-and-namespaced-models
#
# This allows us to use CI ActiveRecord objects in all routes and use it:
# - [project.namespace, project, build]
#
# instead of:
# - namespace_project_build_path(project.namespace, project, build)
#
# Without that, Ci:: namespace is used for resolving routes:
# - namespace_project_ci_build_path(project.namespace, project, build)
module Ci
def self.use_relative_model_naming?
true
end
end
...@@ -485,6 +485,7 @@ failure. ...@@ -485,6 +485,7 @@ failure.
1. `on_failure` - execute build only when at least one build from prior stages 1. `on_failure` - execute build only when at least one build from prior stages
fails. fails.
1. `always` - execute build regardless of the status of builds from prior stages. 1. `always` - execute build regardless of the status of builds from prior stages.
1. `manual` - execute build manually.
For example: For example:
...@@ -516,6 +517,7 @@ deploy_job: ...@@ -516,6 +517,7 @@ deploy_job:
stage: deploy stage: deploy
script: script:
- make deploy - make deploy
when: manual
cleanup_job: cleanup_job:
stage: cleanup stage: cleanup
...@@ -527,7 +529,20 @@ cleanup_job: ...@@ -527,7 +529,20 @@ cleanup_job:
The above script will: The above script will:
1. Execute `cleanup_build_job` only when `build_job` fails 1. Execute `cleanup_build_job` only when `build_job` fails
2. Always execute `cleanup_job` as the last step in pipeline. 2. Always execute `cleanup_job` as the last step in pipeline
3. Allow you to manually execute `deploy_job` form GitLab
#### Manual actions
>**Note:**
Introduced in GitLab 8.10.
Manual actions are special type of jobs that are not executed automatically in pipeline.
They need to be explicitly started by the user.
Manual actions can be started from pipelines, builds, environments and deployments views.
You can execute the same manual action multiple times.
Example usage of manual actions is deployment, ex. promote a staging environment to production.
### environment ### environment
......
...@@ -43,6 +43,11 @@ FactoryGirl.define do ...@@ -43,6 +43,11 @@ FactoryGirl.define do
status 'pending' status 'pending'
end end
trait :manual do
status 'skipped'
self.when 'manual'
end
trait :allowed_to_fail do trait :allowed_to_fail do
allow_failure true allow_failure true
end end
......
...@@ -13,6 +13,7 @@ feature 'Environments', feature: true do ...@@ -13,6 +13,7 @@ feature 'Environments', feature: true do
describe 'when showing environments' do describe 'when showing environments' do
given!(:environment) { } given!(:environment) { }
given!(:deployment) { } given!(:deployment) { }
given!(:manual) { }
before do before do
visit namespace_project_environments_path(project.namespace, project) visit namespace_project_environments_path(project.namespace, project)
...@@ -43,6 +44,24 @@ feature 'Environments', feature: true do ...@@ -43,6 +44,24 @@ feature 'Environments', feature: true do
scenario 'does show deployment SHA' do scenario 'does show deployment SHA' do
expect(page).to have_link(deployment.short_sha) expect(page).to have_link(deployment.short_sha)
end end
context 'with build and manual actions' do
given(:pipeline) { create(:ci_pipeline, project: project) }
given(:build) { create(:ci_build, pipeline: pipeline) }
given(:deployment) { create(:deployment, environment: environment, deployable: build) }
given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') }
scenario 'does show a play button' do
expect(page).to have_link(manual.name.titleize)
end
scenario 'does allow to play manual action' do
expect(manual).to be_skipped
expect{ click_link(manual.name.titleize) }.to change{ Ci::Pipeline.count }.by(0)
expect(page).to have_content(manual.name)
expect(manual.reload).to be_pending
end
end
end end
end end
...@@ -54,6 +73,7 @@ feature 'Environments', feature: true do ...@@ -54,6 +73,7 @@ feature 'Environments', feature: true do
describe 'when showing the environment' do describe 'when showing the environment' do
given(:environment) { create(:environment, project: project) } given(:environment) { create(:environment, project: project) }
given!(:deployment) { } given!(:deployment) { }
given!(:manual) { }
before do before do
visit namespace_project_environment_path(project.namespace, project, environment) visit namespace_project_environment_path(project.namespace, project, environment)
...@@ -77,7 +97,8 @@ feature 'Environments', feature: true do ...@@ -77,7 +97,8 @@ feature 'Environments', feature: true do
end end
context 'with build' do context 'with build' do
given(:build) { create(:ci_build, project: project) } given(:pipeline) { create(:ci_pipeline, project: project) }
given(:build) { create(:ci_build, pipeline: pipeline) }
given(:deployment) { create(:deployment, environment: environment, deployable: build) } given(:deployment) { create(:deployment, environment: environment, deployable: build) }
scenario 'does show build name' do scenario 'does show build name' do
...@@ -87,6 +108,21 @@ feature 'Environments', feature: true do ...@@ -87,6 +108,21 @@ feature 'Environments', feature: true do
scenario 'does show retry button' do scenario 'does show retry button' do
expect(page).to have_link('Retry') expect(page).to have_link('Retry')
end end
context 'with manual action' do
given(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy to production') }
scenario 'does show a play button' do
expect(page).to have_link(manual.name.titleize)
end
scenario 'does allow to play manual action' do
expect(manual).to be_skipped
expect{ click_link(manual.name.titleize) }.to change{ Ci::Pipeline.count }.by(0)
expect(page).to have_content(manual.name)
expect(manual.reload).to be_pending
end
end
end end
end end
end end
......
...@@ -62,6 +62,20 @@ describe "Pipelines" do ...@@ -62,6 +62,20 @@ describe "Pipelines" do
end end
end end
context 'with manual actions' do
let!(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'manual build', stage: 'test', commands: 'test') }
before { visit namespace_project_pipelines_path(project.namespace, project) }
it { expect(page).to have_link('Manual Build') }
context 'when playing' do
before { click_link('Manual Build') }
it { expect(manual.reload).to be_pending }
end
end
context 'for generic statuses' do context 'for generic statuses' do
context 'when running' do context 'when running' do
let!(:running) { create(:generic_commit_status, status: 'running', pipeline: pipeline, stage: 'test') } let!(:running) { create(:generic_commit_status, status: 'running', pipeline: pipeline, stage: 'test') }
...@@ -117,6 +131,7 @@ describe "Pipelines" do ...@@ -117,6 +131,7 @@ describe "Pipelines" do
@success = create(:ci_build, :success, pipeline: pipeline, stage: 'build', name: 'build') @success = create(:ci_build, :success, pipeline: pipeline, stage: 'build', name: 'build')
@failed = create(:ci_build, :failed, pipeline: pipeline, stage: 'test', name: 'test', commands: 'test') @failed = create(:ci_build, :failed, pipeline: pipeline, stage: 'test', name: 'test', commands: 'test')
@running = create(:ci_build, :running, pipeline: pipeline, stage: 'deploy', name: 'deploy') @running = create(:ci_build, :running, pipeline: pipeline, stage: 'deploy', name: 'deploy')
@manual = create(:ci_build, :manual, pipeline: pipeline, stage: 'deploy', name: 'manual build')
@external = create(:generic_commit_status, status: 'success', pipeline: pipeline, name: 'jenkins', stage: 'external') @external = create(:generic_commit_status, status: 'success', pipeline: pipeline, name: 'jenkins', stage: 'external')
end end
...@@ -131,6 +146,7 @@ describe "Pipelines" do ...@@ -131,6 +146,7 @@ describe "Pipelines" do
expect(page).to have_content(@external.id) expect(page).to have_content(@external.id)
expect(page).to have_content('Retry failed') expect(page).to have_content('Retry failed')
expect(page).to have_content('Cancel running') expect(page).to have_content('Cancel running')
expect(page).to have_link('Play')
end end
context 'retrying builds' do context 'retrying builds' do
...@@ -154,6 +170,12 @@ describe "Pipelines" do ...@@ -154,6 +170,12 @@ describe "Pipelines" do
it { expect(page).to have_selector('.ci-canceled') } it { expect(page).to have_selector('.ci-canceled') }
end end
end end
context 'playing manual build' do
before { click_link('Play') }
it { expect(@manual.reload).to be_pending }
end
end end
describe 'POST /:project/pipelines' do describe 'POST /:project/pipelines' do
......
...@@ -670,4 +670,55 @@ describe Ci::Build, models: true do ...@@ -670,4 +670,55 @@ describe Ci::Build, models: true do
end end
end end
end end
describe '#manual?' do
before do
build.update(when: value)
end
subject { build.manual? }
context 'when is set to manual' do
let(:value) { 'manual' }
it { is_expected.to be_truthy }
end
context 'when set to something else' do
let(:value) { 'something else' }
it { is_expected.to be_falsey }
end
end
describe '#other_actions' do
let(:build) { create(:ci_build, :manual, pipeline: pipeline) }
let!(:other_build) { create(:ci_build, :manual, pipeline: pipeline, name: 'other action') }
subject { build.other_actions }
it 'returns other actions' do
is_expected.to contain_exactly(other_build)
end
end
describe '#play' do
let(:build) { create(:ci_build, :manual, pipeline: pipeline) }
subject { build.play }
it 'enques a build' do
is_expected.to be_pending
is_expected.to eq(build)
end
context 'for success build' do
before { build.queue }
it 'creates a new build' do
is_expected.to be_pending
is_expected.not_to eq(build)
end
end
end
end end
...@@ -416,4 +416,28 @@ describe Ci::Pipeline, models: true do ...@@ -416,4 +416,28 @@ describe Ci::Pipeline, models: true do
end end
end end
end end
describe '#manual_actions' do
subject { pipeline.manual_actions }
it 'when none defined' do
is_expected.to be_empty
end
context 'when action defined' do
let!(:manual) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy') }
it 'returns one action' do
is_expected.to contain_exactly(manual)
end
context 'there are multiple of the same name' do
let!(:manual2) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy') }
it 'returns latest one' do
is_expected.to contain_exactly(manual2)
end
end
end
end
end end
...@@ -11,6 +11,7 @@ describe Deployment, models: true do ...@@ -11,6 +11,7 @@ describe Deployment, models: true do
it { is_expected.to delegate_method(:name).to(:environment).with_prefix } it { is_expected.to delegate_method(:name).to(:environment).with_prefix }
it { is_expected.to delegate_method(:commit).to(:project) } it { is_expected.to delegate_method(:commit).to(:project) }
it { is_expected.to delegate_method(:commit_title).to(:commit).as(:try) } it { is_expected.to delegate_method(:commit_title).to(:commit).as(:try) }
it { is_expected.to delegate_method(:manual_actions).to(:deployable).as(:try) }
it { is_expected.to validate_presence_of(:ref) } it { is_expected.to validate_presence_of(:ref) }
it { is_expected.to validate_presence_of(:sha) } it { is_expected.to validate_presence_of(:sha) }
......
require 'spec_helper'
describe Ci::CreatePipelineService, services: true do
let(:project) { FactoryGirl.create(:project) }
let(:user) { create(:admin) }
before do
stub_ci_pipeline_to_return_yaml_file
end
describe '#execute' do
def execute(params)
described_class.new(project, user, params).execute
end
context 'valid params' do
let(:pipeline) do
execute(ref: 'refs/heads/master',
before: '00000000',
after: project.commit.id,
commits: [{ message: "Message" }])
end
it { expect(pipeline).to be_kind_of(Ci::Pipeline) }
it { expect(pipeline).to be_valid }
it { expect(pipeline).to be_persisted }
it { expect(pipeline).to eq(project.pipelines.last) }
it { expect(pipeline).to have_attributes(user: user) }
it { expect(pipeline.builds.first).to be_kind_of(Ci::Build) }
end
context "skip tag if there is no build for it" do
it "creates commit if there is appropriate job" do
result = execute(ref: 'refs/heads/master',
before: '00000000',
after: project.commit.id,
commits: [{ message: "Message" }])
expect(result).to be_persisted
end
it "creates commit if there is no appropriate job but deploy job has right ref setting" do
config = YAML.dump({ deploy: { script: "ls", only: ["master"] } })
stub_ci_pipeline_yaml_file(config)
result = execute(ref: 'refs/heads/master',
before: '00000000',
after: project.commit.id,
commits: [{ message: "Message" }])
expect(result).to be_persisted
end
end
it 'skips creating pipeline for refs without .gitlab-ci.yml' do
stub_ci_pipeline_yaml_file(nil)
result = execute(ref: 'refs/heads/master',
before: '00000000',
after: project.commit.id,
commits: [{ message: 'Message' }])
expect(result).not_to be_persisted
expect(Ci::Pipeline.count).to eq(0)
end
it 'fails commits if yaml is invalid' do
message = 'message'
allow_any_instance_of(Ci::Pipeline).to receive(:git_commit_message) { message }
stub_ci_pipeline_yaml_file('invalid: file: file')
commits = [{ message: message }]
pipeline = execute(ref: 'refs/heads/master',
before: '00000000',
after: project.commit.id,
commits: commits)
expect(pipeline).to be_persisted
expect(pipeline.builds.any?).to be false
expect(pipeline.status).to eq('failed')
expect(pipeline.yaml_errors).not_to be_nil
end
context 'when commit contains a [ci skip] directive' do
let(:message) { "some message[ci skip]" }
let(:messageFlip) { "some message[skip ci]" }
let(:capMessage) { "some message[CI SKIP]" }
let(:capMessageFlip) { "some message[SKIP CI]" }
before do
allow_any_instance_of(Ci::Pipeline).to receive(:git_commit_message) { message }
end
it "skips builds creation if there is [ci skip] tag in commit message" do
commits = [{ message: message }]
pipeline = execute(ref: 'refs/heads/master',
before: '00000000',
after: project.commit.id,
commits: commits)
expect(pipeline).to be_persisted
expect(pipeline.builds.any?).to be false
expect(pipeline.status).to eq("skipped")
end
it "skips builds creation if there is [skip ci] tag in commit message" do
commits = [{ message: messageFlip }]
pipeline = execute(ref: 'refs/heads/master',
before: '00000000',
after: project.commit.id,
commits: commits)
expect(pipeline).to be_persisted
expect(pipeline.builds.any?).to be false
expect(pipeline.status).to eq("skipped")
end
it "skips builds creation if there is [CI SKIP] tag in commit message" do
commits = [{ message: capMessage }]
pipeline = execute(ref: 'refs/heads/master',
before: '00000000',
after: project.commit.id,
commits: commits)
expect(pipeline).to be_persisted
expect(pipeline.builds.any?).to be false
expect(pipeline.status).to eq("skipped")
end
it "skips builds creation if there is [SKIP CI] tag in commit message" do
commits = [{ message: capMessageFlip }]
pipeline = execute(ref: 'refs/heads/master',
before: '00000000',
after: project.commit.id,
commits: commits)
expect(pipeline).to be_persisted
expect(pipeline.builds.any?).to be false
expect(pipeline.status).to eq("skipped")
end
it "does not skips builds creation if there is no [ci skip] or [skip ci] tag in commit message" do
allow_any_instance_of(Ci::Pipeline).to receive(:git_commit_message) { "some message" }
commits = [{ message: "some message" }]
pipeline = execute(ref: 'refs/heads/master',
before: '00000000',
after: project.commit.id,
commits: commits)
expect(pipeline).to be_persisted
expect(pipeline.builds.first.name).to eq("rspec")
end
it "fails builds creation if there is [ci skip] tag in commit message and yaml is invalid" do
stub_ci_pipeline_yaml_file('invalid: file: fiile')
commits = [{ message: message }]
pipeline = execute(ref: 'refs/heads/master',
before: '00000000',
after: project.commit.id,
commits: commits)
expect(pipeline).to be_persisted
expect(pipeline.builds.any?).to be false
expect(pipeline.status).to eq("failed")
expect(pipeline.yaml_errors).not_to be_nil
end
end
it "creates commit with failed status if yaml is invalid" do
stub_ci_pipeline_yaml_file('invalid: file')
commits = [{ message: "some message" }]
pipeline = execute(ref: 'refs/heads/master',
before: '00000000',
after: project.commit.id,
commits: commits)
expect(pipeline).to be_persisted
expect(pipeline.status).to eq("failed")
expect(pipeline.builds.any?).to be false
end
context 'when there are no jobs for this pipeline' do
before do
config = YAML.dump({ test: { script: 'ls', only: ['feature'] } })
stub_ci_pipeline_yaml_file(config)
end
it 'does not create a new pipeline' do
result = execute(ref: 'refs/heads/master',
before: '00000000',
after: project.commit.id,
commits: [{ message: 'some msg' }])
expect(result).not_to be_persisted
expect(Ci::Build.all).to be_empty
expect(Ci::Pipeline.count).to eq(0)
end
end
context 'with manual actions' do
before do
config = YAML.dump({ deploy: { script: 'ls', when: 'manual' } })
stub_ci_pipeline_yaml_file(config)
end
it 'does not create a new pipeline' do
result = execute(ref: 'refs/heads/master',
before: '00000000',
after: project.commit.id,
commits: [{ message: 'some msg' }])
expect(result).to be_persisted
expect(result.manual_actions).not_to be_empty
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