diff options
author | Mayra Cabrera <mcabrera@gitlab.com> | 2019-04-26 14:17:26 -0500 |
---|---|---|
committer | Mayra Cabrera <mcabrera@gitlab.com> | 2019-04-30 11:45:18 -0500 |
commit | 98c4f3ac2dd728892bba57e668c83e4b9f16a276 (patch) | |
tree | bf86c9ad5b97e20a9fae977c4c3a7d80a865b3af | |
parent | 6469d4cc8d8e6ddae4183855d41fe4dffc13d143 (diff) | |
download | gitlab-ce-28741-play-all-manual-jobs.tar.gz |
Addresses backend comments28741-play-all-manual-jobs
- Creates a stages_controller with a play_manual action
- Renames blocked_or_skipped to playable
- Make new service re-use the Ci::Build#play method.
- Rename playable? to manual_playable? so the action is more descriptive
- Log an error in case the user does not have access to one of the
instances
27 files changed, 272 insertions, 273 deletions
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue index 62b81d8d937..ba0dea626dc 100644 --- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue +++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue @@ -24,7 +24,7 @@ export default { :groups="stage.groups" :stage-connector-class="stageConnectorClass(index, stage)" :is-first-column="isFirstColumn(index)" - :action="stage.play_manual_details" + :action="stage.status.action" @refreshPipelineGraph="refreshPipelineGraph" /> </ul> diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 64b440ba23b..22c4b8eef1f 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -6,7 +6,7 @@ class Projects::PipelinesController < Projects::ApplicationController before_action :authorize_read_pipeline! before_action :authorize_read_build!, only: [:index] before_action :authorize_create_pipeline!, only: [:new, :create] - before_action :authorize_update_pipeline!, only: [:retry, :cancel, :play_all_manual] + before_action :authorize_update_pipeline!, only: [:retry, :cancel] around_action :allow_gitaly_ref_name_caching, only: [:index, :show] @@ -147,19 +147,6 @@ class Projects::PipelinesController < Projects::ApplicationController @counts[:failed] = @project.all_pipelines.failed.count(:all) end - def play_all_manual - return not_found unless pipeline_stage - - options = { pipeline: pipeline, stage: pipeline_stage } - - ::Ci::PlayStageManualBuildsService.new(@project, current_user, options) - .execute - - render json: StageSerializer - .new(project: @project, current_user: @current_user) - .represent(pipeline_stage, play_all: false) - end - private def serialize_pipelines @@ -209,8 +196,4 @@ class Projects::PipelinesController < Projects::ApplicationController view_context.limited_counter_with_delimiter(finder.execute) end - - def pipeline_stage - @pipeline_stage ||= pipeline.find_stage_by_name(params[:stage]) - end end diff --git a/app/controllers/projects/stages_controller.rb b/app/controllers/projects/stages_controller.rb new file mode 100644 index 00000000000..c8db5b1277f --- /dev/null +++ b/app/controllers/projects/stages_controller.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +class Projects::StagesController < Projects::PipelinesController + before_action :authorize_update_pipeline! + + def play_manual + ::Ci::PlayManualStageService + .new(@project, current_user, pipeline: pipeline) + .execute(stage) + + respond_to do |format| + format.json do + render json: StageSerializer + .new(project: @project, current_user: @current_user) + .represent(stage) + end + end + end + + private + + def stage + @pipeline_stage ||= pipeline.find_stage_by_name!(params[:stage_name]) + end +end diff --git a/app/models/ci/legacy_stage.rb b/app/models/ci/legacy_stage.rb index a15875773ba..930c8a71453 100644 --- a/app/models/ci/legacy_stage.rb +++ b/app/models/ci/legacy_stage.rb @@ -59,7 +59,7 @@ module Ci end end - def blocked_or_skipped? + def manual_playable? %[manual scheduled skipped].include?(status.to_s) end end diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 20c0088fd10..80401ca0a1e 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -771,8 +771,8 @@ module Ci Gitlab::Utils.slugify(source_ref.to_s) end - def find_stage_by_name(name) - stages.find_by(name: name) + def find_stage_by_name!(name) + stages.find_by!(name: name) end private diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb index b25b0369666..d90339d90dc 100644 --- a/app/models/ci/stage.rb +++ b/app/models/ci/stage.rb @@ -120,5 +120,9 @@ module Ci .new(self, current_user) .fabricate! end + + def manual_playable? + blocked? || skipped? + end end end diff --git a/app/models/concerns/has_status.rb b/app/models/concerns/has_status.rb index 921d3cbef19..8882f48c281 100644 --- a/app/models/concerns/has_status.rb +++ b/app/models/concerns/has_status.rb @@ -122,10 +122,6 @@ module HasStatus BLOCKED_STATUS.include?(status) end - def blocked_or_skipped? - blocked? || status == 'skipped' - end - private def calculate_duration diff --git a/app/serializers/stage_entity.rb b/app/serializers/stage_entity.rb index 07b0fd46567..029dd3d0684 100644 --- a/app/serializers/stage_entity.rb +++ b/app/serializers/stage_entity.rb @@ -42,20 +42,14 @@ class StageEntity < Grape::Entity format: :json) end - expose :play_manual_details, - if: -> (status, opts) { show_play_manual_details?(opts) }, - with: Stages::PlayManualEntity - private alias_method :stage, :object def detailed_status - @detailed_status ||= stage.detailed_status(request.current_user) + stage.detailed_status(request.current_user) end - alias_method :play_manual_details, :detailed_status - def grouped_statuses @grouped_statuses ||= stage.statuses.latest_ordered.group_by(&:status) end @@ -75,8 +69,4 @@ class StageEntity < Grape::Entity grouped_retried_statuses.fetch(ordered_status, []) end.flatten end - - def show_play_manual_details?(opts) - opts.fetch(:play_all, true) && detailed_status.has_manual_builds? - end end diff --git a/app/serializers/stages/play_manual_entity.rb b/app/serializers/stages/play_manual_entity.rb deleted file mode 100644 index 618b38c9743..00000000000 --- a/app/serializers/stages/play_manual_entity.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -class Stages::PlayManualEntity < Grape::Entity - expose :action_icon, as: :icon - expose :action_button_title, as: :button_title - expose :action_title, as: :title - expose :action_path, as: :path - expose :action_method, as: :method -end diff --git a/app/services/ci/play_manual_stage_service.rb b/app/services/ci/play_manual_stage_service.rb new file mode 100644 index 00000000000..2497fc52e6b --- /dev/null +++ b/app/services/ci/play_manual_stage_service.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module Ci + class PlayManualStageService < BaseService + def initialize(project, current_user, params) + super + + @pipeline = params[:pipeline] + end + + def execute(stage) + stage.builds.manual.each do |build| + next unless build.playable? + + build.play(current_user) + rescue Gitlab::Access::AccessDeniedError + logger.error(message: 'Unable to play manual action', build_id: build.id) + end + end + + private + + attr_reader :pipeline, :current_user + + def logger + Gitlab::AppLogger + end + end +end diff --git a/app/services/ci/play_stage_manual_builds_service.rb b/app/services/ci/play_stage_manual_builds_service.rb deleted file mode 100644 index 2512c5310ef..00000000000 --- a/app/services/ci/play_stage_manual_builds_service.rb +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -module Ci - class PlayStageManualBuildsService < BaseService - def initialize(project, current_user, params) - super - - @pipeline = params[:pipeline] - @stage = params[:stage] - end - - def execute - raise Gitlab::Access::AccessDeniedError unless can?(current_user, :update_pipeline, pipeline) - - manual_builds.map(&:enqueue) - manual_builds.update_all(user_id: current_user.id, updated_at: Time.now) - end - - private - - attr_reader :pipeline, :stage - - def manual_builds - @manual_builds ||= stage.builds.manual - end - end -end diff --git a/config/routes/project.rb b/config/routes/project.rb index 892bacc6af2..93d746f3282 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -200,7 +200,12 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do get :builds get :failures get :status - post :play_all_manual, path: 'stages/:stage/play_all_manual' + end + + member do + resources :stages, only: [], param: :name do + post :play_manual + end end end diff --git a/lib/gitlab/ci/status/stage/common.rb b/lib/gitlab/ci/status/stage/common.rb index f2fe6a94acb..f12daaa9676 100644 --- a/lib/gitlab/ci/status/stage/common.rb +++ b/lib/gitlab/ci/status/stage/common.rb @@ -18,10 +18,6 @@ module Gitlab def has_action? false end - - def has_manual_builds? - false - end end end end diff --git a/lib/gitlab/ci/status/stage/play_manual.rb b/lib/gitlab/ci/status/stage/play_manual.rb index 554b650b0aa..ac3fc0912fa 100644 --- a/lib/gitlab/ci/status/stage/play_manual.rb +++ b/lib/gitlab/ci/status/stage/play_manual.rb @@ -11,10 +11,6 @@ module Gitlab 'play' end - def action_button_title - _('Play all manual') - end - def action_title 'Play all manual' end @@ -22,18 +18,22 @@ module Gitlab def action_path pipeline = subject.pipeline - play_all_manual_project_pipeline_path(pipeline.project, pipeline, subject.name) + project_stage_play_manual_path(pipeline.project, pipeline, subject.name) end def action_method :post end + def action_button_title + _('Play all manual') + end + def self.matches?(stage, user) - stage.blocked_or_skipped? + stage.manual_playable? end - def has_manual_builds? + def has_action? true end end diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb index 51a46916f40..9a50ea79f5e 100644 --- a/spec/controllers/projects/pipelines_controller_spec.rb +++ b/spec/controllers/projects/pipelines_controller_spec.rb @@ -393,50 +393,4 @@ describe Projects::PipelinesController do end end end - - describe 'POST #play_all_manual.json' do - let(:pipeline) { create(:ci_pipeline, project: project) } - let(:stage_name) { 'test' } - - before do - create_manual_build(pipeline, 'test', 'rspec 1/3') - create_manual_build(pipeline, 'test', 'rspec 2/3') - create_manual_build(pipeline, 'test', 'rspec 3/3') - - pipeline.reload - end - - context 'when the stage does not exists' do - let(:stage_name) { 'deploy' } - - it 'fails to play all manual' do - play_all_manual! - - expect(response).to have_gitlab_http_status(:not_found) - end - end - - context 'when the stage exists' do - it 'starts all manual jobs' do - expect(pipeline.builds.manual.count).to eq(3) - play_all_manual! - - expect(response).to have_gitlab_http_status(:ok) - expect(pipeline.builds.manual.count).to eq(0) - end - end - - def play_all_manual! - post :play_all_manual, params: { - namespace_id: project.namespace, - project_id: project, - id: pipeline.id, - stage: stage_name - }, format: :json - end - - def create_manual_build(pipeline, stage, name) - create(:ci_build, :manual, pipeline: pipeline, stage: stage, name: name) - end - end end diff --git a/spec/controllers/projects/stages_controller_spec.rb b/spec/controllers/projects/stages_controller_spec.rb new file mode 100644 index 00000000000..a91e3523fd7 --- /dev/null +++ b/spec/controllers/projects/stages_controller_spec.rb @@ -0,0 +1,72 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Projects::StagesController do + let(:user) { create(:user) } + let(:project) { create(:project, :repository) } + + before do + sign_in(user) + end + + describe 'POST #play_manual.json' do + let(:pipeline) { create(:ci_pipeline, project: project) } + let(:stage_name) { 'test' } + + before do + create_manual_build(pipeline, 'test', 'rspec 1/2') + create_manual_build(pipeline, 'test', 'rspec 2/2') + + pipeline.reload + end + + context 'when user does not have access' do + it 'returns not authorized' do + play_manual_stage! + + expect(response).to have_gitlab_http_status(404) + end + end + + context 'when user has access' do + before do + project.add_maintainer(user) + end + + context 'when the stage does not exists' do + let(:stage_name) { 'deploy' } + + it 'fails to play all manual' do + play_manual_stage! + + expect(response).to have_gitlab_http_status(:not_found) + end + end + + context 'when the stage exists' do + it 'starts all manual jobs' do + expect(pipeline.builds.manual.count).to eq(2) + + play_manual_stage! + + expect(response).to have_gitlab_http_status(:ok) + expect(pipeline.builds.manual.count).to eq(0) + end + end + end + + def play_manual_stage! + post :play_manual, params: { + namespace_id: project.namespace, + project_id: project, + id: pipeline.id, + stage_name: stage_name + }, format: :json + end + + def create_manual_build(pipeline, stage, name) + create(:ci_build, :manual, pipeline: pipeline, stage: stage, name: name) + end + end +end diff --git a/spec/lib/gitlab/ci/status/stage/play_manual_spec.rb b/spec/lib/gitlab/ci/status/stage/play_manual_spec.rb index a357881103d..b0113b00ef0 100644 --- a/spec/lib/gitlab/ci/status/stage/play_manual_spec.rb +++ b/spec/lib/gitlab/ci/status/stage/play_manual_spec.rb @@ -31,7 +31,7 @@ describe Gitlab::Ci::Status::Stage::PlayManual do subject { play_manual.action_path } - it { is_expected.to eq("/#{pipeline.project.full_path}/pipelines/#{pipeline.id}/stages/#{stage.name}/play_all_manual") } + it { is_expected.to eq("/#{pipeline.project.full_path}/pipelines/#{pipeline.id}/stages/#{stage.name}/play_manual") } end describe '#action_method' do @@ -71,10 +71,4 @@ describe Gitlab::Ci::Status::Stage::PlayManual do end end end - - describe '#has_manual_builds?' do - subject { play_manual.has_manual_builds? } - - it { is_expected.to be_truthy } - end end diff --git a/spec/models/ci/legacy_stage_spec.rb b/spec/models/ci/legacy_stage_spec.rb index be0307518eb..bb812cc0533 100644 --- a/spec/models/ci/legacy_stage_spec.rb +++ b/spec/models/ci/legacy_stage_spec.rb @@ -272,4 +272,6 @@ describe Ci::LegacyStage do def create_job(type, status: 'success', stage: stage_name, **opts) create(type, pipeline: pipeline, stage: stage, status: status, **opts) end + + it_behaves_like 'manual playable stage', :ci_stage end diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 7a353ebd92b..af455a72f50 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -2958,7 +2958,7 @@ describe Ci::Pipeline, :mailer do create_list(:ci_build, 2, pipeline: pipeline, stage: stage.name) end - subject { pipeline.find_stage_by_name(stage_name) } + subject { pipeline.find_stage_by_name!(stage_name) } context 'when stage exists' do it { is_expected.to eq(stage) } @@ -2967,7 +2967,11 @@ describe Ci::Pipeline, :mailer do context 'when stage does not exist' do let(:stage_name) { 'build' } - it { is_expected.to be_nil } + it 'raises an ActiveRecord exception' do + expect do + subject + end.to raise_exception(ActiveRecord::RecordNotFound) + end end end end diff --git a/spec/models/ci/stage_spec.rb b/spec/models/ci/stage_spec.rb index 661958390e2..85cd32fb03a 100644 --- a/spec/models/ci/stage_spec.rb +++ b/spec/models/ci/stage_spec.rb @@ -285,4 +285,6 @@ describe Ci::Stage, :models do end end end + + it_behaves_like 'manual playable stage', :ci_stage_entity end diff --git a/spec/models/concerns/has_status_spec.rb b/spec/models/concerns/has_status_spec.rb index 05480ad0285..a217dc42537 100644 --- a/spec/models/concerns/has_status_spec.rb +++ b/spec/models/concerns/has_status_spec.rb @@ -367,28 +367,4 @@ describe HasStatus do puts subject end end - - describe '#blocked_or_skipped?' do - %w[ci_pipeline ci_stage ci_build generic_commit_status].each do |type| - let(:object) { build(type, status: status) } - - context 'when status is scheduled' do - let(:status) { :scheduled } - - it { is_expected.to be_truthy } - end - - context 'when status is manual' do - let(:status) { :manual } - - it { is_expected.to be_truthy } - end - - context 'when status is skipped' do - let(:status) { :skipped } - - it { is_expected.to be_truthy } - end - end - end end diff --git a/spec/serializers/pipeline_serializer_spec.rb b/spec/serializers/pipeline_serializer_spec.rb index 88f18209dce..54e6abc2d3a 100644 --- a/spec/serializers/pipeline_serializer_spec.rb +++ b/spec/serializers/pipeline_serializer_spec.rb @@ -157,6 +157,7 @@ describe PipelineSerializer do it 'verifies number of queries', :request_store do recorded = ActiveRecord::QueryRecorder.new { subject } expected_queries = Gitlab.ee? ? 38 : 31 + expect(recorded.count).to be_within(2).of(expected_queries) expect(recorded.cached_count).to eq(0) end diff --git a/spec/serializers/stage_entity_spec.rb b/spec/serializers/stage_entity_spec.rb index 114a1593d72..6b1185d1283 100644 --- a/spec/serializers/stage_entity_spec.rb +++ b/spec/serializers/stage_entity_spec.rb @@ -48,8 +48,8 @@ describe StageEntity do expect(subject[:title]).to eq 'test: passed' end - it 'does not contain play_manual_details info' do - expect(subject[:play_manual_details]).not_to be_present + it 'does not contain play_details info' do + expect(subject[:status][:action]).not_to be_present end context 'when the jobs should be grouped' do @@ -75,7 +75,7 @@ describe StageEntity do let(:stage) { create(:ci_stage_entity, status: 'skipped') } it 'contains play_all_manual' do - expect(subject[:play_manual_details]).to be_present + expect(subject[:status][:action]).to be_present end end @@ -83,7 +83,7 @@ describe StageEntity do let(:stage) { create(:ci_stage_entity, status: 'scheduled') } it 'contains play_all_manual' do - expect(subject[:play_manual_details]).to be_present + expect(subject[:status][:action]).to be_present end end @@ -91,7 +91,7 @@ describe StageEntity do let(:stage) { create(:ci_stage_entity, status: 'manual') } it 'contains play_all_manual' do - expect(subject[:play_manual_details]).to be_present + expect(subject[:status][:action]).to be_present end end end diff --git a/spec/serializers/stage_serializer_spec.rb b/spec/serializers/stage_serializer_spec.rb index 94d72910b32..aae17cfbcb9 100644 --- a/spec/serializers/stage_serializer_spec.rb +++ b/spec/serializers/stage_serializer_spec.rb @@ -27,32 +27,5 @@ describe StageSerializer do expect(subject).not_to be_empty end end - - context 'with manual builds' do - let(:resource) { create(:ci_stage_entity, status: 'manual') } - - subject { serializer.represent(resource, { play_all: play_all }) } - - before do - create_list(:ci_build, 3, :manual, - stage: resource.name, stage_id: resource.id) - end - - context 'with play all option' do - let(:play_all) { true } - - it 'returns play manual details' do - expect(subject[:play_manual_details]).to be_present - end - end - - context 'without play all option' do - let(:play_all) { false } - - it 'does not return play manual details' do - expect(subject[:play_manual_details]).not_to be_present - end - end - end end end diff --git a/spec/services/ci/play_manual_stage_service_spec.rb b/spec/services/ci/play_manual_stage_service_spec.rb new file mode 100644 index 00000000000..5d812745c7f --- /dev/null +++ b/spec/services/ci/play_manual_stage_service_spec.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Ci::PlayManualStageService, '#execute' do + let(:current_user) { create(:user) } + let(:pipeline) { create(:ci_pipeline, user: current_user) } + let(:project) { pipeline.project } + let(:service) { described_class.new(project, current_user, pipeline: pipeline) } + let(:stage_status) { 'manual' } + + let(:stage) do + create(:ci_stage_entity, + pipeline: pipeline, + project: project, + name: 'test') + end + + before do + project.add_maintainer(current_user) + create_builds_for_stage(status: stage_status) + end + + context 'when pipeline has manual builds' do + before do + service.execute(stage) + end + + it 'starts manual builds from pipeline' do + expect(pipeline.builds.manual.count).to eq(0) + end + + it 'updates manual builds' do + pipeline.builds.each do |build| + expect(build.user).to eq(current_user) + end + end + end + + context 'when pipeline has no manual builds' do + let(:stage_status) { 'failed' } + + before do + service.execute(stage) + end + + it 'does not update the builds' do + expect(pipeline.builds.failed.count).to eq(3) + end + end + + context 'when user does not have permission on a specific build' do + before do + allow_any_instance_of(Ci::Build).to receive(:play) + .and_raise(Gitlab::Access::AccessDeniedError) + + service.execute(stage) + end + + it 'logs the error' do + expect(Gitlab::AppLogger).to receive(:error) + .exactly(stage.builds.manual.count) + + service.execute(stage) + end + end + + def create_builds_for_stage(options) + options.merge!({ + when: 'manual', + pipeline: pipeline, + stage: stage.name, + stage_id: stage.id, + user: pipeline.user + }) + + create_list(:ci_build, 3, options) + end +end diff --git a/spec/services/ci/play_stage_manual_builds_service_spec.rb b/spec/services/ci/play_stage_manual_builds_service_spec.rb deleted file mode 100644 index 8ffb33d82c7..00000000000 --- a/spec/services/ci/play_stage_manual_builds_service_spec.rb +++ /dev/null @@ -1,77 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -describe Ci::PlayStageManualBuildsService, '#execute' do - let(:current_user) { create(:user) } - let(:pipeline) { create(:ci_pipeline, user: current_user) } - let(:project) { pipeline.project } - - let(:stage) do - create(:ci_stage_entity, - pipeline: pipeline, - project: project, - name: 'test') - end - - let(:options) do - { - pipeline: stage.pipeline, - stage: stage - } - end - - let(:service) do - described_class.new(project, current_user, options) - end - - context 'when user does not have access' do - it 'throws an exception' do - project.add_reporter(current_user) - - expect do - service.execute - end.to raise_error(Gitlab::Access::AccessDeniedError) - end - end - - context 'when user has access' do - before do - project.add_maintainer(current_user) - end - - context 'when pipeline has manual builds' do - before do - create_builds_for_stage('manual') - service.execute - pipeline.reload - end - - it 'starts manual builds from pipeline' do - expect(pipeline.builds.manual.count).to eq(0) - end - - it 'updates manual builds' do - pipeline.builds.each do |build| - expect(build.user).to eq(current_user) - end - end - end - - context 'when pipeline has no manual builds' do - before do - create_builds_for_stage('failed') - service.execute - pipeline.reload - end - - it 'does not update the builds' do - expect(pipeline.builds.failed.count).to eq(3) - end - end - end - - def create_builds_for_stage(status) - create_list(:ci_build, 3, status: status, pipeline: pipeline, stage: stage.name, stage_id: stage.id, user: pipeline.user) - end -end diff --git a/spec/support/shared_examples/ci/stage_shared_examples.rb b/spec/support/shared_examples/ci/stage_shared_examples.rb new file mode 100644 index 00000000000..925974ed11e --- /dev/null +++ b/spec/support/shared_examples/ci/stage_shared_examples.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +shared_examples 'manual playable stage' do |stage_type| + let(:stage) { build(stage_type, status: status) } + + describe '#manual_playable?' do + subject { stage.manual_playable? } + + context 'when is manual' do + let(:status) { 'manual' } + + it { is_expected.to be_truthy } + end + + context 'when is scheduled' do + let(:status) { 'scheduled' } + + it { is_expected.to be_truthy } + end + + context 'when is skipped' do + let(:status) { 'skipped' } + + it { is_expected.to be_truthy } + end + end +end |