Commit 6d1c5761 authored by Lin Jen-Shin's avatar Lin Jen-Shin

Improve how we could cancel pipelines:

* Introduce `HasStatus.cancelable` which we might be able to cancel
* Cancel and check upon `cancelable`
* Also cancel on `CommitStatus` rather than just `Ci::Build`

Fixes #23635

Fixes #17845
parent 891465ba
...@@ -167,11 +167,11 @@ module Ci ...@@ -167,11 +167,11 @@ module Ci
end end
def cancelable? def cancelable?
builds.running_or_pending.any? statuses.cancelable.any?
end end
def cancel_running def cancel_running
builds.running_or_pending.each(&:cancel) statuses.cancelable.each(&:cancel)
end end
def retry_failed(user) def retry_failed(user)
......
...@@ -73,6 +73,10 @@ module HasStatus ...@@ -73,6 +73,10 @@ module HasStatus
scope :skipped, -> { where(status: 'skipped') } scope :skipped, -> { where(status: 'skipped') }
scope :running_or_pending, -> { where(status: [:running, :pending]) } scope :running_or_pending, -> { where(status: [:running, :pending]) }
scope :finished, -> { where(status: [:success, :failed, :canceled]) } scope :finished, -> { where(status: [:success, :failed, :canceled]) }
scope :cancelable, -> do
where(status: [:running, :pending, :created])
end
end end
def started? def started?
......
---
title: Fix cancelling created or external pipelines
merge_request: 7508
author:
...@@ -90,8 +90,8 @@ describe "Pipelines" do ...@@ -90,8 +90,8 @@ describe "Pipelines" do
visit namespace_project_pipelines_path(project.namespace, project) visit namespace_project_pipelines_path(project.namespace, project)
end end
it 'is not cancelable' do it 'is cancelable' do
expect(page).not_to have_link('Cancel') expect(page).to have_link('Cancel')
end end
it 'has pipeline running' do it 'has pipeline running' do
......
...@@ -402,6 +402,46 @@ describe Ci::Pipeline, models: true do ...@@ -402,6 +402,46 @@ describe Ci::Pipeline, models: true do
end end
end end
describe '#cancelable?' do
subject { pipeline.cancelable? }
%i[created running pending].each do |status|
context "when there is a build #{status}" do
before do
create(:ci_build, status, pipeline: pipeline)
end
it { is_expected.to be_truthy }
end
context "when there is an external job #{status}" do
before do
create(:generic_commit_status, status, pipeline: pipeline)
end
it { is_expected.to be_truthy }
end
end
%i[success failed canceled].each do |status|
context "when there is a build #{status}" do
before do
create(:ci_build, status, pipeline: pipeline)
end
it { is_expected.to be_falsey }
end
context "when there is an external job #{status}" do
before do
create(:generic_commit_status, status, pipeline: pipeline)
end
it { is_expected.to be_falsey }
end
end
end
describe '#execute_hooks' do describe '#execute_hooks' do
let!(:build_a) { create_build('a', 0) } let!(:build_a) { create_build('a', 0) }
let!(:build_b) { create_build('b', 1) } let!(:build_b) { create_build('b', 1) }
......
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