Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce into bitbucket-oauth2
This commit is contained in:
commit
076cdd2044
85 changed files with 1347 additions and 212 deletions
|
@ -232,6 +232,7 @@
|
|||
&:hover:not(.active) {
|
||||
background-color: $gray-lightest;
|
||||
box-shadow: inset 2px 0 0 0 $border-color;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
|
|
|
@ -4,25 +4,7 @@ module CiStatusHelper
|
|||
builds_namespace_project_commit_path(project.namespace, project, pipeline.sha)
|
||||
end
|
||||
|
||||
def ci_status_with_icon(status, target = nil)
|
||||
content = ci_icon_for_status(status) + ci_text_for_status(status)
|
||||
klass = "ci-status ci-#{status}"
|
||||
|
||||
if target
|
||||
link_to content, target, class: klass
|
||||
else
|
||||
content_tag :span, content, class: klass
|
||||
end
|
||||
end
|
||||
|
||||
def ci_text_for_status(status)
|
||||
if detailed_status?(status)
|
||||
status.text
|
||||
else
|
||||
status
|
||||
end
|
||||
end
|
||||
|
||||
# Is used by Commit and Merge Request Widget
|
||||
def ci_label_for_status(status)
|
||||
if detailed_status?(status)
|
||||
return status.label
|
||||
|
|
|
@ -100,6 +100,12 @@ module Ci
|
|||
end
|
||||
end
|
||||
|
||||
def detailed_status(current_user)
|
||||
Gitlab::Ci::Status::Build::Factory
|
||||
.new(self, current_user)
|
||||
.fabricate!
|
||||
end
|
||||
|
||||
def manual?
|
||||
self.when == 'manual'
|
||||
end
|
||||
|
@ -123,8 +129,13 @@ module Ci
|
|||
end
|
||||
end
|
||||
|
||||
def cancelable?
|
||||
active?
|
||||
end
|
||||
|
||||
def retryable?
|
||||
project.builds_enabled? && commands.present? && complete?
|
||||
project.builds_enabled? && commands.present? &&
|
||||
(success? || failed? || canceled?)
|
||||
end
|
||||
|
||||
def retried?
|
||||
|
@ -148,7 +159,7 @@ module Ci
|
|||
end
|
||||
|
||||
def environment_action
|
||||
self.options.fetch(:environment, {}).fetch(:action, 'start')
|
||||
self.options.fetch(:environment, {}).fetch(:action, 'start') if self.options
|
||||
end
|
||||
|
||||
def outdated_deployment?
|
||||
|
|
|
@ -336,8 +336,10 @@ module Ci
|
|||
.select { |merge_request| merge_request.head_pipeline.try(:id) == self.id }
|
||||
end
|
||||
|
||||
def detailed_status
|
||||
Gitlab::Ci::Status::Pipeline::Factory.new(self).fabricate!
|
||||
def detailed_status(current_user)
|
||||
Gitlab::Ci::Status::Pipeline::Factory
|
||||
.new(self, current_user)
|
||||
.fabricate!
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
@ -22,8 +22,10 @@ module Ci
|
|||
@status ||= statuses.latest.status
|
||||
end
|
||||
|
||||
def detailed_status
|
||||
Gitlab::Ci::Status::Stage::Factory.new(self).fabricate!
|
||||
def detailed_status(current_user)
|
||||
Gitlab::Ci::Status::Stage::Factory
|
||||
.new(self, current_user)
|
||||
.fabricate!
|
||||
end
|
||||
|
||||
def statuses
|
||||
|
|
|
@ -131,4 +131,10 @@ class CommitStatus < ActiveRecord::Base
|
|||
def has_trace?
|
||||
false
|
||||
end
|
||||
|
||||
def detailed_status(current_user)
|
||||
Gitlab::Ci::Status::Factory
|
||||
.new(self, current_user)
|
||||
.fabricate!
|
||||
end
|
||||
end
|
||||
|
|
|
@ -17,14 +17,13 @@ class Namespace < ActiveRecord::Base
|
|||
validates :owner, presence: true, unless: ->(n) { n.type == "Group" }
|
||||
validates :name,
|
||||
presence: true,
|
||||
uniqueness: true,
|
||||
uniqueness: { scope: :parent_id },
|
||||
length: { maximum: 255 },
|
||||
namespace_name: true
|
||||
|
||||
validates :description, length: { maximum: 255 }
|
||||
validates :path,
|
||||
presence: true,
|
||||
uniqueness: { case_sensitive: false },
|
||||
length: { maximum: 255 },
|
||||
namespace: true
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
%span
|
||||
Overview
|
||||
= nav_link(controller: [:admin, :projects]) do
|
||||
= link_to admin_namespaces_projects_path, title: 'Projects' do
|
||||
= link_to admin_projects_path, title: 'Projects' do
|
||||
%span
|
||||
Projects
|
||||
= nav_link(controller: :users) do
|
||||
|
|
|
@ -116,7 +116,7 @@
|
|||
.light-well.well-centered
|
||||
%h4 Projects
|
||||
.data
|
||||
= link_to admin_namespaces_projects_path do
|
||||
= link_to admin_projects_path do
|
||||
%h1= number_with_delimiter(Project.cached_count)
|
||||
%hr
|
||||
= link_to('New Project', new_project_path, class: "btn btn-new")
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
%li.group-row{ class: css_class }
|
||||
.controls
|
||||
= link_to 'Edit', edit_admin_group_path(group), id: "edit_#{dom_id(group)}", class: 'btn'
|
||||
= link_to 'Edit', admin_group_edit_path(group), id: "edit_#{dom_id(group)}", class: 'btn'
|
||||
= link_to 'Delete', [:admin, group], data: { confirm: "Are you sure you want to remove #{group.name}?" }, method: :delete, class: 'btn btn-remove'
|
||||
.stats
|
||||
%span
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
%h3.page-title
|
||||
Group: #{@group.name}
|
||||
|
||||
= link_to edit_admin_group_path(@group), class: "btn pull-right" do
|
||||
= link_to admin_group_edit_path(@group), class: "btn pull-right" do
|
||||
%i.fa.fa-pencil-square-o
|
||||
Edit
|
||||
%hr
|
||||
|
@ -88,7 +88,7 @@
|
|||
Read more about project permissions
|
||||
%strong= link_to "here", help_page_path("user/permissions"), class: "vlink"
|
||||
|
||||
= form_tag members_update_admin_group_path(@group), id: "new_project_member", class: "bulk_import", method: :put do
|
||||
= form_tag admin_group_members_update_path(@group), id: "new_project_member", class: "bulk_import", method: :put do
|
||||
%div
|
||||
= users_select_tag(:user_ids, multiple: true, email_user: true, scope: :all)
|
||||
%div.prepend-top-10
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
%div{ class: container_class }
|
||||
.top-area
|
||||
.prepend-top-default
|
||||
= form_tag admin_namespaces_projects_path, method: :get do |f|
|
||||
= form_tag admin_projects_path, method: :get do |f|
|
||||
.search-holder
|
||||
.search-field-holder
|
||||
= search_field_tag :name, params[:name], class: "form-control search-text-input js-search-input", id: "dashboard_search", autofocus: true, spellcheck: false, placeholder: 'Search by name'
|
||||
|
@ -41,19 +41,19 @@
|
|||
= button_tag "Search", class: "btn btn-primary btn-search"
|
||||
|
||||
%ul.nav-links
|
||||
- opts = params[:visibility_level].present? ? {} : { page: admin_namespaces_projects_path }
|
||||
- opts = params[:visibility_level].present? ? {} : { page: admin_projects_path }
|
||||
= nav_link(opts) do
|
||||
= link_to admin_namespaces_projects_path do
|
||||
= link_to admin_projects_path do
|
||||
All
|
||||
|
||||
= nav_link(html_options: { class: params[:visibility_level] == Gitlab::VisibilityLevel::PRIVATE.to_s ? 'active' : '' }) do
|
||||
= link_to admin_namespaces_projects_path(visibility_level: Gitlab::VisibilityLevel::PRIVATE) do
|
||||
= link_to admin_projects_path(visibility_level: Gitlab::VisibilityLevel::PRIVATE) do
|
||||
Private
|
||||
= nav_link(html_options: { class: params[:visibility_level] == Gitlab::VisibilityLevel::INTERNAL.to_s ? 'active' : '' }) do
|
||||
= link_to admin_namespaces_projects_path(visibility_level: Gitlab::VisibilityLevel::INTERNAL) do
|
||||
= link_to admin_projects_path(visibility_level: Gitlab::VisibilityLevel::INTERNAL) do
|
||||
Internal
|
||||
= nav_link(html_options: { class: params[:visibility_level] == Gitlab::VisibilityLevel::PUBLIC.to_s ? 'active' : '' }) do
|
||||
= link_to admin_namespaces_projects_path(visibility_level: Gitlab::VisibilityLevel::PUBLIC) do
|
||||
= link_to admin_projects_path(visibility_level: Gitlab::VisibilityLevel::PUBLIC) do
|
||||
Public
|
||||
|
||||
.nav-controls
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
%strong ##{build.id}
|
||||
|
||||
%td.status
|
||||
= ci_status_with_icon(build.status)
|
||||
= render 'ci/status/badge', status: build.detailed_status(current_user)
|
||||
|
||||
%td.status
|
||||
- if project
|
||||
|
|
10
app/views/ci/status/_badge.html.haml
Normal file
10
app/views/ci/status/_badge.html.haml
Normal file
|
@ -0,0 +1,10 @@
|
|||
- status = local_assigns.fetch(:status)
|
||||
|
||||
- if status.has_details?
|
||||
= link_to status.details_path, class: "ci-status ci-#{status}" do
|
||||
= custom_icon(status.icon)
|
||||
= status.text
|
||||
- else
|
||||
%span{ class: "ci-status ci-#{status}" }
|
||||
= custom_icon(status.icon)
|
||||
= status.text
|
|
@ -1,6 +1,6 @@
|
|||
.content-block.build-header
|
||||
.header-content
|
||||
= ci_status_with_icon(@build.status)
|
||||
= render 'ci/status/badge', status: @build.detailed_status(current_user)
|
||||
Build
|
||||
%strong ##{@build.id}
|
||||
in pipeline
|
||||
|
|
|
@ -9,10 +9,7 @@
|
|||
|
||||
%tr.build.commit{class: ('retried' if retried)}
|
||||
%td.status
|
||||
- if can?(current_user, :read_build, build)
|
||||
= ci_status_with_icon(build.status, namespace_project_build_url(build.project.namespace, build.project, build))
|
||||
- else
|
||||
= ci_status_with_icon(build.status)
|
||||
= render "ci/status/badge", status: build.detailed_status(current_user)
|
||||
|
||||
%td.branch-commit
|
||||
- if can?(current_user, :read_build, build)
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
- status = pipeline.status
|
||||
- detailed_status = pipeline.detailed_status
|
||||
- show_commit = local_assigns.fetch(:show_commit, true)
|
||||
- show_branch = local_assigns.fetch(:show_branch, true)
|
||||
|
||||
%tr.commit
|
||||
%td.commit-link
|
||||
= link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id), class: "ci-status ci-#{detailed_status}" do
|
||||
= ci_icon_for_status(detailed_status)
|
||||
= ci_text_for_status(detailed_status)
|
||||
= render 'ci/status/badge', status: pipeline.detailed_status(current_user)
|
||||
|
||||
%td
|
||||
= link_to namespace_project_pipeline_path(pipeline.project.namespace, pipeline.project, pipeline.id) do
|
||||
|
|
|
@ -8,10 +8,7 @@
|
|||
|
||||
%tr.generic_commit_status{class: ('retried' if retried)}
|
||||
%td.status
|
||||
- if can?(current_user, :read_commit_status, generic_commit_status) && generic_commit_status.target_url
|
||||
= ci_status_with_icon(generic_commit_status.status, generic_commit_status.target_url)
|
||||
- else
|
||||
= ci_status_with_icon(generic_commit_status.status)
|
||||
= render 'ci/status/badge', status: generic_commit_status.detailed_status(current_user)
|
||||
|
||||
%td.generic_commit_status-link
|
||||
- if can?(current_user, :read_commit_status, generic_commit_status) && generic_commit_status.target_url
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.page-content-header
|
||||
.header-main-content
|
||||
= ci_status_with_icon(@pipeline.detailed_status)
|
||||
= render 'ci/status/badge', status: @pipeline.detailed_status(current_user)
|
||||
%strong Pipeline ##{@commit.pipelines.last.id}
|
||||
triggered #{time_ago_with_tooltip(@commit.authored_date)} by
|
||||
= author_avatar(@commit, size: 24)
|
||||
|
|
|
@ -19,4 +19,4 @@
|
|||
%li.build
|
||||
.curve
|
||||
.dropdown.inline.build-content
|
||||
= render "projects/stage/in_stage_group", name: group_name, subject: grouped_statuses
|
||||
= render 'projects/stage/in_stage_group', name: group_name, subject: grouped_statuses
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#{@message}.
|
||||
|
||||
%p
|
||||
= link_to "See the affected projects in the GitLab admin panel", admin_namespaces_projects_url(last_repository_check_failed: 1)
|
||||
= link_to "See the affected projects in the GitLab admin panel", admin_projects_url(last_repository_check_failed: 1)
|
||||
|
||||
%p
|
||||
You are receiving this message because you are a GitLab administrator for #{Gitlab.config.gitlab.url}.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#{@message}.
|
||||
\
|
||||
View details: #{admin_namespaces_projects_url(last_repository_check_failed: 1)}
|
||||
View details: #{admin_projects_url(last_repository_check_failed: 1)}
|
||||
|
||||
You are receiving this message because you are a GitLab administrator
|
||||
for #{Gitlab.config.gitlab.url}.
|
||||
|
|
1
app/views/shared/icons/_icon_status_manual.svg
Executable file
1
app/views/shared/icons/_icon_status_manual.svg
Executable file
|
@ -0,0 +1 @@
|
|||
<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd"><path d="M0 7a7 7 0 1 1 14 0A7 7 0 0 1 0 7z"/><path d="M13 7A6 6 0 1 0 1 7a6 6 0 0 0 12 0z" fill="#FFF"/><path d="M10.5 7.63V6.37l-.787-.13c-.044-.175-.132-.349-.263-.61l.481-.652-.918-.913-.657.478a2.346 2.346 0 0 0-.612-.26L7.656 3.5H6.388l-.132.783c-.219.043-.394.13-.612.26l-.657-.478-.918.913.437.652c-.131.218-.175.392-.262.61l-.744.086v1.261l.787.13c.044.218.132.392.263.61l-.438.651.92.913.655-.434c.175.086.394.173.613.26l.131.783h1.313l.131-.783c.219-.043.394-.13.613-.26l.656.478.918-.913-.48-.652c.13-.218.218-.435.262-.61l.656-.13zM7 8.283a1.285 1.285 0 0 1-1.313-1.305c0-.739.57-1.304 1.313-1.304.744 0 1.313.565 1.313 1.304 0 .74-.57 1.305-1.313 1.305z"/></g></svg>
|
After Width: | Height: | Size: 787 B |
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Changed cursor icon to pointer when mousing over stages on the Cycle Analytics
|
||||
pages
|
||||
merge_request:
|
||||
author: Ryan Harris
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Adds tests for custom event polyfill
|
||||
merge_request: 7996
|
||||
author:
|
|
@ -28,9 +28,19 @@ namespace :admin do
|
|||
|
||||
resources :applications
|
||||
|
||||
resources :groups, constraints: { id: /[^\/]+/ } do
|
||||
member do
|
||||
resources :groups, only: [:index, :new, :create]
|
||||
|
||||
scope(path: 'groups/*id',
|
||||
controller: :groups,
|
||||
constraints: { id: Gitlab::Regex.namespace_route_regex }) do
|
||||
|
||||
scope(as: :group) do
|
||||
put :members_update
|
||||
get :edit, action: :edit
|
||||
get '/', action: :show
|
||||
patch '/', action: :update
|
||||
put '/', action: :update
|
||||
delete '/', action: :destroy
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -50,14 +60,13 @@ namespace :admin do
|
|||
resource :system_info, controller: 'system_info', only: [:show]
|
||||
resources :requests_profiles, only: [:index, :show], param: :name, constraints: { name: /.+\.html/ }
|
||||
|
||||
resources :namespaces, path: '/projects', constraints: { id: /[a-zA-Z.0-9_\-]+/ }, only: [] do
|
||||
root to: 'projects#index', as: :projects
|
||||
resources :projects, only: [:index]
|
||||
|
||||
scope(path: 'projects/*namespace_id', as: :namespace) do
|
||||
resources(:projects,
|
||||
path: '/',
|
||||
constraints: { id: /[a-zA-Z.0-9_\-]+/ },
|
||||
only: [:index, :show]) do
|
||||
root to: 'projects#show'
|
||||
constraints: { id: Gitlab::Regex.project_route_regex },
|
||||
only: [:show]) do
|
||||
|
||||
member do
|
||||
put :transfer
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
|
||||
# for more information on how to write migrations for GitLab.
|
||||
|
||||
class RemoveUniqPathIndexFromNamespace < ActiveRecord::Migration
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
def up
|
||||
constraint_name = 'namespaces_path_key'
|
||||
|
||||
transaction do
|
||||
if index_exists?(:namespaces, :path)
|
||||
remove_index(:namespaces, :path)
|
||||
end
|
||||
|
||||
# In some bizarre cases PostgreSQL might have a separate unique constraint
|
||||
# that we'll need to drop.
|
||||
if constraint_exists?(constraint_name) && Gitlab::Database.postgresql?
|
||||
execute("ALTER TABLE namespaces DROP CONSTRAINT IF EXISTS #{constraint_name};")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
unless index_exists?(:namespaces, :path)
|
||||
add_concurrent_index(:namespaces, :path, unique: true)
|
||||
end
|
||||
end
|
||||
|
||||
def constraint_exists?(name)
|
||||
indexes(:namespaces).map(&:name).include?(name)
|
||||
end
|
||||
end
|
20
db/migrate/20161206153751_add_path_index_to_namespace.rb
Normal file
20
db/migrate/20161206153751_add_path_index_to_namespace.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
|
||||
# for more information on how to write migrations for GitLab.
|
||||
|
||||
class AddPathIndexToNamespace < ActiveRecord::Migration
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
def up
|
||||
add_concurrent_index :namespaces, :path
|
||||
end
|
||||
|
||||
def down
|
||||
if index_exists?(:namespaces, :path)
|
||||
remove_index :namespaces, :path
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,36 @@
|
|||
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
|
||||
# for more information on how to write migrations for GitLab.
|
||||
|
||||
class RemoveUniqNameIndexFromNamespace < ActiveRecord::Migration
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
def up
|
||||
constraint_name = 'namespaces_name_key'
|
||||
|
||||
transaction do
|
||||
if index_exists?(:namespaces, :name)
|
||||
remove_index(:namespaces, :name)
|
||||
end
|
||||
|
||||
# In some bizarre cases PostgreSQL might have a separate unique constraint
|
||||
# that we'll need to drop.
|
||||
if constraint_exists?(constraint_name) && Gitlab::Database.postgresql?
|
||||
execute("ALTER TABLE namespaces DROP CONSTRAINT IF EXISTS #{constraint_name};")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
unless index_exists?(:namespaces, :name)
|
||||
add_concurrent_index(:namespaces, :name, unique: true)
|
||||
end
|
||||
end
|
||||
|
||||
def constraint_exists?(name)
|
||||
indexes(:namespaces).map(&:name).include?(name)
|
||||
end
|
||||
end
|
20
db/migrate/20161206153754_add_name_index_to_namespace.rb
Normal file
20
db/migrate/20161206153754_add_name_index_to_namespace.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
|
||||
# for more information on how to write migrations for GitLab.
|
||||
|
||||
class AddNameIndexToNamespace < ActiveRecord::Migration
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
def up
|
||||
add_concurrent_index(:namespaces, [:name, :parent_id], unique: true)
|
||||
end
|
||||
|
||||
def down
|
||||
if index_exists?(:namespaces, :name)
|
||||
remove_index :namespaces, [:name, :parent_id]
|
||||
end
|
||||
end
|
||||
end
|
|
@ -744,11 +744,11 @@ ActiveRecord::Schema.define(version: 20161212142807) do
|
|||
|
||||
add_index "namespaces", ["created_at"], name: "index_namespaces_on_created_at", using: :btree
|
||||
add_index "namespaces", ["deleted_at"], name: "index_namespaces_on_deleted_at", using: :btree
|
||||
add_index "namespaces", ["name"], name: "index_namespaces_on_name", unique: true, using: :btree
|
||||
add_index "namespaces", ["name", "parent_id"], name: "index_namespaces_on_name_and_parent_id", unique: true, using: :btree
|
||||
add_index "namespaces", ["name"], name: "index_namespaces_on_name_trigram", using: :gin, opclasses: {"name"=>"gin_trgm_ops"}
|
||||
add_index "namespaces", ["owner_id"], name: "index_namespaces_on_owner_id", using: :btree
|
||||
add_index "namespaces", ["parent_id", "id"], name: "index_namespaces_on_parent_id_and_id", unique: true, using: :btree
|
||||
add_index "namespaces", ["path"], name: "index_namespaces_on_path", unique: true, using: :btree
|
||||
add_index "namespaces", ["path"], name: "index_namespaces_on_path", using: :btree
|
||||
add_index "namespaces", ["path"], name: "index_namespaces_on_path_trigram", using: :gin, opclasses: {"path"=>"gin_trgm_ops"}
|
||||
add_index "namespaces", ["type"], name: "index_namespaces_on_type", using: :btree
|
||||
|
||||
|
@ -1290,4 +1290,4 @@ ActiveRecord::Schema.define(version: 20161212142807) do
|
|||
add_foreign_key "subscriptions", "projects", on_delete: :cascade
|
||||
add_foreign_key "trending_projects", "projects", on_delete: :cascade
|
||||
add_foreign_key "u2f_registrations", "users"
|
||||
end
|
||||
end
|
|
@ -72,7 +72,7 @@ sudo -u git -H git checkout 8-14-stable-ee
|
|||
```bash
|
||||
cd /home/git/gitlab-shell
|
||||
sudo -u git -H git fetch --all --tags
|
||||
sudo -u git -H git checkout v4.0.0
|
||||
sudo -u git -H git checkout v4.0.3
|
||||
```
|
||||
|
||||
### 6. Update gitlab-workhorse
|
||||
|
|
|
@ -168,7 +168,7 @@ module SharedPaths
|
|||
end
|
||||
|
||||
step 'I visit admin projects page' do
|
||||
visit admin_namespaces_projects_path
|
||||
visit admin_projects_path
|
||||
end
|
||||
|
||||
step 'I visit admin users page' do
|
||||
|
|
7
lib/gitlab/allowable.rb
Normal file
7
lib/gitlab/allowable.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
module Gitlab
|
||||
module Allowable
|
||||
def can?(user, action, subject)
|
||||
Ability.allowed?(user, action, subject)
|
||||
end
|
||||
end
|
||||
end
|
37
lib/gitlab/ci/status/build/cancelable.rb
Normal file
37
lib/gitlab/ci/status/build/cancelable.rb
Normal file
|
@ -0,0 +1,37 @@
|
|||
module Gitlab
|
||||
module Ci
|
||||
module Status
|
||||
module Build
|
||||
class Cancelable < SimpleDelegator
|
||||
include Status::Extended
|
||||
|
||||
def has_action?
|
||||
can?(user, :update_build, subject)
|
||||
end
|
||||
|
||||
def action_icon
|
||||
'ban'
|
||||
end
|
||||
|
||||
def action_path
|
||||
cancel_namespace_project_build_path(subject.project.namespace,
|
||||
subject.project,
|
||||
subject)
|
||||
end
|
||||
|
||||
def action_method
|
||||
:post
|
||||
end
|
||||
|
||||
def action_title
|
||||
'Cancel'
|
||||
end
|
||||
|
||||
def self.matches?(build, user)
|
||||
build.cancelable?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
19
lib/gitlab/ci/status/build/common.rb
Normal file
19
lib/gitlab/ci/status/build/common.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
module Gitlab
|
||||
module Ci
|
||||
module Status
|
||||
module Build
|
||||
module Common
|
||||
def has_details?
|
||||
can?(user, :read_build, subject)
|
||||
end
|
||||
|
||||
def details_path
|
||||
namespace_project_build_path(subject.project.namespace,
|
||||
subject.project,
|
||||
subject)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
18
lib/gitlab/ci/status/build/factory.rb
Normal file
18
lib/gitlab/ci/status/build/factory.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
module Gitlab
|
||||
module Ci
|
||||
module Status
|
||||
module Build
|
||||
class Factory < Status::Factory
|
||||
def self.extended_statuses
|
||||
[Status::Build::Stop, Status::Build::Play,
|
||||
Status::Build::Cancelable, Status::Build::Retryable]
|
||||
end
|
||||
|
||||
def self.common_helpers
|
||||
Status::Build::Common
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
53
lib/gitlab/ci/status/build/play.rb
Normal file
53
lib/gitlab/ci/status/build/play.rb
Normal file
|
@ -0,0 +1,53 @@
|
|||
module Gitlab
|
||||
module Ci
|
||||
module Status
|
||||
module Build
|
||||
class Play < SimpleDelegator
|
||||
include Status::Extended
|
||||
|
||||
def text
|
||||
'manual'
|
||||
end
|
||||
|
||||
def label
|
||||
'manual play action'
|
||||
end
|
||||
|
||||
def icon
|
||||
'icon_status_manual'
|
||||
end
|
||||
|
||||
def has_action?
|
||||
can?(user, :update_build, subject)
|
||||
end
|
||||
|
||||
def action_icon
|
||||
'play'
|
||||
end
|
||||
|
||||
def action_title
|
||||
'Play'
|
||||
end
|
||||
|
||||
def action_class
|
||||
'ci-play-icon'
|
||||
end
|
||||
|
||||
def action_path
|
||||
play_namespace_project_build_path(subject.project.namespace,
|
||||
subject.project,
|
||||
subject)
|
||||
end
|
||||
|
||||
def action_method
|
||||
:post
|
||||
end
|
||||
|
||||
def self.matches?(build, user)
|
||||
build.playable? && !build.stops_environment?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
37
lib/gitlab/ci/status/build/retryable.rb
Normal file
37
lib/gitlab/ci/status/build/retryable.rb
Normal file
|
@ -0,0 +1,37 @@
|
|||
module Gitlab
|
||||
module Ci
|
||||
module Status
|
||||
module Build
|
||||
class Retryable < SimpleDelegator
|
||||
include Status::Extended
|
||||
|
||||
def has_action?
|
||||
can?(user, :update_build, subject)
|
||||
end
|
||||
|
||||
def action_icon
|
||||
'refresh'
|
||||
end
|
||||
|
||||
def action_title
|
||||
'Retry'
|
||||
end
|
||||
|
||||
def action_path
|
||||
retry_namespace_project_build_path(subject.project.namespace,
|
||||
subject.project,
|
||||
subject)
|
||||
end
|
||||
|
||||
def action_method
|
||||
:post
|
||||
end
|
||||
|
||||
def self.matches?(build, user)
|
||||
build.retryable?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
49
lib/gitlab/ci/status/build/stop.rb
Normal file
49
lib/gitlab/ci/status/build/stop.rb
Normal file
|
@ -0,0 +1,49 @@
|
|||
module Gitlab
|
||||
module Ci
|
||||
module Status
|
||||
module Build
|
||||
class Stop < SimpleDelegator
|
||||
include Status::Extended
|
||||
|
||||
def text
|
||||
'manual'
|
||||
end
|
||||
|
||||
def label
|
||||
'manual stop action'
|
||||
end
|
||||
|
||||
def icon
|
||||
'icon_status_manual'
|
||||
end
|
||||
|
||||
def has_action?
|
||||
can?(user, :update_build, subject)
|
||||
end
|
||||
|
||||
def action_icon
|
||||
'stop'
|
||||
end
|
||||
|
||||
def action_title
|
||||
'Stop'
|
||||
end
|
||||
|
||||
def action_path
|
||||
play_namespace_project_build_path(subject.project.namespace,
|
||||
subject.project,
|
||||
subject)
|
||||
end
|
||||
|
||||
def action_method
|
||||
:post
|
||||
end
|
||||
|
||||
def self.matches?(build, user)
|
||||
build.playable? && build.stops_environment?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -4,10 +4,14 @@ module Gitlab
|
|||
# Base abstract class fore core status
|
||||
#
|
||||
class Core
|
||||
include Gitlab::Routing.url_helpers
|
||||
include Gitlab::Routing
|
||||
include Gitlab::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.
|
||||
|
@ -34,7 +34,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def has_details?
|
||||
raise NotImplementedError
|
||||
false
|
||||
end
|
||||
|
||||
def details_path
|
||||
|
@ -42,16 +42,27 @@ module Gitlab
|
|||
end
|
||||
|
||||
def has_action?
|
||||
raise NotImplementedError
|
||||
false
|
||||
end
|
||||
|
||||
def action_icon
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def action_class
|
||||
end
|
||||
|
||||
def action_path
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def action_method
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def action_title
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,8 +2,12 @@ module Gitlab
|
|||
module Ci
|
||||
module Status
|
||||
module Extended
|
||||
def matches?(_subject)
|
||||
raise NotImplementedError
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
class_methods do
|
||||
def matches?(_subject, _user)
|
||||
raise NotImplementedError
|
||||
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,27 +15,32 @@ 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)
|
||||
@extended ||= self.class.extended_statuses.find do |status|
|
||||
status.matches?(@subject, @user)
|
||||
end
|
||||
end
|
||||
|
||||
def extended_statuses
|
||||
[]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,13 +4,13 @@ module Gitlab
|
|||
module Pipeline
|
||||
module Common
|
||||
def has_details?
|
||||
true
|
||||
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
|
||||
|
|
|
@ -4,14 +4,14 @@ module Gitlab
|
|||
module Stage
|
||||
module Common
|
||||
def has_details?
|
||||
true
|
||||
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
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
module Gitlab
|
||||
module Routing
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
include Gitlab::Routing.url_helpers
|
||||
end
|
||||
|
||||
# Returns the URL helpers Module.
|
||||
#
|
||||
# This method caches the output as Rails' "url_helpers" method creates an
|
||||
|
|
|
@ -12,12 +12,14 @@ FactoryGirl.define do
|
|||
started_at 'Di 29. Okt 09:51:28 CET 2013'
|
||||
finished_at 'Di 29. Okt 09:53:28 CET 2013'
|
||||
commands 'ls -a'
|
||||
|
||||
options do
|
||||
{
|
||||
image: "ruby:2.1",
|
||||
services: ["postgres"]
|
||||
}
|
||||
end
|
||||
|
||||
yaml_variables do
|
||||
[
|
||||
{ key: :DB_NAME, value: 'postgres', public: true }
|
||||
|
@ -60,15 +62,20 @@ FactoryGirl.define do
|
|||
end
|
||||
|
||||
trait :teardown_environment do
|
||||
options do
|
||||
{ environment: { action: 'stop' } }
|
||||
end
|
||||
environment 'staging'
|
||||
options environment: { name: 'staging',
|
||||
action: 'stop' }
|
||||
end
|
||||
|
||||
trait :allowed_to_fail do
|
||||
allow_failure true
|
||||
end
|
||||
|
||||
trait :playable do
|
||||
skipped
|
||||
manual
|
||||
end
|
||||
|
||||
after(:build) do |build, evaluator|
|
||||
build.project = build.pipeline.project
|
||||
end
|
||||
|
|
|
@ -21,7 +21,7 @@ feature 'Admin Groups', feature: true do
|
|||
scenario 'shows the visibility level radio populated with the group visibility_level value' do
|
||||
group = create(:group, :private)
|
||||
|
||||
visit edit_admin_group_path(group)
|
||||
visit admin_group_edit_path(group)
|
||||
|
||||
expect_selected_visibility(group.visibility_level)
|
||||
end
|
||||
|
|
|
@ -8,11 +8,11 @@ describe "Admin::Projects", feature: true do
|
|||
|
||||
describe "GET /admin/projects" do
|
||||
before do
|
||||
visit admin_namespaces_projects_path
|
||||
visit admin_projects_path
|
||||
end
|
||||
|
||||
it "is ok" do
|
||||
expect(current_path).to eq(admin_namespaces_projects_path)
|
||||
expect(current_path).to eq(admin_projects_path)
|
||||
end
|
||||
|
||||
it "has projects list" do
|
||||
|
@ -22,7 +22,7 @@ describe "Admin::Projects", feature: true do
|
|||
|
||||
describe "GET /admin/projects/:id" do
|
||||
before do
|
||||
visit admin_namespaces_projects_path
|
||||
visit admin_projects_path
|
||||
click_link "#{@project.name}"
|
||||
end
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ describe "Admin::Projects", feature: true do
|
|||
include AccessMatchers
|
||||
|
||||
describe "GET /admin/projects" do
|
||||
subject { admin_namespaces_projects_path }
|
||||
subject { admin_projects_path }
|
||||
|
||||
it { is_expected.to be_allowed_for :admin }
|
||||
it { is_expected.to be_denied_for :user }
|
||||
|
|
43
spec/javascripts/lib/utils/custom_event_polyfill_spec.js.es6
Normal file
43
spec/javascripts/lib/utils/custom_event_polyfill_spec.js.es6
Normal file
|
@ -0,0 +1,43 @@
|
|||
//= require lib/utils/custom_event_polyfill
|
||||
|
||||
describe('Custom Event Polyfill', () => {
|
||||
it('should be defined', () => {
|
||||
expect(window.CustomEvent).toBeDefined();
|
||||
});
|
||||
|
||||
it('should create a `CustomEvent` instance', () => {
|
||||
const e = new window.CustomEvent('foo');
|
||||
|
||||
expect(e.type).toEqual('foo');
|
||||
expect(e.bubbles).toBe(false);
|
||||
expect(e.cancelable).toBe(false);
|
||||
expect(e.detail).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should create a `CustomEvent` instance with a `details` object', () => {
|
||||
const e = new window.CustomEvent('bar', { detail: { foo: 'bar' } });
|
||||
|
||||
expect(e.type).toEqual('bar');
|
||||
expect(e.bubbles).toBe(false);
|
||||
expect(e.cancelable).toBe(false);
|
||||
expect(e.detail.foo).toEqual('bar');
|
||||
});
|
||||
|
||||
it('should create a `CustomEvent` instance with a `bubbles` boolean', () => {
|
||||
const e = new window.CustomEvent('bar', { bubbles: true });
|
||||
|
||||
expect(e.type).toEqual('bar');
|
||||
expect(e.bubbles).toBe(true);
|
||||
expect(e.cancelable).toBe(false);
|
||||
expect(e.detail).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should create a `CustomEvent` instance with a `cancelable` boolean', () => {
|
||||
const e = new window.CustomEvent('bar', { cancelable: true });
|
||||
|
||||
expect(e.type).toEqual('bar');
|
||||
expect(e.bubbles).toBe(false);
|
||||
expect(e.cancelable).toBe(true);
|
||||
expect(e.detail).toBeFalsy();
|
||||
});
|
||||
});
|
27
spec/lib/gitlab/allowable_spec.rb
Normal file
27
spec/lib/gitlab/allowable_spec.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Allowable do
|
||||
subject do
|
||||
Class.new.include(described_class).new
|
||||
end
|
||||
|
||||
describe '#can?' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
context 'when user is allowed to do something' do
|
||||
let(:project) { create(:empty_project, :public) }
|
||||
|
||||
it 'reports correct ability to perform action' do
|
||||
expect(subject.can?(user, :read_project, project)).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user is not allowed to do something' do
|
||||
let(:project) { create(:empty_project, :private) }
|
||||
|
||||
it 'reports correct ability to perform action' do
|
||||
expect(subject.can?(user, :read_project, project)).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
86
spec/lib/gitlab/ci/status/build/cancelable_spec.rb
Normal file
86
spec/lib/gitlab/ci/status/build/cancelable_spec.rb
Normal file
|
@ -0,0 +1,86 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Build::Cancelable do
|
||||
let(:status) { double('core status') }
|
||||
let(:user) { double('user') }
|
||||
|
||||
subject do
|
||||
described_class.new(status)
|
||||
end
|
||||
|
||||
describe '#text' do
|
||||
it 'does not override status text' do
|
||||
expect(status).to receive(:text)
|
||||
|
||||
subject.text
|
||||
end
|
||||
end
|
||||
|
||||
describe '#icon' do
|
||||
it 'does not override status icon' do
|
||||
expect(status).to receive(:icon)
|
||||
|
||||
subject.icon
|
||||
end
|
||||
end
|
||||
|
||||
describe '#label' do
|
||||
it 'does not override status label' do
|
||||
expect(status).to receive(:label)
|
||||
|
||||
subject.label
|
||||
end
|
||||
end
|
||||
|
||||
describe 'action details' do
|
||||
let(:user) { create(:user) }
|
||||
let(:build) { create(:ci_build) }
|
||||
let(:status) { Gitlab::Ci::Status::Core.new(build, user) }
|
||||
|
||||
describe '#has_action?' do
|
||||
context 'when user is allowed to update build' do
|
||||
before { build.project.team << [user, :developer] }
|
||||
|
||||
it { is_expected.to have_action }
|
||||
end
|
||||
|
||||
context 'when user is not allowed to update build' do
|
||||
it { is_expected.not_to have_action }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#action_path' do
|
||||
it { expect(subject.action_path).to include "#{build.id}/cancel" }
|
||||
end
|
||||
|
||||
describe '#action_icon' do
|
||||
it { expect(subject.action_icon).to eq 'ban' }
|
||||
end
|
||||
|
||||
describe '#action_title' do
|
||||
it { expect(subject.action_title).to eq 'Cancel' }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.matches?' do
|
||||
subject { described_class.matches?(build, user) }
|
||||
|
||||
context 'when build is cancelable' do
|
||||
let(:build) do
|
||||
create(:ci_build, :running)
|
||||
end
|
||||
|
||||
it 'is a correct match' do
|
||||
expect(subject).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is not cancelable' do
|
||||
let(:build) { create(:ci_build, :success) }
|
||||
|
||||
it 'does not match' do
|
||||
expect(subject).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
37
spec/lib/gitlab/ci/status/build/common_spec.rb
Normal file
37
spec/lib/gitlab/ci/status/build/common_spec.rb
Normal file
|
@ -0,0 +1,37 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Build::Common do
|
||||
let(:user) { create(:user) }
|
||||
let(:build) { create(:ci_build) }
|
||||
let(:project) { build.project }
|
||||
|
||||
subject do
|
||||
Gitlab::Ci::Status::Core
|
||||
.new(build, user)
|
||||
.extend(described_class)
|
||||
end
|
||||
|
||||
describe '#has_action?' do
|
||||
it { is_expected.not_to have_action }
|
||||
end
|
||||
|
||||
describe '#has_details?' do
|
||||
context 'when user has access to read build' do
|
||||
before { project.team << [user, :developer] }
|
||||
|
||||
it { is_expected.to have_details }
|
||||
end
|
||||
|
||||
context 'when user does not have access to read build' do
|
||||
before { project.update(public_builds: false) }
|
||||
|
||||
it { is_expected.not_to have_details }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#details_path' do
|
||||
it 'links to the build details page' do
|
||||
expect(subject.details_path).to include "builds/#{build.id}"
|
||||
end
|
||||
end
|
||||
end
|
141
spec/lib/gitlab/ci/status/build/factory_spec.rb
Normal file
141
spec/lib/gitlab/ci/status/build/factory_spec.rb
Normal file
|
@ -0,0 +1,141 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Build::Factory do
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { build.project }
|
||||
|
||||
subject { described_class.new(build, user) }
|
||||
let(:status) { subject.fabricate! }
|
||||
|
||||
before { project.team << [user, :developer] }
|
||||
|
||||
context 'when build is successful' do
|
||||
let(:build) { create(:ci_build, :success) }
|
||||
|
||||
it 'fabricates a retryable build status' do
|
||||
expect(status).to be_a Gitlab::Ci::Status::Build::Retryable
|
||||
end
|
||||
|
||||
it 'fabricates status with correct details' do
|
||||
expect(status.text).to eq 'passed'
|
||||
expect(status.icon).to eq 'icon_status_success'
|
||||
expect(status.label).to eq 'passed'
|
||||
expect(status).to have_details
|
||||
expect(status).to have_action
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is failed' do
|
||||
let(:build) { create(:ci_build, :failed) }
|
||||
|
||||
it 'fabricates a retryable build status' do
|
||||
expect(status).to be_a Gitlab::Ci::Status::Build::Retryable
|
||||
end
|
||||
|
||||
it 'fabricates status with correct details' do
|
||||
expect(status.text).to eq 'failed'
|
||||
expect(status.icon).to eq 'icon_status_failed'
|
||||
expect(status.label).to eq 'failed'
|
||||
expect(status).to have_details
|
||||
expect(status).to have_action
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is a canceled' do
|
||||
let(:build) { create(:ci_build, :canceled) }
|
||||
|
||||
it 'fabricates a retryable build status' do
|
||||
expect(status).to be_a Gitlab::Ci::Status::Build::Retryable
|
||||
end
|
||||
|
||||
it 'fabricates status with correct details' do
|
||||
expect(status.text).to eq 'canceled'
|
||||
expect(status.icon).to eq 'icon_status_canceled'
|
||||
expect(status.label).to eq 'canceled'
|
||||
expect(status).to have_details
|
||||
expect(status).to have_action
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is running' do
|
||||
let(:build) { create(:ci_build, :running) }
|
||||
|
||||
it 'fabricates a canceable build status' do
|
||||
expect(status).to be_a Gitlab::Ci::Status::Build::Cancelable
|
||||
end
|
||||
|
||||
it 'fabricates status with correct details' do
|
||||
expect(status.text).to eq 'running'
|
||||
expect(status.icon).to eq 'icon_status_running'
|
||||
expect(status.label).to eq 'running'
|
||||
expect(status).to have_details
|
||||
expect(status).to have_action
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is pending' do
|
||||
let(:build) { create(:ci_build, :pending) }
|
||||
|
||||
it 'fabricates a cancelable build status' do
|
||||
expect(status).to be_a Gitlab::Ci::Status::Build::Cancelable
|
||||
end
|
||||
|
||||
it 'fabricates status with correct details' do
|
||||
expect(status.text).to eq 'pending'
|
||||
expect(status.icon).to eq 'icon_status_pending'
|
||||
expect(status.label).to eq 'pending'
|
||||
expect(status).to have_details
|
||||
expect(status).to have_action
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is skipped' do
|
||||
let(:build) { create(:ci_build, :skipped) }
|
||||
|
||||
it 'fabricates a core skipped status' do
|
||||
expect(status).to be_a Gitlab::Ci::Status::Skipped
|
||||
end
|
||||
|
||||
it 'fabricates status with correct details' do
|
||||
expect(status.text).to eq 'skipped'
|
||||
expect(status.icon).to eq 'icon_status_skipped'
|
||||
expect(status.label).to eq 'skipped'
|
||||
expect(status).to have_details
|
||||
expect(status).not_to have_action
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is a manual action' do
|
||||
context 'when build is a play action' do
|
||||
let(:build) { create(:ci_build, :playable) }
|
||||
|
||||
it 'fabricates a core skipped status' do
|
||||
expect(status).to be_a Gitlab::Ci::Status::Build::Play
|
||||
end
|
||||
|
||||
it 'fabricates status with correct details' do
|
||||
expect(status.text).to eq 'manual'
|
||||
expect(status.icon).to eq 'icon_status_manual'
|
||||
expect(status.label).to eq 'manual play action'
|
||||
expect(status).to have_details
|
||||
expect(status).to have_action
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is an environment stop action' do
|
||||
let(:build) { create(:ci_build, :playable, :teardown_environment) }
|
||||
|
||||
it 'fabricates a core skipped status' do
|
||||
expect(status).to be_a Gitlab::Ci::Status::Build::Stop
|
||||
end
|
||||
|
||||
it 'fabricates status with correct details' do
|
||||
expect(status.text).to eq 'manual'
|
||||
expect(status.icon).to eq 'icon_status_manual'
|
||||
expect(status.label).to eq 'manual stop action'
|
||||
expect(status).to have_details
|
||||
expect(status).to have_action
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
82
spec/lib/gitlab/ci/status/build/play_spec.rb
Normal file
82
spec/lib/gitlab/ci/status/build/play_spec.rb
Normal file
|
@ -0,0 +1,82 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Build::Play do
|
||||
let(:status) { double('core') }
|
||||
let(:user) { double('user') }
|
||||
|
||||
subject { described_class.new(status) }
|
||||
|
||||
describe '#text' do
|
||||
it { expect(subject.text).to eq 'manual' }
|
||||
end
|
||||
|
||||
describe '#label' do
|
||||
it { expect(subject.label).to eq 'manual play action' }
|
||||
end
|
||||
|
||||
describe '#icon' do
|
||||
it { expect(subject.icon).to eq 'icon_status_manual' }
|
||||
end
|
||||
|
||||
describe 'action details' do
|
||||
let(:user) { create(:user) }
|
||||
let(:build) { create(:ci_build) }
|
||||
let(:status) { Gitlab::Ci::Status::Core.new(build, user) }
|
||||
|
||||
describe '#has_action?' do
|
||||
context 'when user is allowed to update build' do
|
||||
before { build.project.team << [user, :developer] }
|
||||
|
||||
it { is_expected.to have_action }
|
||||
end
|
||||
|
||||
context 'when user is not allowed to update build' do
|
||||
it { is_expected.not_to have_action }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#action_path' do
|
||||
it { expect(subject.action_path).to include "#{build.id}/play" }
|
||||
end
|
||||
|
||||
describe '#action_icon' do
|
||||
it { expect(subject.action_icon).to eq 'play' }
|
||||
end
|
||||
|
||||
describe '#action_title' do
|
||||
it { expect(subject.action_title).to eq 'Play' }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.matches?' do
|
||||
subject { described_class.matches?(build, user) }
|
||||
|
||||
context 'when build is playable' do
|
||||
context 'when build stops an environment' do
|
||||
let(:build) do
|
||||
create(:ci_build, :playable, :teardown_environment)
|
||||
end
|
||||
|
||||
it 'does not match' do
|
||||
expect(subject).to be false
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build does not stop an environment' do
|
||||
let(:build) { create(:ci_build, :playable) }
|
||||
|
||||
it 'is a correct match' do
|
||||
expect(subject).to be true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is not playable' do
|
||||
let(:build) { create(:ci_build) }
|
||||
|
||||
it 'does not match' do
|
||||
expect(subject).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
86
spec/lib/gitlab/ci/status/build/retryable_spec.rb
Normal file
86
spec/lib/gitlab/ci/status/build/retryable_spec.rb
Normal file
|
@ -0,0 +1,86 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Build::Retryable do
|
||||
let(:status) { double('core status') }
|
||||
let(:user) { double('user') }
|
||||
|
||||
subject do
|
||||
described_class.new(status)
|
||||
end
|
||||
|
||||
describe '#text' do
|
||||
it 'does not override status text' do
|
||||
expect(status).to receive(:text)
|
||||
|
||||
subject.text
|
||||
end
|
||||
end
|
||||
|
||||
describe '#icon' do
|
||||
it 'does not override status icon' do
|
||||
expect(status).to receive(:icon)
|
||||
|
||||
subject.icon
|
||||
end
|
||||
end
|
||||
|
||||
describe '#label' do
|
||||
it 'does not override status label' do
|
||||
expect(status).to receive(:label)
|
||||
|
||||
subject.label
|
||||
end
|
||||
end
|
||||
|
||||
describe 'action details' do
|
||||
let(:user) { create(:user) }
|
||||
let(:build) { create(:ci_build) }
|
||||
let(:status) { Gitlab::Ci::Status::Core.new(build, user) }
|
||||
|
||||
describe '#has_action?' do
|
||||
context 'when user is allowed to update build' do
|
||||
before { build.project.team << [user, :developer] }
|
||||
|
||||
it { is_expected.to have_action }
|
||||
end
|
||||
|
||||
context 'when user is not allowed to update build' do
|
||||
it { is_expected.not_to have_action }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#action_path' do
|
||||
it { expect(subject.action_path).to include "#{build.id}/retry" }
|
||||
end
|
||||
|
||||
describe '#action_icon' do
|
||||
it { expect(subject.action_icon).to eq 'refresh' }
|
||||
end
|
||||
|
||||
describe '#action_title' do
|
||||
it { expect(subject.action_title).to eq 'Retry' }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.matches?' do
|
||||
subject { described_class.matches?(build, user) }
|
||||
|
||||
context 'when build is retryable' do
|
||||
let(:build) do
|
||||
create(:ci_build, :success)
|
||||
end
|
||||
|
||||
it 'is a correct match' do
|
||||
expect(subject).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is not retryable' do
|
||||
let(:build) { create(:ci_build, :running) }
|
||||
|
||||
it 'does not match' do
|
||||
expect(subject).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
84
spec/lib/gitlab/ci/status/build/stop_spec.rb
Normal file
84
spec/lib/gitlab/ci/status/build/stop_spec.rb
Normal file
|
@ -0,0 +1,84 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Build::Stop do
|
||||
let(:status) { double('core status') }
|
||||
let(:user) { double('user') }
|
||||
|
||||
subject do
|
||||
described_class.new(status)
|
||||
end
|
||||
|
||||
describe '#text' do
|
||||
it { expect(subject.text).to eq 'manual' }
|
||||
end
|
||||
|
||||
describe '#label' do
|
||||
it { expect(subject.label).to eq 'manual stop action' }
|
||||
end
|
||||
|
||||
describe '#icon' do
|
||||
it { expect(subject.icon).to eq 'icon_status_manual' }
|
||||
end
|
||||
|
||||
describe 'action details' do
|
||||
let(:user) { create(:user) }
|
||||
let(:build) { create(:ci_build) }
|
||||
let(:status) { Gitlab::Ci::Status::Core.new(build, user) }
|
||||
|
||||
describe '#has_action?' do
|
||||
context 'when user is allowed to update build' do
|
||||
before { build.project.team << [user, :developer] }
|
||||
|
||||
it { is_expected.to have_action }
|
||||
end
|
||||
|
||||
context 'when user is not allowed to update build' do
|
||||
it { is_expected.not_to have_action }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#action_path' do
|
||||
it { expect(subject.action_path).to include "#{build.id}/play" }
|
||||
end
|
||||
|
||||
describe '#action_icon' do
|
||||
it { expect(subject.action_icon).to eq 'stop' }
|
||||
end
|
||||
|
||||
describe '#action_title' do
|
||||
it { expect(subject.action_title).to eq 'Stop' }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.matches?' do
|
||||
subject { described_class.matches?(build, user) }
|
||||
|
||||
context 'when build is playable' do
|
||||
context 'when build stops an environment' do
|
||||
let(:build) do
|
||||
create(:ci_build, :playable, :teardown_environment)
|
||||
end
|
||||
|
||||
it 'is a correct match' do
|
||||
expect(subject).to be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build does not stop an environment' do
|
||||
let(:build) { create(:ci_build, :playable) }
|
||||
|
||||
it 'does not match' do
|
||||
expect(subject).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is not playable' do
|
||||
let(:build) { create(:ci_build) }
|
||||
|
||||
it 'does not match' do
|
||||
expect(subject).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,7 +1,9 @@
|
|||
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
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
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(
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
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
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
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
|
||||
|
|
|
@ -1,23 +1,36 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Ci::Status::Pipeline::Common do
|
||||
let(:pipeline) { create(:ci_pipeline) }
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:empty_project, :private) }
|
||||
let(:pipeline) { create(:ci_pipeline, project: project) }
|
||||
|
||||
subject do
|
||||
Class.new(Gitlab::Ci::Status::Core)
|
||||
.new(pipeline).extend(described_class)
|
||||
Gitlab::Ci::Status::Core
|
||||
.new(pipeline, user)
|
||||
.extend(described_class)
|
||||
end
|
||||
|
||||
it 'does not have action' do
|
||||
expect(subject).not_to have_action
|
||||
describe '#has_action?' do
|
||||
it { is_expected.not_to have_action }
|
||||
end
|
||||
|
||||
it 'has details' do
|
||||
expect(subject).to have_details
|
||||
describe '#has_details?' do
|
||||
context 'when user has access to read pipeline' do
|
||||
before { project.team << [user, :developer] }
|
||||
|
||||
it { is_expected.to have_details }
|
||||
end
|
||||
|
||||
context 'when user does not have access to read pipeline' do
|
||||
it { is_expected.not_to have_details }
|
||||
end
|
||||
end
|
||||
|
||||
it 'links to the pipeline details page' do
|
||||
expect(subject.details_path)
|
||||
.to include "pipelines/#{pipeline.id}"
|
||||
describe '#details_path' do
|
||||
it 'links to the pipeline details page' do
|
||||
expect(subject.details_path)
|
||||
.to include "pipelines/#{pipeline.id}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
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
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
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
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
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
|
||||
|
|
|
@ -1,26 +1,43 @@
|
|||
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
|
||||
|
|
|
@ -1,17 +1,26 @@
|
|||
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
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
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
|
||||
|
|
23
spec/lib/gitlab/routing_spec.rb
Normal file
23
spec/lib/gitlab/routing_spec.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::Routing do
|
||||
context 'when module is included' do
|
||||
subject do
|
||||
Class.new.include(described_class).new
|
||||
end
|
||||
|
||||
it 'makes it possible to access url helpers' do
|
||||
expect(subject).to respond_to(:namespace_project_path)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when module is not included' do
|
||||
subject do
|
||||
Class.new.include(described_class.url_helpers).new
|
||||
end
|
||||
|
||||
it 'exposes url helpers module through a method' do
|
||||
expect(subject).to respond_to(:namespace_project_path)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -899,21 +899,87 @@ describe Ci::Build, models: true do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#retryable?' do
|
||||
context 'when build is running' do
|
||||
before do
|
||||
build.run!
|
||||
describe '#cancelable?' do
|
||||
subject { build }
|
||||
|
||||
context 'when build is cancelable' do
|
||||
context 'when build is pending' do
|
||||
it { is_expected.to be_cancelable }
|
||||
end
|
||||
|
||||
it { expect(build).not_to be_retryable }
|
||||
context 'when build is running' do
|
||||
before do
|
||||
build.run!
|
||||
end
|
||||
|
||||
it { is_expected.to be_cancelable }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is finished' do
|
||||
before do
|
||||
build.success!
|
||||
context 'when build is not cancelable' do
|
||||
context 'when build is successful' do
|
||||
before do
|
||||
build.success!
|
||||
end
|
||||
|
||||
it { is_expected.not_to be_cancelable }
|
||||
end
|
||||
|
||||
it { expect(build).to be_retryable }
|
||||
context 'when build is failed' do
|
||||
before do
|
||||
build.drop!
|
||||
end
|
||||
|
||||
it { is_expected.not_to be_cancelable }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#retryable?' do
|
||||
subject { build }
|
||||
|
||||
context 'when build is retryable' do
|
||||
context 'when build is successful' do
|
||||
before do
|
||||
build.success!
|
||||
end
|
||||
|
||||
it { is_expected.to be_retryable }
|
||||
end
|
||||
|
||||
context 'when build is failed' do
|
||||
before do
|
||||
build.drop!
|
||||
end
|
||||
|
||||
it { is_expected.to be_retryable }
|
||||
end
|
||||
|
||||
context 'when build is canceled' do
|
||||
before do
|
||||
build.cancel!
|
||||
end
|
||||
|
||||
it { is_expected.to be_retryable }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is not retryable' do
|
||||
context 'when build is running' do
|
||||
before do
|
||||
build.run!
|
||||
end
|
||||
|
||||
it { is_expected.not_to be_retryable }
|
||||
end
|
||||
|
||||
context 'when build is skipped' do
|
||||
before do
|
||||
build.skip!
|
||||
end
|
||||
|
||||
it { is_expected.not_to be_retryable }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1180,4 +1246,13 @@ describe Ci::Build, models: true do
|
|||
it { is_expected.to eq('review/master') }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#detailed_status' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
it 'returns a detailed status' do
|
||||
expect(build.detailed_status(user))
|
||||
.to be_a Gitlab::Ci::Status::Build::Cancelable
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -442,11 +442,15 @@ describe Ci::Pipeline, models: true do
|
|||
end
|
||||
|
||||
describe '#detailed_status' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
subject { pipeline.detailed_status(user) }
|
||||
|
||||
context 'when pipeline is created' do
|
||||
let(:pipeline) { create(:ci_pipeline, status: :created) }
|
||||
|
||||
it 'returns detailed status for created pipeline' do
|
||||
expect(pipeline.detailed_status.text).to eq 'created'
|
||||
expect(subject.text).to eq 'created'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -454,7 +458,7 @@ describe Ci::Pipeline, models: true do
|
|||
let(:pipeline) { create(:ci_pipeline, status: :pending) }
|
||||
|
||||
it 'returns detailed status for pending pipeline' do
|
||||
expect(pipeline.detailed_status.text).to eq 'pending'
|
||||
expect(subject.text).to eq 'pending'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -462,7 +466,7 @@ describe Ci::Pipeline, models: true do
|
|||
let(:pipeline) { create(:ci_pipeline, status: :running) }
|
||||
|
||||
it 'returns detailed status for running pipeline' do
|
||||
expect(pipeline.detailed_status.text).to eq 'running'
|
||||
expect(subject.text).to eq 'running'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -470,7 +474,7 @@ describe Ci::Pipeline, models: true do
|
|||
let(:pipeline) { create(:ci_pipeline, status: :success) }
|
||||
|
||||
it 'returns detailed status for successful pipeline' do
|
||||
expect(pipeline.detailed_status.text).to eq 'passed'
|
||||
expect(subject.text).to eq 'passed'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -478,7 +482,7 @@ describe Ci::Pipeline, models: true do
|
|||
let(:pipeline) { create(:ci_pipeline, status: :failed) }
|
||||
|
||||
it 'returns detailed status for failed pipeline' do
|
||||
expect(pipeline.detailed_status.text).to eq 'failed'
|
||||
expect(subject.text).to eq 'failed'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -486,7 +490,7 @@ describe Ci::Pipeline, models: true do
|
|||
let(:pipeline) { create(:ci_pipeline, status: :canceled) }
|
||||
|
||||
it 'returns detailed status for canceled pipeline' do
|
||||
expect(pipeline.detailed_status.text).to eq 'canceled'
|
||||
expect(subject.text).to eq 'canceled'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -494,7 +498,7 @@ describe Ci::Pipeline, models: true do
|
|||
let(:pipeline) { create(:ci_pipeline, status: :skipped) }
|
||||
|
||||
it 'returns detailed status for skipped pipeline' do
|
||||
expect(pipeline.detailed_status.text).to eq 'skipped'
|
||||
expect(subject.text).to eq 'skipped'
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -506,7 +510,7 @@ describe Ci::Pipeline, models: true do
|
|||
end
|
||||
|
||||
it 'retruns detailed status for successful pipeline with warnings' do
|
||||
expect(pipeline.detailed_status.label).to eq 'passed with warnings'
|
||||
expect(subject.label).to eq 'passed with warnings'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -68,7 +68,9 @@ describe Ci::Stage, models: true do
|
|||
end
|
||||
|
||||
describe '#detailed_status' do
|
||||
subject { stage.detailed_status }
|
||||
let(:user) { create(:user) }
|
||||
|
||||
subject { stage.detailed_status(user) }
|
||||
|
||||
context 'when build is created' do
|
||||
let!(:stage_build) { create_job(:ci_build, status: :created) }
|
||||
|
|
|
@ -234,4 +234,13 @@ describe CommitStatus, models: true do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#detailed_status' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
it 'returns a detailed status' do
|
||||
expect(commit_status.detailed_status(user))
|
||||
.to be_a Gitlab::Ci::Status::Success
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe GenericCommitStatus, models: true do
|
||||
let(:pipeline) { FactoryGirl.create :ci_pipeline }
|
||||
let(:generic_commit_status) { FactoryGirl.create :generic_commit_status, pipeline: pipeline }
|
||||
let(:pipeline) { create(:ci_pipeline) }
|
||||
|
||||
let(:generic_commit_status) do
|
||||
create(:generic_commit_status, pipeline: pipeline)
|
||||
end
|
||||
|
||||
describe '#context' do
|
||||
subject { generic_commit_status.context }
|
||||
|
@ -17,6 +20,15 @@ describe GenericCommitStatus, models: true do
|
|||
it { is_expected.to eq([:external]) }
|
||||
end
|
||||
|
||||
describe '#detailed_status' do
|
||||
let(:user) { create(:user) }
|
||||
|
||||
it 'returns detailed status object' do
|
||||
expect(generic_commit_status.detailed_status(user))
|
||||
.to be_a Gitlab::Ci::Status::Success
|
||||
end
|
||||
end
|
||||
|
||||
describe 'set_default_values' do
|
||||
before do
|
||||
generic_commit_status.context = nil
|
||||
|
|
|
@ -50,9 +50,8 @@ describe Group, models: true do
|
|||
|
||||
describe 'validations' do
|
||||
it { is_expected.to validate_presence_of :name }
|
||||
it { is_expected.to validate_uniqueness_of(:name) }
|
||||
it { is_expected.to validate_uniqueness_of(:name).scoped_to(:parent_id) }
|
||||
it { is_expected.to validate_presence_of :path }
|
||||
it { is_expected.to validate_uniqueness_of(:path) }
|
||||
it { is_expected.not_to validate_presence_of :owner }
|
||||
end
|
||||
|
||||
|
|
|
@ -6,20 +6,16 @@ describe Namespace, models: true do
|
|||
it { is_expected.to have_many :projects }
|
||||
|
||||
it { is_expected.to validate_presence_of(:name) }
|
||||
it { is_expected.to validate_uniqueness_of(:name) }
|
||||
it { is_expected.to validate_uniqueness_of(:name).scoped_to(:parent_id) }
|
||||
it { is_expected.to validate_length_of(:name).is_at_most(255) }
|
||||
|
||||
it { is_expected.to validate_length_of(:description).is_at_most(255) }
|
||||
|
||||
it { is_expected.to validate_presence_of(:path) }
|
||||
it { is_expected.to validate_uniqueness_of(:path) }
|
||||
it { is_expected.to validate_length_of(:path).is_at_most(255) }
|
||||
|
||||
it { is_expected.to validate_presence_of(:owner) }
|
||||
|
||||
describe "Mass assignment" do
|
||||
end
|
||||
|
||||
describe "Respond to" do
|
||||
it { is_expected.to respond_to(:human_name) }
|
||||
it { is_expected.to respond_to(:to_param) }
|
||||
|
|
|
@ -475,7 +475,7 @@ describe API::Commits, api: true do
|
|||
|
||||
expect(response).to have_http_status(400)
|
||||
expect(json_response['message']).to eq('Sorry, we cannot cherry-pick this commit automatically.
|
||||
It may have already been cherry-pick, or a more recent commit may have updated some of its content.')
|
||||
A cherry-pick may have already been performed with this commit, or a more recent commit may have updated some of its content.')
|
||||
end
|
||||
|
||||
it 'returns 400 if you are not allowed to push to the target branch' do
|
||||
|
|
|
@ -66,7 +66,8 @@ describe Admin::ProjectsController, "routing" do
|
|||
end
|
||||
|
||||
it "to #show" do
|
||||
expect(get("/admin/projects/gitlab")).to route_to('admin/projects#show', namespace_id: 'gitlab')
|
||||
expect(get("/admin/projects/gitlab/gitlab-ce")).to route_to('admin/projects#show', namespace_id: 'gitlab', id: 'gitlab-ce')
|
||||
expect(get("/admin/projects/gitlab/subgroup/gitlab-ce")).to route_to('admin/projects#show', namespace_id: 'gitlab/subgroup', id: 'gitlab-ce')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -119,3 +120,14 @@ describe Admin::HealthCheckController, "routing" do
|
|||
expect(get("/admin/health_check")).to route_to('admin/health_check#show')
|
||||
end
|
||||
end
|
||||
|
||||
describe Admin::GroupsController, "routing" do
|
||||
it "to #index" do
|
||||
expect(get("/admin/groups")).to route_to('admin/groups#index')
|
||||
end
|
||||
|
||||
it "to #show" do
|
||||
expect(get("/admin/groups/gitlab")).to route_to('admin/groups#show', id: 'gitlab')
|
||||
expect(get("/admin/groups/gitlab/subgroup")).to route_to('admin/groups#show', id: 'gitlab/subgroup')
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue