Skip to content
Snippets Groups Projects
Commit cd8b5987 authored by Stan Hu's avatar Stan Hu
Browse files

Merge branch 'ce-to-ee-2018-10-29' into 'master'

CE upstream - 2018-10-29 11:21 UTC

Closes #7760

See merge request gitlab-org/gitlab-ee!8131
parents 6a0e1212 b306a0c7
No related branches found
No related tags found
1 merge request!8131CE upstream - 2018-10-29 11:21 UTC
Pipeline #34772432 passed with warnings
Showing
with 143 additions and 54 deletions
......@@ -58,10 +58,15 @@ export const alternativeTokenKeys = [
export const conditions = [
{
url: 'assignee_id=0',
url: 'assignee_id=None',
tokenKey: 'assignee',
value: 'none',
},
{
url: 'assignee_id=Any',
tokenKey: 'assignee',
value: 'any',
},
{
url: 'milestone_title=No+Milestone',
tokenKey: 'milestone',
......
......@@ -4,12 +4,13 @@ class Dashboard::MilestonesController < Dashboard::ApplicationController
include MilestoneActions
before_action :projects
before_action :groups, only: :index
before_action :milestone, only: [:show, :merge_requests, :participants, :labels]
def index
respond_to do |format|
format.html do
@milestone_states = GlobalMilestone.states_count(@projects)
@milestone_states = Milestone.states_count(@projects.select(:id), @groups.select(:id))
@milestones = Kaminari.paginate_array(milestones).page(params[:page])
end
format.json do
......@@ -42,4 +43,8 @@ def milestone
@milestone = DashboardMilestone.build(@projects, params[:title])
render_404 unless @milestone
end
def groups
@groups ||= GroupsFinder.new(current_user, state_all: true).execute
end
end
......@@ -12,7 +12,7 @@ class Groups::MilestonesController < Groups::ApplicationController
def index
respond_to do |format|
format.html do
@milestone_states = GlobalMilestone.states_count(group_projects, group)
@milestone_states = Milestone.states_count(group_projects, [group])
@milestones = Kaminari.paginate_array(milestones).page(params[:page])
end
format.json do
......
......@@ -22,6 +22,12 @@ class Cluster < ActiveRecord::Base
has_many :cluster_projects, class_name: 'Clusters::Project'
has_many :projects, through: :cluster_projects, class_name: '::Project'
has_many :cluster_groups, class_name: 'Clusters::Group'
has_many :groups, through: :cluster_groups, class_name: '::Group'
has_one :cluster_group, -> { order(id: :desc) }, class_name: 'Clusters::Group'
has_one :group, through: :cluster_group, class_name: '::Group'
# we force autosave to happen when we save `Cluster` model
has_one :provider_gcp, class_name: 'Clusters::Providers::Gcp', autosave: true
......@@ -40,8 +46,12 @@ class Cluster < ActiveRecord::Base
accepts_nested_attributes_for :platform_kubernetes, update_only: true
validates :name, cluster_name: true
validates :cluster_type, presence: true
validate :restrict_modification, on: :update
validate :no_groups, unless: :group_type?
validate :no_projects, unless: :project_type?
delegate :status, to: :provider, allow_nil: true
delegate :status_reason, to: :provider, allow_nil: true
delegate :on_creation?, to: :provider, allow_nil: true
......@@ -52,6 +62,12 @@ class Cluster < ActiveRecord::Base
delegate :available?, to: :application_ingress, prefix: true, allow_nil: true
delegate :available?, to: :application_prometheus, prefix: true, allow_nil: true
enum cluster_type: {
instance_type: 1,
group_type: 2,
project_type: 3
}
enum platform_type: {
kubernetes: 1
}
......@@ -124,5 +140,17 @@ def restrict_modification
true
end
def no_groups
if groups.any?
errors.add(:cluster, 'cannot have groups assigned')
end
end
def no_projects
if projects.any?
errors.add(:cluster, 'cannot have projects assigned')
end
end
end
end
# frozen_string_literal: true
module Clusters
class Group < ActiveRecord::Base
self.table_name = 'cluster_groups'
belongs_to :cluster, class_name: 'Clusters::Cluster'
belongs_to :group, class_name: '::Group'
end
end
......@@ -42,6 +42,7 @@ def cluster_attributes_from_service_template
{
name: 'kubernetes-template',
projects: [self],
cluster_type: :project_type,
provider_type: :user,
platform_type: :kubernetes,
platform_kubernetes_attributes: platform_kubernetes_attributes_from_service_template
......
......@@ -36,50 +36,6 @@ def self.build(projects, title)
new(title, child_milestones)
end
def self.states_count(projects, group = nil)
legacy_group_milestones_count = legacy_group_milestone_states_count(projects)
group_milestones_count = group_milestones_states_count(group)
legacy_group_milestones_count.merge(group_milestones_count) do |k, legacy_group_milestones_count, group_milestones_count|
legacy_group_milestones_count + group_milestones_count
end
end
def self.group_milestones_states_count(group)
return STATE_COUNT_HASH unless group
params = { group_ids: [group.id], state: 'all' }
relation = MilestonesFinder.new(params).execute # rubocop: disable CodeReuse/Finder
grouped_by_state = relation.reorder(nil).group(:state).count
{
opened: grouped_by_state['active'] || 0,
closed: grouped_by_state['closed'] || 0,
all: grouped_by_state.values.sum
}
end
# Counts the legacy group milestones which must be grouped by title
def self.legacy_group_milestone_states_count(projects)
return STATE_COUNT_HASH unless projects
params = { project_ids: projects.map(&:id), state: 'all' }
relation = MilestonesFinder.new(params).execute # rubocop: disable CodeReuse/Finder
project_milestones_by_state_and_title = relation.reorder(nil).group(:state, :title).count
opened = count_by_state(project_milestones_by_state_and_title, 'active')
closed = count_by_state(project_milestones_by_state_and_title, 'closed')
all = project_milestones_by_state_and_title.map { |(_, title), _| title }.uniq.count
{
opened: opened,
closed: closed,
all: all
}
end
def self.count_by_state(milestones_by_state_and_title, state)
milestones_by_state_and_title.count do |(milestone_state, _), _|
milestone_state == state
......
......@@ -43,6 +43,9 @@ class Group < Namespace
has_many :boards
has_many :badges, class_name: 'GroupBadge'
has_many :cluster_groups, class_name: 'Clusters::Group'
has_many :clusters, through: :cluster_groups, class_name: 'Clusters::Cluster'
has_many :todos
accepts_nested_attributes_for :variables, allow_destroy: true
......
......@@ -174,6 +174,22 @@ def self.sort_by_attribute(method)
sorted.with_order_id_desc
end
def self.states_count(projects, groups = nil)
return STATE_COUNT_HASH unless projects || groups
counts = Milestone
.for_projects_and_groups(projects&.map(&:id), groups&.map(&:id))
.reorder(nil)
.group(:state)
.count
{
opened: counts['active'] || 0,
closed: counts['closed'] || 0,
all: counts.values.sum
}
end
##
# Returns the String necessary to reference this Milestone in Markdown. Group
# milestones only support name references, and do not support cross-project
......
......@@ -11,9 +11,9 @@ def initialize(user = nil, params = {})
end
def execute(project:, access_token: nil)
raise ArgumentError.new(_('Instance does not support multiple Kubernetes clusters')) unless can_create_cluster?(project)
raise ArgumentError, _('Instance does not support multiple Kubernetes clusters') unless can_create_cluster?(project)
cluster_params = params.merge(user: current_user, projects: [project])
cluster_params = params.merge(user: current_user, cluster_type: :project_type, projects: [project])
cluster_params[:provider_gcp_attributes].try do |provider|
provider[:access_token] = access_token
end
......
......@@ -61,7 +61,10 @@
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'none' } }
%button.btn.btn-link{ type: 'button' }
= _('No Assignee')
= _('None')
%li.filter-dropdown-item{ data: { value: 'any' } }
%button.btn.btn-link{ type: 'button' }
= _('Any')
%li.divider.droplab-item-ignore
- if current_user
= render 'shared/issuable/user_dropdown_item',
......@@ -81,7 +84,7 @@
%li.filter-dropdown-item{ data: { value: 'upcoming' } }
%button.btn.btn-link{ type: 'button' }
= _('Upcoming')
%li.filter-dropdown-item{ 'data-value' => 'started' }
%li.filter-dropdown-item{ data: { value: 'started' } }
%button.btn.btn-link{ type: 'button' }
= _('Started')
%li.divider.droplab-item-ignore
......
---
title: Adds model and migrations to enable group level clusters
merge_request: 22307
author:
type: other
---
title: Add None/Any option for assignee_id in search bar
merge_request: 22599
author: Heinrich Lee Yu
type: added
---
title: Fixing count on Milestones
merge_request: 21446
author:
type: fixed
......@@ -87,6 +87,7 @@
get 'ide' => 'ide#index'
get 'ide/*vueroute' => 'ide#index', format: false
draw :operations
draw :instance_statistics
end
......
# frozen_string_literal: true
class CreateClusterGroups < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def change
create_table :cluster_groups do |t|
t.references :cluster, null: false, foreign_key: { on_delete: :cascade }
t.references :group, null: false, index: true
t.index [:cluster_id, :group_id], unique: true
t.foreign_key :namespaces, column: :group_id, on_delete: :cascade
end
end
end
# frozen_string_literal: true
class AddClusterTypeToClusters < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
PROJECT_CLUSTER_TYPE = 3
disable_ddl_transaction!
def up
add_column_with_default(:clusters, :cluster_type, :smallint, default: PROJECT_CLUSTER_TYPE)
end
def down
remove_column(:clusters, :cluster_type)
end
end
......@@ -717,6 +717,14 @@
add_index "ci_variables", ["project_id", "key", "environment_scope"], name: "index_ci_variables_on_project_id_and_key_and_environment_scope", unique: true, using: :btree
create_table "cluster_groups", force: :cascade do |t|
t.integer "cluster_id", null: false
t.integer "group_id", null: false
end
add_index "cluster_groups", ["cluster_id", "group_id"], name: "index_cluster_groups_on_cluster_id_and_group_id", unique: true, using: :btree
add_index "cluster_groups", ["group_id"], name: "index_cluster_groups_on_group_id", using: :btree
create_table "cluster_platforms_kubernetes", force: :cascade do |t|
t.integer "cluster_id", null: false
t.datetime "created_at", null: false
......@@ -772,6 +780,7 @@
t.boolean "enabled", default: true
t.string "name", null: false
t.string "environment_scope", default: "*", null: false
t.integer "cluster_type", limit: 2, default: 3, null: false
end
add_index "clusters", ["enabled"], name: "index_clusters_on_enabled", using: :btree
......@@ -3225,6 +3234,8 @@
add_foreign_key "ci_triggers", "projects", name: "fk_e3e63f966e", on_delete: :cascade
add_foreign_key "ci_triggers", "users", column: "owner_id", name: "fk_e8e10d1964", on_delete: :cascade
add_foreign_key "ci_variables", "projects", name: "fk_ada5eb64b3", on_delete: :cascade
add_foreign_key "cluster_groups", "clusters", on_delete: :cascade
add_foreign_key "cluster_groups", "namespaces", column: "group_id", on_delete: :cascade
add_foreign_key "cluster_platforms_kubernetes", "clusters", on_delete: :cascade
add_foreign_key "cluster_projects", "clusters", on_delete: :cascade
add_foreign_key "cluster_projects", "projects", on_delete: :cascade
......
......@@ -134,7 +134,7 @@ Parameters:
"description": "Amazing release. Wow"
},
"name": "v1.0.0",
"target: "2695effb5807a22ff3d138d593fd856244e155e7",
"target": "2695effb5807a22ff3d138d593fd856244e155e7",
"message": null
}
```
......
......@@ -176,8 +176,8 @@ Clicking on the current board name in the upper left corner will reveal a
menu from where you can create another Issue Board and rename or delete the
existing one.
Clicking on the main issue board link will take you to the last board
you visited.
When you're revisiting an issue board in a project or group with multiple boards,
GitLab will automatically load the last board you visited.
NOTE: **Note:**
The Multiple Issue Boards feature is available for
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment