summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/models/ci/pipeline.rb19
-rw-r--r--app/models/commit_status.rb5
-rw-r--r--app/presenters/ci/build_presenter.rb4
-rw-r--r--app/presenters/ci/pipeline_presenter.rb4
-rw-r--r--app/services/ci/create_pipeline_service.rb3
-rw-r--r--db/migrate/20170406114958_add_auto_canceled_by_id_to_ci_builds.rb9
-rw-r--r--db/migrate/20170406115029_add_auto_canceled_by_id_foreign_key_to_ci_builds.rb22
-rw-r--r--db/schema.rb2
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml2
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml1
-rw-r--r--spec/models/ci/pipeline_spec.rb37
-rw-r--r--spec/models/commit_status_spec.rb26
-rw-r--r--spec/presenters/ci/build_presenter_spec.rb34
-rw-r--r--spec/presenters/ci/pipeline_presenter_spec.rb2
14 files changed, 143 insertions, 27 deletions
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 8aad149519e..e03def25755 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -11,6 +11,8 @@ module Ci
belongs_to :auto_canceled_by, class_name: 'Ci::Pipeline'
has_many :auto_canceled_pipelines, class_name: 'Ci::Pipeline', foreign_key: 'auto_canceled_by_id'
+ has_many :auto_canceled_jobs, class_name: 'CommitStatus', foreign_key: 'auto_canceled_by_id'
+
has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id
has_many :builds, foreign_key: :commit_id
has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id
@@ -93,6 +95,10 @@ module Ci
PipelineNotificationWorker.perform_async(pipeline.id)
end
end
+
+ after_transition :canceled => any - [:canceled] do |pipeline|
+ pipeline.update(auto_canceled_by: nil)
+ end
end
# ref can't be HEAD or SHA, can only be branch/tag name
@@ -226,10 +232,21 @@ module Ci
def cancel_running
Gitlab::OptimisticLocking.retry_lock(
statuses.cancelable) do |cancelable|
- cancelable.find_each(&:cancel)
+ cancelable.find_each do |job|
+ yield(job) if block_given?
+ job.cancel
+ end
end
end
+ def auto_cancel_running(pipeline)
+ update(auto_canceled_by: pipeline)
+
+ cancel_running do |job|
+ job.auto_canceled_by = pipeline
+ end
+ end
+
def retry_failed(current_user)
Ci::RetryPipelineService.new(project, current_user)
.execute(self)
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index 17b322b5ae3..2c4033146bf 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -7,6 +7,7 @@ class CommitStatus < ActiveRecord::Base
belongs_to :project
belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id
+ belongs_to :auto_canceled_by, class_name: 'Ci::Pipeline'
belongs_to :user
delegate :commit, to: :pipeline
@@ -137,6 +138,10 @@ class CommitStatus < ActiveRecord::Base
false
end
+ def auto_canceled?
+ canceled? && auto_canceled_by_id?
+ end
+
# Added in 9.0 to keep backward compatibility for projects exported in 8.17
# and prior.
def gl_project_id
diff --git a/app/presenters/ci/build_presenter.rb b/app/presenters/ci/build_presenter.rb
index d9970396cc6..c495c3f39bb 100644
--- a/app/presenters/ci/build_presenter.rb
+++ b/app/presenters/ci/build_presenter.rb
@@ -13,8 +13,8 @@ module Ci
end
def status_title
- if canceled? && pipeline.auto_canceled?
- "Job is redundant and is auto-canceled by Pipeline ##{pipeline.auto_canceled_by_id}"
+ if auto_canceled?
+ "Job is redundant and is auto-canceled by Pipeline ##{auto_canceled_by_id}"
end
end
end
diff --git a/app/presenters/ci/pipeline_presenter.rb b/app/presenters/ci/pipeline_presenter.rb
index b8e74bf5509..a542bdd8295 100644
--- a/app/presenters/ci/pipeline_presenter.rb
+++ b/app/presenters/ci/pipeline_presenter.rb
@@ -3,7 +3,9 @@ module Ci
presents :pipeline
def status_title
- "Pipeline is redundant and is auto-canceled by Pipeline ##{auto_canceled_by_id}" if auto_canceled?
+ if auto_canceled?
+ "Pipeline is redundant and is auto-canceled by Pipeline ##{auto_canceled_by_id}"
+ end
end
end
end
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index f944c869922..21350be5557 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -68,8 +68,7 @@ module Ci
def cancel_pending_pipelines
Gitlab::OptimisticLocking.retry_lock(auto_cancelable_pipelines) do |cancelables|
cancelables.find_each do |cancelable|
- cancelable.cancel_running
- cancelable.update_attributes(auto_canceled_by_id: pipeline.id)
+ cancelable.auto_cancel_running(pipeline)
end
end
end
diff --git a/db/migrate/20170406114958_add_auto_canceled_by_id_to_ci_builds.rb b/db/migrate/20170406114958_add_auto_canceled_by_id_to_ci_builds.rb
new file mode 100644
index 00000000000..c1d803b4308
--- /dev/null
+++ b/db/migrate/20170406114958_add_auto_canceled_by_id_to_ci_builds.rb
@@ -0,0 +1,9 @@
+class AddAutoCanceledByIdToCiBuilds < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :ci_builds, :auto_canceled_by_id, :integer
+ end
+end
diff --git a/db/migrate/20170406115029_add_auto_canceled_by_id_foreign_key_to_ci_builds.rb b/db/migrate/20170406115029_add_auto_canceled_by_id_foreign_key_to_ci_builds.rb
new file mode 100644
index 00000000000..3004683933b
--- /dev/null
+++ b/db/migrate/20170406115029_add_auto_canceled_by_id_foreign_key_to_ci_builds.rb
@@ -0,0 +1,22 @@
+class AddAutoCanceledByIdForeignKeyToCiBuilds < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ on_delete =
+ if Gitlab::Database.mysql?
+ :nullify
+ else
+ 'SET NULL'
+ end
+
+ add_concurrent_foreign_key :ci_builds, :ci_pipelines, column: :auto_canceled_by_id, on_delete: on_delete
+ end
+
+ def down
+ remove_foreign_key :ci_builds, column: :auto_canceled_by_id
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 59dbe9fd69a..afc67dba702 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -223,6 +223,7 @@ ActiveRecord::Schema.define(version: 20170405080720) do
t.string "token"
t.integer "lock_version"
t.string "coverage_regex"
+ t.integer "auto_canceled_by_id"
end
add_index "ci_builds", ["commit_id", "stage_idx", "created_at"], name: "index_ci_builds_on_commit_id_and_stage_idx_and_created_at", using: :btree
@@ -1300,6 +1301,7 @@ ActiveRecord::Schema.define(version: 20170405080720) do
add_foreign_key "boards", "projects"
add_foreign_key "chat_teams", "namespaces", on_delete: :cascade
+ add_foreign_key "ci_builds", "ci_pipelines", column: "auto_canceled_by_id", name: "fk_a2141b1522", on_delete: :nullify
add_foreign_key "ci_pipelines", "ci_pipelines", column: "auto_canceled_by_id", name: "fk_262d4c2d19", on_delete: :nullify
add_foreign_key "ci_triggers", "users", column: "owner_id", name: "fk_e8e10d1964", on_delete: :cascade
add_foreign_key "issue_metrics", "issues", on_delete: :cascade
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 8aa8e3fc1cd..5f3a83d5792 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -91,10 +91,12 @@ pipelines:
- trigger_requests
- auto_canceled_by
- auto_canceled_pipelines
+- auto_canceled_jobs
statuses:
- project
- pipeline
- user
+- auto_canceled_by
variables:
- project
triggers:
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index 15b8fa07040..50154a67908 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -224,6 +224,7 @@ CommitStatus:
- token
- lock_version
- coverage_regex
+- auto_canceled_by_id
Ci::Variable:
- id
- project_id
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 38d3be926aa..3595601a72d 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -136,6 +136,43 @@ describe Ci::Pipeline, models: true do
end
end
+ describe '#auto_canceled?' do
+ subject { pipeline.auto_canceled? }
+
+ context 'when it is canceled' do
+ before do
+ pipeline.cancel
+ end
+
+ context 'when there is auto_canceled_by' do
+ before do
+ pipeline.update(auto_canceled_by: create(:ci_empty_pipeline))
+ end
+
+ it 'is auto canceled' do
+ is_expected.to be_truthy
+ end
+ end
+
+ context 'when there is no auto_canceled_by' do
+ it 'is not auto canceled' do
+ is_expected.to be_falsey
+ end
+ end
+
+ context 'when it is retried and canceled manually' do
+ before do
+ pipeline.enqueue
+ pipeline.cancel
+ end
+
+ it 'is not auto canceled' do
+ is_expected.to be_falsey
+ end
+ end
+ end
+ end
+
describe 'pipeline stages' do
before do
create(:commit_status, pipeline: pipeline,
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index 7343b735a74..3bffb8dba72 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -101,6 +101,32 @@ describe CommitStatus, :models do
end
end
+ describe '#auto_canceled?' do
+ subject { commit_status.auto_canceled? }
+
+ context 'when it is canceled' do
+ before do
+ commit_status.cancel
+ end
+
+ context 'when there is auto_canceled_by' do
+ before do
+ commit_status.update(auto_cancel_by: create(:ci_empty_pipeline))
+ end
+
+ it 'is auto canceled' do
+ is_expected.to be_truthy
+ end
+ end
+
+ context 'when there is no auto_canceled_by' do
+ it 'is not auto canceled' do
+ is_expected.to be_falsey
+ end
+ end
+ end
+ end
+
describe '#duration' do
subject { commit_status.duration }
diff --git a/spec/presenters/ci/build_presenter_spec.rb b/spec/presenters/ci/build_presenter_spec.rb
index a9a8df1550d..ebb599bb48c 100644
--- a/spec/presenters/ci/build_presenter_spec.rb
+++ b/spec/presenters/ci/build_presenter_spec.rb
@@ -58,33 +58,27 @@ describe Ci::BuildPresenter do
end
describe '#status_title' do
- context 'when build is canceled' do
+ context 'when build is auto-canceled' do
before do
- expect(presenter).to receive(:canceled?).and_return(true)
+ expect(build).to receive(:auto_canceled?).and_return(true)
+ expect(build).to receive(:auto_canceled_by_id).and_return(1)
end
- context 'when pipeline is auto-canceled' do
- before do
- expect(pipeline).to receive(:auto_canceled?).and_return(true)
- expect(pipeline).to receive(:auto_canceled_by_id).and_return(1)
- end
+ it 'shows that the job is auto-canceled' do
+ status_title = presenter.status_title
- it 'shows that the job is auto-canceled' do
- status_title = presenter.status_title
-
- expect(status_title).to include('auto-canceled')
- expect(status_title).to include('Pipeline #1')
- end
+ expect(status_title).to include('auto-canceled')
+ expect(status_title).to include('Pipeline #1')
end
+ end
- context 'when pipeline is not auto-canceled' do
- before do
- expect(pipeline).to receive(:auto_canceled?).and_return(false)
- end
+ context 'when build is not auto-canceled' do
+ before do
+ expect(build).to receive(:auto_canceled?).and_return(false)
+ end
- it 'shows that the job is auto-canceled' do
- expect(presenter.status_title).to be_nil
- end
+ it 'does not have a status title' do
+ expect(presenter.status_title).to be_nil
end
end
end
diff --git a/spec/presenters/ci/pipeline_presenter_spec.rb b/spec/presenters/ci/pipeline_presenter_spec.rb
index 449e45c1f4c..9134d1cc31c 100644
--- a/spec/presenters/ci/pipeline_presenter_spec.rb
+++ b/spec/presenters/ci/pipeline_presenter_spec.rb
@@ -46,7 +46,7 @@ describe Ci::PipelinePresenter do
expect(pipeline).to receive(:auto_canceled?).and_return(false)
end
- it 'shows that the job is auto-canceled' do
+ it 'does not have a status title' do
expect(presenter.status_title).to be_nil
end
end