diff options
58 files changed, 324 insertions, 264 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index a1c928aedf3..56ac809b548 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,19 @@ documentation](doc/development/changelog.md) for instructions on adding your own entry. +## 11.6.2 (2019-01-02) + +### Fixed (7 changes) + +- Hide cluster features that don't work yet with Group Clusters. !23935 +- Fix a 500 error that could occur until all migrations are done. !23939 +- Fix missing Git clone button when protocol restriction setting enabled. !24015 +- Fix clone dropdown parent inheritance issues in HAML. !24029 +- Fix content-disposition in blobs and files API endpoint. !24078 +- Fixed markdown toolbar buttons. +- Adjust line-height of blame view line numbers. + + ## 11.6.1 (2018-12-28) ### Security (15 changes) @@ -127,7 +127,7 @@ gem 'asciidoctor-plantuml', '0.0.8' gem 'rouge', '~> 3.1' gem 'truncato', '~> 0.7.9' gem 'bootstrap_form', '~> 2.7.0' -gem 'nokogiri', '~> 1.8.4' +gem 'nokogiri', '~> 1.8.5' gem 'escape_utils', '~> 1.1' # Calendar rendering @@ -322,7 +322,7 @@ end group :development, :test do gem 'bootsnap', '~> 1.3' gem 'bullet', '~> 5.5.0', require: !!ENV['ENABLE_BULLET'] - gem 'pry-byebug', '~> 3.4.1', platform: :mri + gem 'pry-byebug', '~> 3.5.1', platform: :mri gem 'pry-rails', '~> 0.3.4' gem 'awesome_print', require: false @@ -342,8 +342,8 @@ group :development, :test do # Generate Fake data gem 'ffaker', '~> 2.10' - gem 'capybara', '~> 2.15' - gem 'capybara-screenshot', '~> 1.0.0' + gem 'capybara', '~> 2.16.1' + gem 'capybara-screenshot', '~> 1.0.18' gem 'selenium-webdriver', '~> 3.12' gem 'spring', '~> 2.0.0' diff --git a/Gemfile.lock b/Gemfile.lock index 1f7f58d59e0..78cf4d19078 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -97,16 +97,16 @@ GEM bundler-audit (0.5.0) bundler (~> 1.2) thor (~> 0.18) - byebug (9.0.6) - capybara (2.15.1) + byebug (9.1.0) + capybara (2.16.1) addressable mini_mime (>= 0.1.3) nokogiri (>= 1.3.3) rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (~> 2.0) - capybara-screenshot (1.0.14) - capybara (>= 1.0, < 3) + capybara-screenshot (1.0.22) + capybara (>= 1.0, < 4) launchy carrierwave (1.3.0) activemodel (>= 4.0.0) @@ -595,8 +595,8 @@ GEM pry (0.11.3) coderay (~> 1.1.0) method_source (~> 0.9.0) - pry-byebug (3.4.3) - byebug (>= 9.0, < 9.1) + pry-byebug (3.5.1) + byebug (~> 9.1) pry (~> 0.10) pry-rails (0.3.6) pry (>= 0.10.4) @@ -963,8 +963,8 @@ DEPENDENCIES browser (~> 2.5) bullet (~> 5.5.0) bundler-audit (~> 0.5.0) - capybara (~> 2.15) - capybara-screenshot (~> 1.0.0) + capybara (~> 2.16.1) + capybara-screenshot (~> 1.0.18) carrierwave (~> 1.3) charlock_holmes (~> 0.7.5) chronic (~> 0.10.2) @@ -1059,7 +1059,7 @@ DEPENDENCIES nakayoshi_fork (~> 0.0.4) net-ldap net-ssh (~> 5.0) - nokogiri (~> 1.8.4) + nokogiri (~> 1.8.5) oauth2 (~> 1.4) octokit (~> 4.9) omniauth (~> 1.8) @@ -1087,7 +1087,7 @@ DEPENDENCIES pg (~> 0.18.2) premailer-rails (~> 1.9.7) prometheus-client-mmap (~> 0.9.4) - pry-byebug (~> 3.4.1) + pry-byebug (~> 3.5.1) pry-rails (~> 0.3.4) puma (~> 3.12) puma_worker_killer @@ -1171,4 +1171,4 @@ DEPENDENCIES wikicloth (= 0.8.1) BUNDLED WITH - 1.17.1 + 1.17.3 diff --git a/app/assets/stylesheets/framework/issue_box.scss b/app/assets/stylesheets/framework/issue_box.scss index a66604e56ff..e51f230a680 100644 --- a/app/assets/stylesheets/framework/issue_box.scss +++ b/app/assets/stylesheets/framework/issue_box.scss @@ -45,9 +45,4 @@ &.status-box-upcoming { background: $gl-text-color-secondary; } - - &.status-box-milestone { - color: $gl-text-color; - background: $gray-darker; - } } diff --git a/app/assets/stylesheets/pages/milestone.scss b/app/assets/stylesheets/pages/milestone.scss index 1e92582d6d9..94bf32945fc 100644 --- a/app/assets/stylesheets/pages/milestone.scss +++ b/app/assets/stylesheets/pages/milestone.scss @@ -1,3 +1,5 @@ +$status-box-line-height: 26px; + .issues-sortable-list .str-truncated { max-width: 90%; } @@ -38,6 +40,7 @@ font-size: $tooltip-font-size; margin-top: 0; margin-right: $gl-padding-4; + line-height: $status-box-line-height; @include media-breakpoint-down(xs) { line-height: unset; diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 8f683ca06ad..8f267eccc8a 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -77,7 +77,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController def reset_health_check_token @application_setting.reset_health_check_access_token! flash[:notice] = 'New health check access token has been generated!' - redirect_to :back + redirect_back_or_default end def clear_repository_check_states diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 140a625d333..a8fc848c879 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -76,7 +76,7 @@ class ApplicationController < ActionController::Base end def redirect_back_or_default(default: root_path, options: {}) - redirect_to request.referer.present? ? :back : default, options + redirect_back(fallback_location: default, **options) end def not_found diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb index b42116b0f36..868deea3f01 100644 --- a/app/controllers/groups/milestones_controller.rb +++ b/app/controllers/groups/milestones_controller.rb @@ -43,14 +43,7 @@ class Groups::MilestonesController < Groups::ApplicationController def update # Keep this compatible with legacy group milestones where we have to update # all projects milestones states at once. - if @milestone.legacy_group_milestone? - update_params = milestone_params.select { |key| key == "state_event" } - milestones = @milestone.milestones - else - update_params = milestone_params - milestones = [@milestone] - end - + milestones, update_params = get_milestones_for_update milestones.each do |milestone| Milestones::UpdateService.new(milestone.parent, current_user, update_params).execute(milestone) end @@ -71,6 +64,14 @@ class Groups::MilestonesController < Groups::ApplicationController private + def get_milestones_for_update + if @milestone.legacy_group_milestone? + [@milestone.milestones, legacy_milestone_params] + else + [[@milestone], milestone_params] + end + end + def authorize_admin_milestones! return render_404 unless can?(current_user, :admin_milestone, group) end @@ -79,6 +80,10 @@ class Groups::MilestonesController < Groups::ApplicationController params.require(:milestone).permit(:title, :description, :start_date, :due_date, :state_event) end + def legacy_milestone_params + params.require(:milestone).permit(:state_event) + end + def milestone_path if @milestone.legacy_group_milestone? group_milestone_path(group, @milestone.safe_title, title: @milestone.title) diff --git a/app/controllers/sherlock/transactions_controller.rb b/app/controllers/sherlock/transactions_controller.rb index 46e382e594e..8d1847507cc 100644 --- a/app/controllers/sherlock/transactions_controller.rb +++ b/app/controllers/sherlock/transactions_controller.rb @@ -15,7 +15,7 @@ module Sherlock def destroy_all Gitlab::Sherlock.collection.clear - redirect_to :back, status: :found + redirect_back_or_default(options: { status: :found }) end end end diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb index 327b69e5110..50aec83b867 100644 --- a/app/helpers/milestones_helper.rb +++ b/app/helpers/milestones_helper.rb @@ -231,12 +231,15 @@ module MilestonesHelper end end - def group_or_dashboard_milestone_path(milestone) - if milestone.group_milestone? - group_milestone_path(milestone.group, milestone.iid, milestone: { title: milestone.title }) - else - dashboard_milestone_path(milestone.safe_title, title: milestone.title) - end + def group_or_project_milestone_path(milestone) + params = + if milestone.group_milestone? + { milestone: { title: milestone.title } } + else + { title: milestone.title } + end + + milestone_path(milestone.milestone, params) end def can_admin_project_milestones? diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index b128a254b96..aeb35538d67 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -221,6 +221,10 @@ module Ci next unless build.project build.deployment&.drop + end + + after_transition any => [:failed] do |build| + next unless build.project if build.retry_failure? begin diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb index 8f8790585a3..7799f069742 100644 --- a/app/models/clusters/applications/ingress.rb +++ b/app/models/clusters/applications/ingress.rb @@ -23,7 +23,7 @@ module Clusters FETCH_IP_ADDRESS_DELAY = 30.seconds state_machine :status do - before_transition any => [:installed] do |application| + after_transition any => [:installed] do |application| application.run_after_commit do ClusterWaitForIngressIpAddressWorker.perform_in( FETCH_IP_ADDRESS_DELAY, application.name, application.id) diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb index 0c72d7d8340..5ac152278da 100644 --- a/app/models/clusters/applications/knative.rb +++ b/app/models/clusters/applications/knative.rb @@ -20,7 +20,7 @@ module Clusters self.reactive_cache_key = ->(knative) { [knative.class.model_name.singular, knative.id] } state_machine :status do - before_transition any => [:installed] do |application| + after_transition any => [:installed] do |application| application.run_after_commit do ClusterWaitForIngressIpAddressWorker.perform_in( FETCH_IP_ADDRESS_DELAY, application.name, application.id) diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb index e44a069b730..055ffe04646 100644 --- a/app/models/concerns/milestoneish.rb +++ b/app/models/concerns/milestoneish.rb @@ -42,7 +42,7 @@ module Milestoneish def issues_visible_to_user(user) memoize_per_user(user, :issues_visible_to_user) do IssuesFinder.new(user, issues_finder_params) - .execute.preload(:assignees).where(milestone_id: milestoneish_ids) + .execute.preload(:assignees).where(milestone_id: milestoneish_id) end end diff --git a/app/models/dashboard_group_milestone.rb b/app/models/dashboard_group_milestone.rb index ad0bb55f0a7..9bcc95e35a5 100644 --- a/app/models/dashboard_group_milestone.rb +++ b/app/models/dashboard_group_milestone.rb @@ -6,7 +6,7 @@ class DashboardGroupMilestone < GlobalMilestone attr_reader :group_name def initialize(milestone) - super(milestone.title, Array(milestone)) + super @group_name = milestone.group.full_name end @@ -18,22 +18,4 @@ class DashboardGroupMilestone < GlobalMilestone .active .map { |m| new(m) } end - - override :group_milestone? - def group_milestone? - @first_milestone.group_milestone? - end - - override :milestoneish_ids - def milestoneish_ids - milestones.map(&:id) - end - - def group - @first_milestone.group - end - - def iid - @first_milestone.iid - end end diff --git a/app/models/dashboard_milestone.rb b/app/models/dashboard_milestone.rb index 96bc8090b81..9b377b70e5b 100644 --- a/app/models/dashboard_milestone.rb +++ b/app/models/dashboard_milestone.rb @@ -1,11 +1,15 @@ # frozen_string_literal: true class DashboardMilestone < GlobalMilestone - def issues_finder_params - { authorized_only: true } + attr_reader :project_name + + def initialize(milestone) + super + + @project_name = milestone.project.full_name end - def dashboard_milestone? + def project_milestone? true end end diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb index 085ffd16c6a..4e82f3fed27 100644 --- a/app/models/global_milestone.rb +++ b/app/models/global_milestone.rb @@ -3,69 +3,78 @@ class GlobalMilestone include Milestoneish - EPOCH = DateTime.parse('1970-01-01') STATE_COUNT_HASH = { opened: 0, closed: 0, all: 0 }.freeze - attr_accessor :title, :milestones + attr_reader :milestone alias_attribute :name, :title + delegate :title, :state, :due_date, :start_date, :participants, :project, :group, :expires_at, :closed?, :iid, :group_milestone?, :safe_title, :milestoneish_id, to: :milestone + + def to_hash + { + name: title, + title: title, + group_name: group&.full_name, + project_name: project&.full_name + } + end + def for_display - @first_milestone + @milestone end def self.build_collection(projects, params) - params = - { project_ids: projects.map(&:id), state: params[:state] } - - child_milestones = MilestonesFinder.new(params).execute # rubocop: disable CodeReuse/Finder - - milestones = child_milestones.select(:id, :title).group_by(&:title).map do |title, grouped| - milestones_relation = Milestone.where(id: grouped.map(&:id)) - new(title, milestones_relation) - end + items = Milestone.of_projects(projects) + .reorder_by_due_date_asc + .order_by_name_asc - milestones.sort_by { |milestone| milestone.due_date || EPOCH } + Milestone.filter_by_state(items, params[:state]).map { |m| new(m) } end + # necessary for legacy milestones def self.build(projects, title) - child_milestones = Milestone.of_projects(projects).where(title: title) - return if child_milestones.blank? + milestones = Milestone.of_projects(projects).where(title: title) + return if milestones.blank? - new(title, child_milestones) + new(milestones.first) end - def self.count_by_state(milestones_by_state_and_title, state) - milestones_by_state_and_title.count do |(milestone_state, _), _| - milestone_state == state + 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 - private_class_method :count_by_state - def initialize(title, milestones) - @title = title - @name = title - @milestones = milestones - @first_milestone = milestones.find {|m| m.description.present? } || milestones.first - end + def self.group_milestones_states_count(group) + return STATE_COUNT_HASH unless group - def milestoneish_ids - milestones.select(:id) - end + counts_by_state = Milestone.of_groups(group).count_by_state - def safe_title - @title.to_slug.normalize.to_s + { + opened: counts_by_state['active'] || 0, + closed: counts_by_state['closed'] || 0, + all: counts_by_state.values.sum + } end - def projects - @projects ||= Project.for_milestones(milestoneish_ids) - end + def self.legacy_group_milestone_states_count(projects) + return STATE_COUNT_HASH unless projects - def state - milestones.each do |milestone| - return 'active' if milestone.state != 'closed' - end + # We need to reorder(nil) on the projects, because the controller passes them in sorted. + relation = Milestone.of_projects(projects.reorder(nil)).count_by_state - 'closed' + { + opened: relation['active'] || 0, + closed: relation['closed'] || 0, + all: relation.values.sum + } + end + + def initialize(milestone) + @milestone = milestone end def active? @@ -77,37 +86,14 @@ class GlobalMilestone end def issues - @issues ||= Issue.of_milestones(milestoneish_ids).includes(:project, :assignees, :labels) + @issues ||= Issue.of_milestones(milestone).includes(:project, :assignees, :labels) end def merge_requests - @merge_requests ||= MergeRequest.of_milestones(milestoneish_ids).includes(:target_project, :assignee, :labels) - end - - def participants - @participants ||= milestones.map(&:participants).flatten.uniq + @merge_requests ||= MergeRequest.of_milestones(milestone).includes(:target_project, :assignee, :labels) end def labels - @labels ||= GlobalLabel.build_collection(milestones.includes(:labels).map(&:labels).flatten) - .sort_by!(&:title) - end - - def due_date - return @due_date if defined?(@due_date) - - @due_date = - if @milestones.all? { |x| x.due_date == @milestones.first.due_date } - @milestones.first.due_date - end - end - - def start_date - return @start_date if defined?(@start_date) - - @start_date = - if @milestones.all? { |x| x.start_date == @milestones.first.start_date } - @milestones.first.start_date - end + @labels ||= GlobalLabel.build_collection(milestone.labels).sort_by!(&:title) end end diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb index 9dfaebacc83..a58537de319 100644 --- a/app/models/group_milestone.rb +++ b/app/models/group_milestone.rb @@ -1,18 +1,35 @@ # frozen_string_literal: true # Group Milestones are milestones that can be shared among many projects within the same group class GroupMilestone < GlobalMilestone - attr_accessor :group + attr_reader :group, :milestones def self.build_collection(group, projects, params) - super(projects, params).each do |milestone| - milestone.group = group + params = + { state: params[:state] } + + project_milestones = Milestone.of_projects(projects) + child_milestones = Milestone.filter_by_state(project_milestones, params[:state]) + grouped_milestones = child_milestones.group_by(&:title) + + grouped_milestones.map do |title, grouped| + new(title, grouped, group) end end def self.build(group, projects, title) - super(projects, title).tap do |milestone| - milestone&.group = group - end + child_milestones = Milestone.of_projects(projects).where(title: title) + return if child_milestones.blank? + + new(title, child_milestones, group) + end + + def initialize(title, milestones, group) + @milestones = milestones + @group = group + end + + def milestone + @milestone ||= milestones.find { |m| m.description.present? } || milestones.first end def issues_finder_params diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index b937bef100b..6092c56b925 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -105,7 +105,9 @@ class MergeRequest < ActiveRecord::Base before_transition any => :opened do |merge_request| merge_request.merge_jid = nil + end + after_transition any => :opened do |merge_request| merge_request.run_after_commit do UpdateHeadPipelineForMergeRequestWorker.perform_async(merge_request.id) end diff --git a/app/models/milestone.rb b/app/models/milestone.rb index 6dc0fca68e6..f55c39d9912 100644 --- a/app/models/milestone.rb +++ b/app/models/milestone.rb @@ -94,6 +94,10 @@ class Milestone < ActiveRecord::Base end end + def count_by_state + reorder(nil).group(:state).count + end + def predefined?(milestone) milestone == Any || milestone == None || @@ -215,7 +219,7 @@ class Milestone < ActiveRecord::Base self.class.reference_prefix + self.title end - def milestoneish_ids + def milestoneish_id id end diff --git a/app/models/project_services/kubernetes_service.rb b/app/models/project_services/kubernetes_service.rb index b801fd84a07..f69edd60003 100644 --- a/app/models/project_services/kubernetes_service.rb +++ b/app/models/project_services/kubernetes_service.rb @@ -53,7 +53,7 @@ class KubernetesService < DeploymentService end def description - 'Kubernetes / Openshift integration' + 'Kubernetes / OpenShift integration' end def help diff --git a/app/views/dashboard/milestones/_milestone.html.haml b/app/views/dashboard/milestones/_milestone.html.haml index b876d6fd1f3..89212eb6bf9 100644 --- a/app/views/dashboard/milestones/_milestone.html.haml +++ b/app/views/dashboard/milestones/_milestone.html.haml @@ -1,5 +1,5 @@ = render 'shared/milestones/milestone', - milestone_path: group_or_dashboard_milestone_path(milestone), + milestone_path: group_or_project_milestone_path(milestone), issues_path: issues_dashboard_path(milestone_title: milestone.title), merge_requests_path: merge_requests_dashboard_path(milestone_title: milestone.title), milestone: milestone, diff --git a/app/views/projects/services/prometheus/_metrics.html.haml b/app/views/projects/services/prometheus/_metrics.html.haml index 597c029f755..a1d74b91002 100644 --- a/app/views/projects/services/prometheus/_metrics.html.haml +++ b/app/views/projects/services/prometheus/_metrics.html.haml @@ -1,6 +1,6 @@ - project = local_assigns.fetch(:project) -.card.js-panel-monitored-metrics{ data: { active_metrics: active_common_project_prometheus_metrics_path(project, :json), metrics_help_path: help_page_path('user/project/integrations/prometheus_library/metrics') } } +.card.js-panel-monitored-metrics{ data: { active_metrics: active_common_project_prometheus_metrics_path(project, :json), metrics_help_path: help_page_path('user/project/integrations/prometheus_library/index') } } .card-header = s_('PrometheusService|Common metrics') %span.badge.badge-pill.js-monitored-count 0 diff --git a/app/views/projects/services/prometheus/_show.html.haml b/app/views/projects/services/prometheus/_show.html.haml index 1d0b0265bb7..9d4574c4590 100644 --- a/app/views/projects/services/prometheus/_show.html.haml +++ b/app/views/projects/services/prometheus/_show.html.haml @@ -4,7 +4,7 @@ = s_('PrometheusService|Metrics') %p = s_('PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters.') - = link_to s_('PrometheusService|More information'), help_page_path('user/project/integrations/prometheus_library/metrics'), target: '_blank', rel: "noopener noreferrer" + = link_to s_('PrometheusService|More information'), help_page_path('user/project/integrations/prometheus_library/index'), target: '_blank', rel: "noopener noreferrer" .col-lg-9 = render 'projects/services/prometheus/metrics', project: @project diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml index ed7fefba56d..40b8374848e 100644 --- a/app/views/shared/milestones/_milestone.html.haml +++ b/app/views/shared/milestones/_milestone.html.haml @@ -1,5 +1,5 @@ - dashboard = local_assigns[:dashboard] -- custom_dom_id = dom_id(milestone.try(:milestones) ? milestone.milestones.first : milestone) +- custom_dom_id = dom_id(milestone.try(:milestone) ? milestone.milestone : milestone) - milestone_type = milestone.group_milestone? ? 'Group Milestone' : 'Project Milestone' %li{ class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: custom_dom_id } @@ -21,10 +21,12 @@ = milestone.group.full_name - if milestone.legacy_group_milestone? .projects - - milestone.milestones.each do |milestone| - = link_to milestone_path(milestone) do - %span.label-badge.label-badge-blue.d-inline-block.append-bottom-5 - = dashboard ? milestone.project.full_name : milestone.project.name + - link_to milestone_path(milestone.milestone) do + %span.label-badge.label-badge-blue.d-inline-block.append-bottom-5 + = dashboard ? milestone.project.full_name : milestone.project.name + - if milestone.project + .label-badge.label-badge-gray.d-inline-block + = milestone.project.full_name .col-sm-4.milestone-progress = milestone_progress_bar(milestone) @@ -58,5 +60,5 @@ - else = link_to 'Close Milestone', group_milestone_route(milestone, {state_event: :close }), method: :put, class: "btn btn-sm btn-grouped btn-close" - if dashboard - .status-box.status-box-milestone + .label-badge.label-badge-gray = milestone_type diff --git a/app/views/shared/milestones/_top.html.haml b/app/views/shared/milestones/_top.html.haml index 0499b04a482..55b1c14022f 100644 --- a/app/views/shared/milestones/_top.html.haml +++ b/app/views/shared/milestones/_top.html.haml @@ -62,20 +62,19 @@ %th Open issues %th State %th Due date - - milestone.milestones.each do |ms| %tr %td - - project_name = group ? ms.project.name : ms.project.full_name - = link_to project_name, project_milestone_path(ms.project, ms) + - project_name = group ? milestone.project.name : milestone.project.full_name + = link_to project_name, milestone_path(milestone.milestone) %td - = ms.issues_visible_to_user(current_user).opened.count + = milestone.milestone.issues_visible_to_user(current_user).opened.count %td - - if ms.closed? + - if milestone.closed? Closed - else Open %td - = ms.expires_at + = milestone.expires_at - elsif milestone.group_milestone? %br View diff --git a/changelogs/unreleased/51668-fix-line-numbers.yml b/changelogs/unreleased/51668-fix-line-numbers.yml deleted file mode 100644 index ac6e45e3cc7..00000000000 --- a/changelogs/unreleased/51668-fix-line-numbers.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Adjust line-height of blame view line numbers -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/54953-fix-commit_email_hostname-accessor-in-fake_application_settings.yml b/changelogs/unreleased/54953-fix-commit_email_hostname-accessor-in-fake_application_settings.yml deleted file mode 100644 index 623b3a7319c..00000000000 --- a/changelogs/unreleased/54953-fix-commit_email_hostname-accessor-in-fake_application_settings.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix a 500 error that could occur until all migrations are done -merge_request: 23939 -author: -type: fixed diff --git a/changelogs/unreleased/55103-hide-group-cluster-features.yml b/changelogs/unreleased/55103-hide-group-cluster-features.yml deleted file mode 100644 index fbe780d6f01..00000000000 --- a/changelogs/unreleased/55103-hide-group-cluster-features.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Hide cluster features that don't work yet with Group Clusters -merge_request: 23935 -author: -type: fixed diff --git a/changelogs/unreleased/55836-docs-fix-navigation-style-in-docs.yml b/changelogs/unreleased/55836-docs-fix-navigation-style-in-docs.yml new file mode 100644 index 00000000000..2ac3599175b --- /dev/null +++ b/changelogs/unreleased/55836-docs-fix-navigation-style-in-docs.yml @@ -0,0 +1,5 @@ +--- +title: Fix navigation style in docs +merge_request: 24090 +author: Takuya Noguchi +type: other diff --git a/changelogs/unreleased/ccr-49289_milestone_link.yml b/changelogs/unreleased/ccr-49289_milestone_link.yml new file mode 100644 index 00000000000..14c09752a24 --- /dev/null +++ b/changelogs/unreleased/ccr-49289_milestone_link.yml @@ -0,0 +1,5 @@ +--- +title: Add project milestone link +merge_request: 22552 +author: +type: added diff --git a/changelogs/unreleased/deprecated-insert-sql.yml b/changelogs/unreleased/deprecated-insert-sql.yml new file mode 100644 index 00000000000..ad21fbd9dde --- /dev/null +++ b/changelogs/unreleased/deprecated-insert-sql.yml @@ -0,0 +1,5 @@ +--- +title: 'Fix deprecation: insert_sql is deprecated and will be removed' +merge_request: 23944 +author: Jasper Maes +type: other diff --git a/changelogs/unreleased/deprecated-redirect-back.yml b/changelogs/unreleased/deprecated-redirect-back.yml new file mode 100644 index 00000000000..7fc567fbdb5 --- /dev/null +++ b/changelogs/unreleased/deprecated-redirect-back.yml @@ -0,0 +1,5 @@ +--- +title: 'Fix deprecation: redirect_to :back is deprecated' +merge_request: 23943 +author: Jasper Maes +type: other diff --git a/changelogs/unreleased/fj-55781-fix-api-blob-content-disposition.yml b/changelogs/unreleased/fj-55781-fix-api-blob-content-disposition.yml deleted file mode 100644 index 2e1d9889b22..00000000000 --- a/changelogs/unreleased/fj-55781-fix-api-blob-content-disposition.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix content-disposition in blobs and files API endpoint -merge_request: 24078 -author: -type: fixed diff --git a/changelogs/unreleased/markdown-toolbar-btn-fix.yml b/changelogs/unreleased/markdown-toolbar-btn-fix.yml deleted file mode 100644 index eefb4d19f86..00000000000 --- a/changelogs/unreleased/markdown-toolbar-btn-fix.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fixed markdown toolbar buttons -merge_request: -author: -type: fixed diff --git a/changelogs/unreleased/sh-fix-clone-geo-dropdown.yml b/changelogs/unreleased/sh-fix-clone-geo-dropdown.yml deleted file mode 100644 index 1c0cbdc3a2c..00000000000 --- a/changelogs/unreleased/sh-fix-clone-geo-dropdown.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix clone dropdown parent inheritance issues in HAML -merge_request: 24029 -author: -type: fixed diff --git a/changelogs/unreleased/sh-fix-http-clone-panel.yml b/changelogs/unreleased/sh-fix-http-clone-panel.yml deleted file mode 100644 index ab220bd5076..00000000000 --- a/changelogs/unreleased/sh-fix-http-clone-panel.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Fix missing Git clone button when protocol restriction setting enabled -merge_request: 24015 -author: -type: fixed diff --git a/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb b/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb index 90d869a8c10..8de8b3bcc2e 100644 --- a/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb +++ b/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb @@ -46,7 +46,7 @@ class CreateMissingNamespaceForInternalUsers < ActiveRecord::Migration[4.2] end insert_query = "INSERT INTO namespaces(owner_id, path, name, created_at, updated_at) VALUES(#{user_id}, '#{path}', '#{path}', NOW(), NOW())" - namespace_id = connection.insert_sql(insert_query) + namespace_id = connection.insert(insert_query) create_route(namespace_id) end diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md index a1ea78b64bd..25ae535d1ec 100644 --- a/doc/administration/job_artifacts.md +++ b/doc/administration/job_artifacts.md @@ -165,12 +165,6 @@ _The artifacts are stored by default in gitlab-rake gitlab:artifacts:migrate ``` - Currently this has to be executed manually and it will allow you to - migrate the existing artifacts to the object storage, but all new - artifacts will still be stored on the local disk. In the future - you will be given an option to define a default storage artifacts for all - new files. - --- **In installations from source:** @@ -201,12 +195,6 @@ _The artifacts are stored by default in sudo -u git -H bundle exec rake gitlab:artifacts:migrate RAILS_ENV=production ``` - Currently this has to be executed manually and it will allow you to - migrate the existing artifacts to the object storage, but all new - artifacts will still be stored on the local disk. In the future - you will be given an option to define a default storage artifacts for all - new files. - ## Expiring artifacts If an expiry date is used for the artifacts, they are marked for deletion diff --git a/doc/administration/monitoring/performance/request_profiling.md b/doc/administration/monitoring/performance/request_profiling.md index dfd9be3d04c..726882fbb87 100644 --- a/doc/administration/monitoring/performance/request_profiling.md +++ b/doc/administration/monitoring/performance/request_profiling.md @@ -2,14 +2,14 @@ ## Procedure -1. Grab the profiling token from `Monitoring > Requests Profiles` admin page +1. Grab the profiling token from **Monitoring > Requests Profiles** admin page (highlighted in a blue in the image below). ![Profile token](img/request_profiling_token.png) 1. Pass the header `X-Profile-Token: <token>` to the request you want to profile. You can use: - Browser extensions. For example, [ModHeader](https://chrome.google.com/webstore/detail/modheader/idgpnmonknjnojddfkpgkljpfnnfcklj) Chrome extension. - `curl`. For example, `curl --header 'X-Profile-Token: <token>' https://gitlab.example.com/group/project`. 1. Once request is finished (which will take a little longer than usual), you can - view the profiling output from `Monitoring > Requests Profiles` admin page. + view the profiling output from **Monitoring > Requests Profiles** admin page. ![Profiling output](img/request_profile_result.png) ## Cleaning up diff --git a/doc/api/services.md b/doc/api/services.md index f122bac6f1f..c4edaa17815 100644 --- a/doc/api/services.md +++ b/doc/api/services.md @@ -573,7 +573,7 @@ DELETE /projects/:id/services/jira ## Kubernetes -Kubernetes / Openshift integration +Kubernetes / OpenShift integration CAUTION: **Warning:** Kubernetes service integration has been deprecated in GitLab 10.3. API service endpoints will continue to work as long as the Kubernetes service is active, however if the service is inactive API endpoints will automatically return a `400 Bad Request`. Read [GitLab 10.3 release post](https://about.gitlab.com/2017/12/22/gitlab-10-3-released/#kubernetes-integration-service) for more information. diff --git a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md index ec0b5aaed09..b59271e400f 100644 --- a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md +++ b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md @@ -47,7 +47,7 @@ This project has three jobs: ## Store API keys -You'll need to create two variables in `Settings > CI/CD > Variables` on your GitLab project settings: +You'll need to create two variables in **Settings > CI/CD > Variables** in your GitLab project: - `HEROKU_STAGING_API_KEY` - Heroku API key used to deploy staging app. - `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app. diff --git a/doc/install/openshift_and_gitlab/index.md b/doc/install/openshift_and_gitlab/index.md index 4c88b6f97fc..25a87dbd9de 100644 --- a/doc/install/openshift_and_gitlab/index.md +++ b/doc/install/openshift_and_gitlab/index.md @@ -18,7 +18,7 @@ In this tutorial, we will see how to deploy GitLab in OpenShift using GitLab's official Docker image while getting familiar with the web interface and CLI tools that will help us achieve our goal. -For a video demonstration on installing GitLab on Openshift, check the article [In 13 minutes from Kubernetes to a complete application development tool](https://about.gitlab.com/2016/11/14/idea-to-production/). +For a video demonstration on installing GitLab on OpenShift, check the article [In 13 minutes from Kubernetes to a complete application development tool](https://about.gitlab.com/2016/11/14/idea-to-production/). --- @@ -518,7 +518,7 @@ PaaS and managing your applications with the ease of containers. [templates]: https://docs.openshift.org/latest/architecture/core_concepts/templates.html "Documentation - OpenShift templates" [old-post]: https://blog.openshift.com/deploy-gitlab-openshift/ "Old post - Deploy GitLab on OpenShift" [line]: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/658c065c8d022ce858dd63eaeeadb0b2ddc8deea/docker/openshift-template.json#L239 "GitLab - OpenShift template" -[oc-gh]: https://github.com/openshift/origin/releases/tag/v1.3.0 "Openshift 1.3.0 release on GitHub" +[oc-gh]: https://github.com/openshift/origin/releases/tag/v1.3.0 "OpenShift Origin 1.3.0 release on GitHub" [ha]: ../../administration/high_availability/gitlab.html "Documentation - GitLab High Availability" [replicas]: https://docs.openshift.org/latest/architecture/core_concepts/deployments.html#replication-controllers "Documentation - Replication controller" [autoscaling]: https://docs.openshift.org/latest/dev_guide/pod_autoscaling.html "Documentation - Autoscale" diff --git a/doc/topics/authentication/index.md b/doc/topics/authentication/index.md index 766a23c419d..a354d3e7884 100644 --- a/doc/topics/authentication/index.md +++ b/doc/topics/authentication/index.md @@ -45,4 +45,4 @@ This page gathers all the resources for the topic **Authentication** within GitL - [Kanboard Plugin GitLab Authentication](https://github.com/kanboard/plugin-gitlab-auth) - [Jenkins GitLab OAuth Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+OAuth+Plugin) - [How to customize GitLab to support OpenID authentication](http://eric.van-der-vlist.com/blog/2013/11/23/how-to-customize-gitlab-to-support-openid-authentication/) -- [Openshift - Configuring Authentication and User Agent](https://docs.openshift.org/latest/install_config/configuring_authentication.html#GitLab) +- [OKD - Configuring Authentication and User Agent](https://docs.okd.io/latest/install_config/configuring_authentication.html#GitLab) diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md index d9a2eeb32ae..5de8e66e7eb 100644 --- a/doc/user/project/integrations/prometheus.md +++ b/doc/user/project/integrations/prometheus.md @@ -30,7 +30,7 @@ GitLab can seamlessly deploy and manage Prometheus on a [connected Kubernetes cl Once you have a connected Kubernetes cluster with Helm installed, deploying a managed Prometheus is as easy as a single click. -1. Go to the `Operations > Kubernetes` page, to view your connected clusters +1. Go to the **Operations > Kubernetes** page to view your connected clusters 1. Select the cluster you would like to deploy Prometheus to 1. Click the **Install** button to deploy Prometheus to the cluster @@ -88,7 +88,7 @@ to integrate with. Once configured, GitLab will attempt to retrieve performance metrics for any environment which has had a successful deployment. -GitLab will automatically scan the Prometheus server for metrics from known serves like Kubernetes and NGINX, and attempt to identify individual environment. The supported metrics and scan process is detailed in our [Prometheus Metric Library documentation](prometheus_library/metrics.html). +GitLab will automatically scan the Prometheus server for metrics from known serves like Kubernetes and NGINX, and attempt to identify individual environment. The supported metrics and scan process is detailed in our [Prometheus Metric Library documentation](prometheus_library/index.md). You can view the performance dashboard for an environment by [clicking on the monitoring button](../../../ci/environments.md#monitoring-environments). diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb index a0434a66ef1..0add2b3f875 100644 --- a/lib/backup/manager.rb +++ b/lib/backup/manager.rb @@ -195,7 +195,7 @@ module Backup if connection.service == ::Fog::Storage::Local connection.directories.create(key: remote_directory) else - connection.directories.get(remote_directory) + connection.directories.new(key: remote_directory) end end diff --git a/qa/Gemfile b/qa/Gemfile index d69c71003ae..75ad7bd07af 100644 --- a/qa/Gemfile +++ b/qa/Gemfile @@ -5,5 +5,6 @@ gem 'capybara', '~> 2.16.1' gem 'capybara-screenshot', '~> 1.0.18' gem 'rake', '~> 12.3.0' gem 'rspec', '~> 3.7' -gem 'selenium-webdriver', '~> 3.8.0' +gem 'selenium-webdriver', '~> 3.12' gem 'airborne', '~> 0.2.13' +gem 'nokogiri', '~> 1.8.5' diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock index d61ecf8fbb5..55f3211482b 100644 --- a/qa/Gemfile.lock +++ b/qa/Gemfile.lock @@ -25,7 +25,7 @@ GEM capybara-screenshot (1.0.18) capybara (>= 1.0, < 3) launchy - childprocess (0.8.0) + childprocess (0.9.0) ffi (~> 1.0, >= 1.0.11) coderay (1.1.2) concurrent-ruby (1.0.5) @@ -47,7 +47,7 @@ GEM mini_portile2 (2.3.0) minitest (5.11.1) netrc (0.11.0) - nokogiri (1.8.2) + nokogiri (1.8.5) mini_portile2 (~> 2.3.0) pry (0.11.3) coderay (~> 1.1.0) @@ -78,9 +78,9 @@ GEM rspec-support (~> 3.7.0) rspec-support (3.7.0) rubyzip (1.2.2) - selenium-webdriver (3.8.0) + selenium-webdriver (3.141.0) childprocess (~> 0.5) - rubyzip (~> 1.0) + rubyzip (~> 1.2, >= 1.2.2) thread_safe (0.3.6) tzinfo (1.2.4) thread_safe (~> 0.1) @@ -97,10 +97,11 @@ DEPENDENCIES airborne (~> 0.2.13) capybara (~> 2.16.1) capybara-screenshot (~> 1.0.18) + nokogiri (~> 1.8.5) pry-byebug (~> 3.5.1) rake (~> 12.3.0) rspec (~> 3.7) - selenium-webdriver (~> 3.8.0) + selenium-webdriver (~> 3.12) BUNDLED WITH - 1.17.1 + 1.17.3 diff --git a/spec/controllers/dashboard/milestones_controller_spec.rb b/spec/controllers/dashboard/milestones_controller_spec.rb index 8a8cc14fd4c..c9ccd5f7c55 100644 --- a/spec/controllers/dashboard/milestones_controller_spec.rb +++ b/spec/controllers/dashboard/milestones_controller_spec.rb @@ -52,7 +52,7 @@ describe Dashboard::MilestonesController do expect(response).to have_gitlab_http_status(200) expect(json_response.size).to eq(2) - expect(json_response.map { |i| i["first_milestone"]["id"] }).to match_array([group_milestone.id, project_milestone.id]) + expect(json_response.map { |i| i["name"] }).to match_array([group_milestone.name, project_milestone.name]) expect(json_response.map { |i| i["group_name"] }.compact).to match_array(group.name) end diff --git a/spec/controllers/groups/milestones_controller_spec.rb b/spec/controllers/groups/milestones_controller_spec.rb index b8e1e08cff7..40d991a669c 100644 --- a/spec/controllers/groups/milestones_controller_spec.rb +++ b/spec/controllers/groups/milestones_controller_spec.rb @@ -64,7 +64,7 @@ describe Groups::MilestonesController do context 'when there is a title parameter' do it 'searches for a legacy group milestone' do - expect(GlobalMilestone).to receive(:build) + expect(GroupMilestone).to receive(:build) expect(Milestone).not_to receive(:find_by_iid) get :show, params: { group_id: group.to_param, id: title, title: milestone1.safe_title } diff --git a/spec/features/groups/milestone_spec.rb b/spec/features/groups/milestone_spec.rb index 174840794ed..d57eb87ca77 100644 --- a/spec/features/groups/milestone_spec.rb +++ b/spec/features/groups/milestone_spec.rb @@ -81,7 +81,7 @@ describe 'Group milestones' do description: 'Lorem Ipsum is simply dummy text' ) end - let!(:active_project_milestone2) { create(:milestone, project: other_project, state: 'active', title: 'v1.0') } + let!(:active_project_milestone2) { create(:milestone, project: other_project, state: 'active', title: 'v1.1') } let!(:closed_project_milestone1) { create(:milestone, project: project, state: 'closed', title: 'v2.0') } let!(:closed_project_milestone2) { create(:milestone, project: other_project, state: 'closed', title: 'v2.0') } let!(:active_group_milestone) { create(:milestone, group: group, state: 'active', title: 'GL-113') } @@ -104,7 +104,7 @@ describe 'Group milestones' do legacy_milestone = GroupMilestone.build_collection(group, group.projects, { state: 'active' }).first expect(page).to have_selector("#milestone_#{active_group_milestone.id}", count: 1) - expect(page).to have_selector("#milestone_#{legacy_milestone.milestones.first.id}", count: 1) + expect(page).to have_selector("#milestone_#{legacy_milestone.milestone.id}", count: 1) end it 'shows milestone detail and supports its edit' do @@ -121,6 +121,7 @@ describe 'Group milestones' do it 'renders milestones' do expect(page).to have_content('v1.0') + expect(page).to have_content('v1.1') expect(page).to have_content('GL-113') expect(page).to have_link( '1 Issue', diff --git a/spec/features/groups/milestones_sorting_spec.rb b/spec/features/groups/milestones_sorting_spec.rb index bc226ff41c1..7bc015ea28f 100644 --- a/spec/features/groups/milestones_sorting_spec.rb +++ b/spec/features/groups/milestones_sorting_spec.rb @@ -42,6 +42,7 @@ describe 'Milestones sorting', :js do expect(page).to have_button('Due later') + # assert descending sorting within '.milestones' do expect(page.all('ul.content-list > li').first.text).to include('v1.0') expect(page.all('ul.content-list > li')[1].text).to include('v3.0') diff --git a/spec/models/global_milestone_spec.rb b/spec/models/global_milestone_spec.rb index b6355455c1d..62699df5611 100644 --- a/spec/models/global_milestone_spec.rb +++ b/spec/models/global_milestone_spec.rb @@ -65,56 +65,103 @@ describe GlobalMilestone do ) end - before do - projects = [ + let!(:projects) do + [ project1, project2, project3 ] - - @global_milestones = described_class.build_collection(projects, {}) end - it 'has all project milestones' do - expect(@global_milestones.count).to eq(2) + let!(:global_milestones) { described_class.build_collection(projects, {}) } + + context 'when building a collection of milestones' do + it 'has all project milestones' do + expect(global_milestones.count).to eq(6) + end + + it 'has all project milestones titles' do + expect(global_milestones.map(&:title)).to match_array(['Milestone v1.2', 'Milestone v1.2', 'Milestone v1.2', 'VD-123', 'VD-123', 'VD-123']) + end + + it 'has all project milestones' do + expect(global_milestones.size).to eq(6) + end + + it 'sorts collection by due date' do + expect(global_milestones.map(&:due_date)).to eq [milestone1_due_date, milestone1_due_date, milestone1_due_date, nil, nil, nil] + end end - it 'has all project milestones titles' do - expect(@global_milestones.map(&:title)).to match_array(['Milestone v1.2', 'VD-123']) + context 'when adding new milestones' do + it 'does not add more queries' do + control_count = ActiveRecord::QueryRecorder.new do + described_class.build_collection(projects, {}) + end.count + + create_list(:milestone, 3, project: project3) + + expect do + described_class.build_collection(projects, {}) + end.not_to exceed_all_query_limit(control_count) + end end + end + + describe '.states_count' do + context 'when the projects have milestones' do + before do + create(:closed_milestone, title: 'Active Group Milestone', project: project3) + create(:active_milestone, title: 'Active Group Milestone', project: project1) + create(:active_milestone, title: 'Active Group Milestone', project: project2) + create(:closed_milestone, title: 'Closed Group Milestone', project: project1) + create(:closed_milestone, title: 'Closed Group Milestone', project: project2) + create(:closed_milestone, title: 'Closed Group Milestone', project: project3) + create(:closed_milestone, title: 'Closed Group Milestone 4', group: group) + end + + it 'returns the quantity of global milestones and group milestones in each possible state' do + expected_count = { opened: 2, closed: 5, all: 7 } - it 'has all project milestones' do - expect(@global_milestones.map { |group_milestone| group_milestone.milestones.count }.sum).to eq(6) + count = described_class.states_count(Project.all, group) + + expect(count).to eq(expected_count) + end + + it 'returns the quantity of global milestones in each possible state' do + expected_count = { opened: 2, closed: 4, all: 6 } + + count = described_class.states_count(Project.all) + + expect(count).to eq(expected_count) + end end - it 'sorts collection by due date' do - expect(@global_milestones.map(&:due_date)).to eq [nil, milestone1_due_date] + context 'when the projects do not have milestones' do + before do + project1 + end + + it 'returns 0 as the quantity of global milestones in each state' do + expected_count = { opened: 0, closed: 0, all: 0 } + + count = described_class.states_count(Project.all) + + expect(count).to eq(expected_count) + end end end describe '#initialize' do let(:milestone1_project1) { create(:milestone, title: "Milestone v1.2", project: project1) } - let(:milestone1_project2) { create(:milestone, title: "Milestone v1.2", project: project2) } - let(:milestone1_project3) { create(:milestone, title: "Milestone v1.2", project: project3) } - - before do - milestones = - [ - milestone1_project1, - milestone1_project2, - milestone1_project3 - ] - milestones_relation = Milestone.where(id: milestones.map(&:id)) - - @global_milestone = described_class.new(milestone1_project1.title, milestones_relation) - end + subject(:global_milestone) { described_class.new(milestone1_project1) } it 'has exactly one group milestone' do - expect(@global_milestone.title).to eq('Milestone v1.2') + expect(global_milestone.title).to eq('Milestone v1.2') end it 'has all project milestones with the same title' do - expect(@global_milestone.milestones.count).to eq(3) + expect(global_milestone.milestone).to eq(milestone1_project1) end end @@ -122,7 +169,7 @@ describe GlobalMilestone do let(:milestone) { create(:milestone, title: "git / test", project: project1) } it 'strips out slashes and spaces' do - global_milestone = described_class.new(milestone.title, Milestone.where(id: milestone.id)) + global_milestone = described_class.new(milestone) expect(global_milestone.safe_title).to eq('git-test') end @@ -132,11 +179,8 @@ describe GlobalMilestone do context 'when at least one milestone is active' do it 'returns active' do title = 'Active Group Milestone' - milestones = [ - create(:active_milestone, title: title), - create(:closed_milestone, title: title) - ] - global_milestone = described_class.new(title, milestones) + + global_milestone = described_class.new(create(:active_milestone, title: title)) expect(global_milestone.state).to eq('active') end @@ -145,11 +189,8 @@ describe GlobalMilestone do context 'when all milestones are closed' do it 'returns closed' do title = 'Closed Group Milestone' - milestones = [ - create(:closed_milestone, title: title), - create(:closed_milestone, title: title) - ] - global_milestone = described_class.new(title, milestones) + + global_milestone = described_class.new(create(:closed_milestone, title: title)) expect(global_milestone.state).to eq('closed') end diff --git a/spec/models/group_milestone_spec.rb b/spec/models/group_milestone_spec.rb index b60676afc91..fcc33cd95fe 100644 --- a/spec/models/group_milestone_spec.rb +++ b/spec/models/group_milestone_spec.rb @@ -20,13 +20,36 @@ describe GroupMilestone do end describe '.build_collection' do - before do - project_milestone + let(:group) { create(:group) } + let(:project1) { create(:project, group: group) } + let(:project2) { create(:project, path: 'gitlab-ci', group: group) } + let(:project3) { create(:project, path: 'cookbook-gitlab', group: group) } + + let!(:projects) do + [ + project1, + project2, + project3 + ] end it 'returns array of milestones, each with group assigned' do milestones = described_class.build_collection(group, [project], {}) expect(milestones).to all(have_attributes(group: group)) end + + context 'when adding new milestones' do + it 'does not add more queries' do + control_count = ActiveRecord::QueryRecorder.new do + described_class.build_collection(group, projects, {}) + end.count + + create(:milestone, title: 'This title', project: project1) + + expect do + described_class.build_collection(group, projects, {}) + end.not_to exceed_all_query_limit(control_count) + end + end end end diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb index c63621fe7d1..2f322cc7054 100644 --- a/spec/requests/api/runner_spec.rb +++ b/spec/requests/api/runner_spec.rb @@ -1320,7 +1320,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do end before do - fog_connection.directories.get('artifacts').files.create( + fog_connection.directories.new(key: 'artifacts').files.create( key: 'tmp/uploads/12312300', body: 'content' ) diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb index 3cc29a7076d..f1514e90eb2 100644 --- a/spec/requests/lfs_http_spec.rb +++ b/spec/requests/lfs_http_spec.rb @@ -1123,7 +1123,7 @@ describe 'Git LFS API and storage' do context 'with valid remote_id' do before do - fog_connection.directories.get('lfs-objects').files.create( + fog_connection.directories.new(key: 'lfs-objects').files.create( key: 'tmp/uploads/12312300', body: 'content' ) diff --git a/spec/uploaders/file_uploader_spec.rb b/spec/uploaders/file_uploader_spec.rb index c74e0bf1955..db9e5eb2ad6 100644 --- a/spec/uploaders/file_uploader_spec.rb +++ b/spec/uploaders/file_uploader_spec.rb @@ -201,7 +201,7 @@ describe FileUploader do end let!(:fog_file) do - fog_connection.directories.get('uploads').files.create( + fog_connection.directories.new(key: 'uploads').files.create( key: 'tmp/uploads/test/123123', body: 'content' ) diff --git a/spec/uploaders/object_storage_spec.rb b/spec/uploaders/object_storage_spec.rb index 7e673681c31..533e9d87ea6 100644 --- a/spec/uploaders/object_storage_spec.rb +++ b/spec/uploaders/object_storage_spec.rb @@ -716,7 +716,7 @@ describe ObjectStorage do end let!(:fog_file) do - fog_connection.directories.get('uploads').files.create( + fog_connection.directories.new(key: 'uploads').files.create( key: 'tmp/uploads/test/123123', body: 'content' ) |