Commit d3b7250c authored by Kamil Trzcinski's avatar Kamil Trzcinski

Merge branch 'build-statuses' into 22604-manual-actions

parents fc57b314 c1db5b91
class Ability
module Allowable
def can?(user, action, subject)
Ability.allowed?(user, action, subject)
end
end
class << self
# Given a list of users and a project this method returns the users that can
# read the given project.
......
......@@ -3,10 +3,10 @@ module Gitlab
module Status
module Status
class Cancelable < SimpleDelegator
extend Status::Extended
include Status::Extended
def has_action?(current_user)
can?(current_user, :update_build, subject)
def has_action?
can?(user, :update_build, subject)
end
def action_icon
......@@ -14,14 +14,16 @@ module Gitlab
end
def action_path
cancel_namespace_project_build_path(subject.project.namespace, subject.project, subject)
cancel_namespace_project_build_path(subject.project.namespace,
subject.project,
subject)
end
def action_method
:post
end
def self.matches?(build)
def self.matches?(build, user)
build.cancelable?
end
end
......
......@@ -3,14 +3,14 @@ module Gitlab
module Status
module Build
module Common
def has_details?(current_user)
can?(current_user, :read_build, subject)
def has_details?
can?(user, :read_build, subject)
end
def details_path
namespace_project_build_path(@subject.project.namespace,
@subject.project,
@subject.pipeline)
namespace_project_build_path(subject.project.namespace,
subject.project,
subject.pipeline)
end
end
end
......
......@@ -3,14 +3,13 @@ module Gitlab
module Status
module Build
class Factory < Status::Factory
private
def extended_statuses
[Stop, Play, Cancelable, Retryable]
def self.extended_statuses
[Status::Build::Stop, Status::Build::Play,
Status::Build::Cancelable, Status::Build::Retryable]
end
def core_status
super.extend(Status::Build::Common)
def self.common_helpers
Status::Build::Common
end
end
end
......
......@@ -3,7 +3,7 @@ module Gitlab
module Status
module Status
class Play < SimpleDelegator
extend Status::Extended
include Status::Extended
def text
'play'
......@@ -13,8 +13,8 @@ module Gitlab
'play'
end
def has_action?(current_user)
can?(current_user, :update_build, subject)
def has_action?
can?(user, :update_build, subject)
end
def action_icon
......@@ -22,14 +22,16 @@ module Gitlab
end
def action_path
play_namespace_project_build_path(subject.project.namespace, subject.project, subject)
play_namespace_project_build_path(subject.project.namespace,
subject.project,
subject)
end
def action_method
:post
end
def self.matches?(build)
def self.matches?(build, user)
build.playable? && !build.stops_environment?
end
end
......
......@@ -3,10 +3,10 @@ module Gitlab
module Status
module Status
class Retryable < SimpleDelegator
extend Status::Extended
include Status::Extended
def has_action?(current_user)
can?(current_user, :update_build, subject)
def has_action?
can?(user, :update_build, subject)
end
def action_icon
......@@ -14,14 +14,16 @@ module Gitlab
end
def action_path
retry_namespace_project_build_path(subject.project.namespace, subject.project, subject)
retry_namespace_project_build_path(subject.project.namespace,
subject.project,
subject)
end
def action_method
:post
end
def self.matches?(build)
def self.matches?(build, user)
build.retryable?
end
end
......
......@@ -3,7 +3,7 @@ module Gitlab
module Status
module Status
class Play < SimpleDelegator
extend Status::Extended
include Status::Extended
def text
'stop'
......@@ -21,8 +21,8 @@ module Gitlab
'stop'
end
def has_action?(current_user)
can?(current_user, :update_build, subject)
def has_action?
can?(user, :update_build, subject)
end
def action_icon
......@@ -30,14 +30,16 @@ module Gitlab
end
def action_path
play_namespace_project_build_path(subject.project.namespace, subject.project, subject)
play_namespace_project_build_path(subject.project.namespace,
subject.project,
subject)
end
def action_method
:post
end
def self.matches?(build)
def self.matches?(build, user)
build.playable? && build.stops_environment?
end
end
......
......@@ -5,9 +5,13 @@ module Gitlab
#
class Core
include Gitlab::Routing.url_helpers
include Ability::Allowable
def initialize(subject)
attr_reader :subject, :user
def initialize(subject, user)
@subject = subject
@user = user
end
def icon
......@@ -18,10 +22,6 @@ module Gitlab
raise NotImplementedError
end
def title
"#{@subject.class.name.demodulize}: #{label}"
end
# Deprecation warning: this method is here because we need to maintain
# backwards compatibility with legacy statuses. We often do something
# like "ci-status ci-status-#{status}" to set CSS class.
......@@ -33,7 +33,7 @@ module Gitlab
self.class.name.demodulize.downcase.underscore
end
def has_details?(_user = nil)
def has_details?
false
end
......@@ -41,7 +41,7 @@ module Gitlab
raise NotImplementedError
end
def has_action?(_user = nil)
def has_action?
false
end
......
......@@ -2,10 +2,14 @@ module Gitlab
module Ci
module Status
module Extended
def matches?(_subject)
extend ActiveSupport::Concern
class_methods do
def matches?(_subject, _user)
raise NotImplementedError
end
end
end
end
end
end
......@@ -2,10 +2,9 @@ module Gitlab
module Ci
module Status
class Factory
attr_reader :subject
def initialize(subject)
def initialize(subject, user)
@subject = subject
@user = user
end
def fabricate!
......@@ -16,26 +15,31 @@ module Gitlab
end
end
def self.extended_statuses
[]
end
def self.common_helpers
Module.new
end
private
def subject_status
@subject_status ||= subject.status
def simple_status
@simple_status ||= @subject.status || :created
end
def core_status
Gitlab::Ci::Status
.const_get(subject_status.capitalize)
.new(subject)
.const_get(simple_status.capitalize)
.new(@subject, @user)
.extend(self.class.common_helpers)
end
def extended_status
@extended ||= extended_statuses.find do |status|
status.matches?(subject)
end
@extended ||= self.class.extended_statuses.find do |status|
status.matches?(@subject, @user)
end
def extended_statuses
[]
end
end
end
......
......@@ -3,14 +3,14 @@ module Gitlab
module Status
module Pipeline
module Common
def has_details?(current_user)
can?(current_user, :read_pipeline, subject)
def has_details?
can?(user, :read_pipeline, subject)
end
def details_path
namespace_project_pipeline_path(@subject.project.namespace,
@subject.project,
@subject)
namespace_project_pipeline_path(subject.project.namespace,
subject.project,
subject)
end
def has_action?
......
......@@ -3,14 +3,12 @@ module Gitlab
module Status
module Pipeline
class Factory < Status::Factory
private
def extended_statuses
def self.extended_statuses
[Pipeline::SuccessWithWarnings]
end
def core_status
super.extend(Status::Pipeline::Common)
def self.common_helpers
Status::Pipeline::Common
end
end
end
......
......@@ -3,7 +3,7 @@ module Gitlab
module Status
module Pipeline
class SuccessWithWarnings < SimpleDelegator
extend Status::Extended
include Status::Extended
def text
'passed'
......@@ -21,7 +21,7 @@ module Gitlab
'success_with_warnings'
end
def self.matches?(pipeline)
def self.matches?(pipeline, user)
pipeline.success? && pipeline.has_warnings?
end
end
......
......@@ -3,15 +3,15 @@ module Gitlab
module Status
module Stage
module Common
def has_details?(current_user)
can?(current_user, :read_pipeline, subject)
def has_details?
can?(user, :read_pipeline, subject.pipeline)
end
def details_path
namespace_project_pipeline_path(@subject.project.namespace,
@subject.project,
@subject.pipeline,
anchor: @subject.name)
namespace_project_pipeline_path(subject.project.namespace,
subject.project,
subject.pipeline,
anchor: subject.name)
end
def has_action?
......
......@@ -3,10 +3,8 @@ module Gitlab
module Status
module Stage
class Factory < Status::Factory
private
def core_status
super.extend(Status::Stage::Common)
def self.common_helpers
Status::Stage::Common
end
end
end
......
require 'spec_helper'
describe Gitlab::Ci::Status::Canceled do
subject { described_class.new(double('subject')) }
subject do
described_class.new(double('subject'), double('user'))
end
describe '#text' do
it { expect(subject.label).to eq 'canceled' }
......@@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Canceled do
describe '#icon' do
it { expect(subject.icon).to eq 'icon_status_canceled' }
end
describe '#title' do
it { expect(subject.title).to eq 'Double: canceled' }
end
end
require 'spec_helper'
describe Gitlab::Ci::Status::Created do
subject { described_class.new(double('subject')) }
subject do
described_class.new(double('subject'), double('user'))
end
describe '#text' do
it { expect(subject.label).to eq 'created' }
......@@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Created do
describe '#icon' do
it { expect(subject.icon).to eq 'icon_status_created' }
end
describe '#title' do
it { expect(subject.title).to eq 'Double: created' }
end
end
......@@ -2,11 +2,11 @@ require 'spec_helper'
describe Gitlab::Ci::Status::Extended do
subject do
Class.new.extend(described_class)
Class.new.include(described_class)
end
it 'requires subclass to implement matcher' do
expect { subject.matches?(double) }
expect { subject.matches?(double, double) }
.to raise_error(NotImplementedError)
end
end
......@@ -2,15 +2,17 @@ require 'spec_helper'
describe Gitlab::Ci::Status::Factory do
subject do
described_class.new(object)
described_class.new(resource, user)
end
let(:user) { create(:user) }
let(:status) { subject.fabricate! }
context 'when object has a core status' do
HasStatus::AVAILABLE_STATUSES.each do |core_status|
context "when core status is #{core_status}" do
let(:object) { double(status: core_status) }
let(:resource) { double(status: core_status) }
it "fabricates a core status #{core_status}" do
expect(status).to be_a(
......
require 'spec_helper'
describe Gitlab::Ci::Status::Failed do
subject { described_class.new(double('subject')) }
subject do
described_class.new(double('subject'), double('user'))
end
describe '#text' do
it { expect(subject.label).to eq 'failed' }
......@@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Failed do
describe '#icon' do
it { expect(subject.icon).to eq 'icon_status_failed' }
end
describe '#title' do
it { expect(subject.title).to eq 'Double: failed' }
end
end
require 'spec_helper'
describe Gitlab::Ci::Status::Pending do
subject { described_class.new(double('subject')) }
subject do
described_class.new(double('subject'), double('user'))
end
describe '#text' do
it { expect(subject.label).to eq 'pending' }
......@@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Pending do
describe '#icon' do
it { expect(subject.icon).to eq 'icon_status_pending' }
end
describe '#title' do
it { expect(subject.title).to eq 'Double: pending' }
end
end
require 'spec_helper'
describe Gitlab::Ci::Status::Pipeline::Common do
let(:pipeline) { create(:ci_pipeline) }
let(:user) { create(:user) }
let(:project) { create(:empty_project) }
let(:pipeline) { create(:ci_pipeline, project: project) }
subject do
Class.new(Gitlab::Ci::Status::Core)
.new(pipeline).extend(described_class)
.new(pipeline, user)
.extend(described_class)
end
before do
project.team << [user, :developer]
end
it 'does not have action' do
......
require 'spec_helper'
describe Gitlab::Ci::Status::Pipeline::Factory do
let(:user) { create(:user) }
let(:project) { pipeline.project }
subject do
described_class.new(pipeline)
described_class.new(pipeline, user)
end
let(:status) do
subject.fabricate!
end
before do
project.team << [user, :developer]
end
context 'when pipeline has a core status' do
HasStatus::AVAILABLE_STATUSES.each do |core_status|
context "when core status is #{core_status}" do
......
......@@ -29,13 +29,13 @@ describe Gitlab::Ci::Status::Pipeline::SuccessWithWarnings do
end
it 'is a correct match' do
expect(described_class.matches?(pipeline)).to eq true
expect(described_class.matches?(pipeline, double)).to eq true
end
end
context 'when pipeline does not have warnings' do
it 'does not match' do
expect(described_class.matches?(pipeline)).to eq false
expect(described_class.matches?(pipeline, double)).to eq false
end
end
end
......@@ -51,13 +51,13 @@ describe Gitlab::Ci::Status::Pipeline::SuccessWithWarnings do
end
it 'does not match' do
expect(described_class.matches?(pipeline)).to eq false
expect(described_class.matches?(pipeline, double)).to eq false
end
end
context 'when pipeline does not have warnings' do
it 'does not match' do
expect(described_class.matches?(pipeline)).to eq false
expect(described_class.matches?(pipeline, double)).to eq false
end
end
end
......
require 'spec_helper'
describe Gitlab::Ci::Status::Running do
subject { described_class.new(double('subject')) }
subject do
described_class.new(double('subject'), double('user'))
end
describe '#text' do
it { expect(subject.label).to eq 'running' }
......@@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Running do
describe '#icon' do
it { expect(subject.icon).to eq 'icon_status_running' }
end
describe '#title' do
it { expect(subject.title).to eq 'Double: running' }
end
end
require 'spec_helper'
describe Gitlab::Ci::Status::Skipped do
subject { described_class.new(double('subject')) }
subject do
described_class.new(double('subject'), double('user'))
end
describe '#text' do
it { expect(subject.label).to eq 'skipped' }
......@@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Skipped do
describe '#icon' do
it { expect(subject.icon).to eq 'icon_status_skipped' }
end
describe '#title' do
it { expect(subject.title).to eq 'Double: skipped' }
end
end
require 'spec_helper'
describe Gitlab::Ci::Status::Stage::Common do
let(:pipeline) { create(:ci_empty_pipeline) }
let(:stage) { build(:ci_stage, pipeline: pipeline, name: 'test') }
let(:user) { create(:user) }
let(:project) { create(:empty_project) }
let(:pipeline) { create(:ci_empty_pipeline, project: project) }
let(:stage) do
build(:ci_stage, pipeline: pipeline, name: 'test')
end
subject do
Class.new(Gitlab::Ci::Status::Core)
.new(stage).extend(described_class)
.new(stage, user).extend(described_class)
end
it 'does not have action' do
expect(subject).not_to have_action
end
it 'has details' do
expect(subject).to have_details
end
it 'links to the pipeline details page' do
expect(subject.details_path)
.to include "pipelines/#{pipeline.id}"
expect(subject.details_path)
.to include "##{stage.name}"
end
context 'when user has permission to read pipeline' do
before do
project.team << [user, :master]
end
it 'has details' do
expect(subject).to have_details
end
end
context 'when user does not have permission to read pipeline' do
it 'does not have details' do
expect(subject).not_to have_details
end
end
end
require 'spec_helper'
describe Gitlab::Ci::Status::Stage::Factory do
let(:pipeline) { create(:ci_empty_pipeline) }
let(:stage) { build(:ci_stage, pipeline: pipeline, name: 'test') }
let(:user) { create(:user) }
let(:project) { create(:empty_project) }
let(:pipeline) { create(:ci_empty_pipeline, project: project) }
let(:stage) do
build(:ci_stage, pipeline: pipeline, name: 'test')
end
subject do
described_class.new(stage)
described_class.new(stage, user)
end
let(:status) do
subject.fabricate!
end
before do
project.team << [user, :developer]
end
context 'when stage has a core status' do
HasStatus::AVAILABLE_STATUSES.each do |core_status|
context "when core status is #{core_status}" do
......
require 'spec_helper'
describe Gitlab::Ci::Status::Success do
subject { described_class.new(double('subject')) }
subject do
described_class.new(double('subject'), double('user'))
end
describe '#text' do
it { expect(subject.label).to eq 'passed' }
......@@ -14,8 +16,4 @@ describe Gitlab::Ci::Status::Success do
describe '#icon' do
it { expect(subject.icon).to eq 'icon_status_success' }
end
describe '#title' do
it { expect(subject.title).to eq 'Double: passed' }
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