-
-
-
diff --git a/app/assets/stylesheets/framework.scss b/app/assets/stylesheets/framework.scss
index 4041f2b4479..d320fa5f595 100644
--- a/app/assets/stylesheets/framework.scss
+++ b/app/assets/stylesheets/framework.scss
@@ -6,6 +6,7 @@
@import 'bootstrap_migration';
@import 'framework/layout';
+@import 'framework/alerts';
@import 'framework/animations';
@import 'framework/vue_transitions';
@import 'framework/avatar';
diff --git a/app/assets/stylesheets/framework/alerts.scss b/app/assets/stylesheets/framework/alerts.scss
new file mode 100644
index 00000000000..866792a6a1b
--- /dev/null
+++ b/app/assets/stylesheets/framework/alerts.scss
@@ -0,0 +1,4 @@
+.alert-tip {
+ background-color: $theme-gray-100;
+ color: $theme-gray-900;
+}
diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss
index d5693a5d1a1..f48b3ddc912 100644
--- a/app/assets/stylesheets/framework/filters.scss
+++ b/app/assets/stylesheets/framework/filters.scss
@@ -363,6 +363,12 @@
background-color: $white-light;
border-top: 0;
}
+
+ .filter-dropdown-container {
+ .dropdown {
+ margin-left: 0;
+ }
+ }
}
@include media-breakpoint-down(sm) {
@@ -372,16 +378,6 @@
.dropdown-menu {
width: 100%;
}
-
- .dropdown {
- margin-left: 0;
- }
-
- .fa-chevron-down {
- position: absolute;
- right: 10px;
- top: 10px;
- }
}
}
diff --git a/app/assets/stylesheets/framework/highlight.scss b/app/assets/stylesheets/framework/highlight.scss
index 452e946f95f..a0bf6907b5f 100644
--- a/app/assets/stylesheets/framework/highlight.scss
+++ b/app/assets/stylesheets/framework/highlight.scss
@@ -42,6 +42,7 @@
padding: 10px;
text-align: right;
float: left;
+ line-height: 1;
a {
font-family: $monospace-font;
diff --git a/app/assets/stylesheets/framework/icons.scss b/app/assets/stylesheets/framework/icons.scss
index abd26e38d18..8db7d63266e 100644
--- a/app/assets/stylesheets/framework/icons.scss
+++ b/app/assets/stylesheets/framework/icons.scss
@@ -80,3 +80,15 @@
.user-avatar-link {
text-decoration: none;
}
+
+.circle-icon-container {
+ $border-size: 1px;
+
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border: $border-size solid $theme-gray-400;
+ border-radius: 50%;
+ padding: $gl-padding-8 - $border-size;
+ color: $theme-gray-700;
+}
diff --git a/app/assets/stylesheets/framework/secondary_navigation_elements.scss b/app/assets/stylesheets/framework/secondary_navigation_elements.scss
index de9e7c37695..19640ab5986 100644
--- a/app/assets/stylesheets/framework/secondary_navigation_elements.scss
+++ b/app/assets/stylesheets/framework/secondary_navigation_elements.scss
@@ -158,6 +158,10 @@
width: 100%;
}
+ .dropdown-menu-toggle {
+ margin-bottom: 0;
+ }
+
form {
display: block;
height: auto;
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index b075009b57c..221b4e934ff 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -50,9 +50,19 @@
.mr-widget-heading {
position: relative;
border: 1px solid $border-color;
- border-radius: 4px;
+ border-radius: $border-radius-default;
+}
- &:not(.deploy-heading)::before {
+.mr-widget-extension {
+ border-top: 1px solid $border-color;
+ background-color: $gray-light;
+}
+
+.mr-widget-workflow {
+ margin-top: $gl-padding;
+ position: relative;
+
+ &::before {
content: '';
border-left: 1px solid $theme-gray-200;
position: absolute;
@@ -68,8 +78,8 @@
border-top: 0;
}
-.mr-widget-heading,
.mr-widget-section,
+.mr-widget-content,
.mr-widget-footer {
padding: $gl-padding;
}
@@ -560,19 +570,6 @@
color: $gl-text-color;
}
- .git-merge-icon-container {
- border: 1px solid $theme-gray-400;
- border-radius: 50%;
- height: 32px;
- width: 32px;
- color: $theme-gray-700;
- line-height: 28px;
-
- .ic-git-merge {
- vertical-align: middle;
- width: 31px;
- }
- }
.git-merge-container {
justify-content: space-between;
@@ -854,11 +851,6 @@
}
.deploy-heading {
- margin-top: -19px;
- border-top-left-radius: 0;
- border-top-right-radius: 0;
- background-color: $gray-light;
-
@include media-breakpoint-up(md) {
padding: $gl-padding-8 $gl-padding;
}
@@ -868,6 +860,10 @@
font-size: 12px;
margin-left: 48px;
}
+
+ &:not(:last-child) {
+ border-bottom: 1px solid $border-color;
+ }
}
.deploy-body {
diff --git a/app/controllers/admin/requests_profiles_controller.rb b/app/controllers/admin/requests_profiles_controller.rb
index 64d74ae4231..57f7d3e3951 100644
--- a/app/controllers/admin/requests_profiles_controller.rb
+++ b/app/controllers/admin/requests_profiles_controller.rb
@@ -11,7 +11,7 @@ class Admin::RequestsProfilesController < Admin::ApplicationController
profile = Gitlab::RequestProfiler::Profile.find(clean_name)
if profile
- render text: profile.content
+ render html: profile.content
else
redirect_to admin_requests_profiles_path, alert: 'Profile not found'
end
diff --git a/app/controllers/chaos_controller.rb b/app/controllers/chaos_controller.rb
index b4f46cddbe9..8d518c14b90 100644
--- a/app/controllers/chaos_controller.rb
+++ b/app/controllers/chaos_controller.rb
@@ -15,7 +15,7 @@ class ChaosController < ActionController::Base
duration_taken = (Time.now - start).seconds
Kernel.sleep duration_s - duration_taken if duration_s > duration_taken
- render text: "OK", content_type: 'text/plain'
+ render plain: "OK"
end
def cpuspin
@@ -24,14 +24,14 @@ class ChaosController < ActionController::Base
rand while Time.now < end_time
- render text: "OK", content_type: 'text/plain'
+ render plain: "OK"
end
def sleep
duration_s = (params[:duration_s]&.to_i || 30).seconds
Kernel.sleep duration_s
- render text: "OK", content_type: 'text/plain'
+ render plain: "OK"
end
def kill
@@ -44,13 +44,13 @@ class ChaosController < ActionController::Base
secret = ENV['GITLAB_CHAOS_SECRET']
# GITLAB_CHAOS_SECRET is required unless you're running in Development mode
if !secret && !Rails.env.development?
- render text: "chaos misconfigured: please configure GITLAB_CHAOS_SECRET when using GITLAB_ENABLE_CHAOS_ENDPOINTS outside of a development environment", content_type: 'text/plain', status: 500
+ render plain: "chaos misconfigured: please configure GITLAB_CHAOS_SECRET when using GITLAB_ENABLE_CHAOS_ENDPOINTS outside of a development environment", status: :internal_server_error
end
return unless secret
unless request.headers["HTTP_X_CHAOS_SECRET"] == secret
- render text: "To experience chaos, please set X-Chaos-Secret header", content_type: 'text/plain', status: 401
+ render plain: "To experience chaos, please set X-Chaos-Secret header", status: :unauthorized
end
end
end
diff --git a/app/controllers/metrics_controller.rb b/app/controllers/metrics_controller.rb
index 7353be478e1..c2089a0fca3 100644
--- a/app/controllers/metrics_controller.rb
+++ b/app/controllers/metrics_controller.rb
@@ -15,7 +15,7 @@ class MetricsController < ActionController::Base
"# Metrics are disabled, see: #{help_page}\n"
end
- render text: response, content_type: 'text/plain; version=0.0.4'
+ render plain: response, content_type: 'text/plain; version=0.0.4'
end
private
diff --git a/app/controllers/profiles/keys_controller.rb b/app/controllers/profiles/keys_controller.rb
index 912421e3d08..dcee8eb7e6e 100644
--- a/app/controllers/profiles/keys_controller.rb
+++ b/app/controllers/profiles/keys_controller.rb
@@ -41,12 +41,12 @@ class Profiles::KeysController < Profiles::ApplicationController
user = UserFinder.new(params[:username]).find_by_username
if user.present?
headers['Content-Disposition'] = 'attachment'
- render text: user.all_ssh_keys.join("\n"), content_type: 'text/plain'
+ render plain: user.all_ssh_keys.join("\n")
else
return render_404
end
rescue => e
- render text: e.message
+ render html: e.message
end
else
return render_404
diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb
index de10783df1a..e940f382a19 100644
--- a/app/controllers/projects/environments_controller.rb
+++ b/app/controllers/projects/environments_controller.rb
@@ -122,7 +122,7 @@ class Projects::EnvironmentsController < Projects::ApplicationController
set_workhorse_internal_api_content_type
render json: Gitlab::Workhorse.terminal_websocket(terminal)
else
- render text: 'Not found', status: :not_found
+ render html: 'Not found', status: :not_found
end
end
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 9512ba42f67..1487b9d3bca 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -26,6 +26,8 @@ module Ci
has_many :builds, foreign_key: :commit_id, inverse_of: :pipeline
has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id # rubocop:disable Cop/ActiveRecordDependent
has_many :variables, class_name: 'Ci::PipelineVariable'
+ has_many :deployments, through: :builds
+ has_many :environments, -> { distinct }, through: :deployments
# Merge requests for which the current pipeline is running against
# the merge request's latest commit.
@@ -523,10 +525,6 @@ module Ci
yaml_errors.present?
end
- def environments
- builds.where.not(environment: nil).success.pluck(:environment).uniq
- end
-
# Manually set the notes for a Ci::Pipeline
# There is no ActiveRecord relation between Ci::Pipeline and notes
# as they are related to a commit sha. This method helps importing
diff --git a/app/models/clusters/applications/jupyter.rb b/app/models/clusters/applications/jupyter.rb
index e43a0fd1786..421a923d386 100644
--- a/app/models/clusters/applications/jupyter.rb
+++ b/app/models/clusters/applications/jupyter.rb
@@ -56,7 +56,11 @@ module Clusters
def specification
{
"ingress" => {
- "hosts" => [hostname]
+ "hosts" => [hostname],
+ "tls" => [{
+ "hosts" => [hostname],
+ "secretName" => "jupyter-cert"
+ }]
},
"hub" => {
"extraEnv" => {
diff --git a/app/models/environment_status.rb b/app/models/environment_status.rb
index 4a128dde5cd..2fb6cadc8cd 100644
--- a/app/models/environment_status.rb
+++ b/app/models/environment_status.rb
@@ -12,13 +12,13 @@ class EnvironmentStatus
delegate :deployed_at, to: :deployment, allow_nil: true
def self.for_merge_request(mr, user)
- build_environments_status(mr, user, mr.diff_head_sha)
+ build_environments_status(mr, user, mr.actual_head_pipeline)
end
def self.after_merge_request(mr, user)
return [] unless mr.merged?
- build_environments_status(mr, user, mr.merge_commit_sha)
+ build_environments_status(mr, user, mr.merge_pipeline)
end
def initialize(environment, merge_request, sha)
@@ -61,13 +61,13 @@ class EnvironmentStatus
}
end
- def self.build_environments_status(mr, user, sha)
- Environment.where(project_id: [mr.source_project_id, mr.target_project_id])
- .available
- .with_deployment(sha).map do |environment|
+ def self.build_environments_status(mr, user, pipeline)
+ return [] unless pipeline
+
+ pipeline.environments.available.map do |environment|
next unless Ability.allowed?(user, :read_environment, environment)
- EnvironmentStatus.new(environment, mr, sha)
+ EnvironmentStatus.new(environment, mr, pipeline.sha)
end.compact
end
private_class_method :build_environments_status
diff --git a/app/models/notification_setting.rb b/app/models/notification_setting.rb
index 1600acfc575..e82eaf4e069 100644
--- a/app/models/notification_setting.rb
+++ b/app/models/notification_setting.rb
@@ -5,7 +5,7 @@ class NotificationSetting < ActiveRecord::Base
ignore_column :events
- enum level: { global: 3, watch: 2, mention: 4, participating: 1, disabled: 0, custom: 5 }
+ enum level: { global: 3, watch: 2, participating: 1, mention: 4, disabled: 0, custom: 5 }
default_value_for :level, NotificationSetting.levels[:global]
diff --git a/app/views/admin/runners/_sort_dropdown.html.haml b/app/views/admin/runners/_sort_dropdown.html.haml
index b201e6bf10e..19c2a50ebd9 100644
--- a/app/views/admin/runners/_sort_dropdown.html.haml
+++ b/app/views/admin/runners/_sort_dropdown.html.haml
@@ -1,7 +1,7 @@
- sorted_by = sort_options_hash[@sort]
.dropdown.inline.prepend-left-10
- %button.dropdown-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' } }
+ %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' } }
= sorted_by
= icon('chevron-down')
%ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable.dropdown-menu-sort
diff --git a/app/views/explore/projects/_filter.html.haml b/app/views/explore/projects/_filter.html.haml
index b694103ccaf..f518205f14c 100644
--- a/app/views/explore/projects/_filter.html.haml
+++ b/app/views/explore/projects/_filter.html.haml
@@ -1,8 +1,8 @@
- if current_user
.dropdown
- %button.dropdown-toggle{ href: '#', "data-toggle" => "dropdown", 'data-display' => 'static' }
- = icon('globe')
- %span.light= _("Visibility:")
+ %button.dropdown-menu-toggle{ href: '#', "data-toggle" => "dropdown", 'data-display' => 'static' }
+ = icon('globe', class: 'mt-1')
+ %span.light.ml-3= _("Visibility:")
- if params[:visibility_level].present?
= visibility_level_label(params[:visibility_level].to_i)
- else
diff --git a/app/views/projects/forks/index.html.haml b/app/views/projects/forks/index.html.haml
index b44ea89510b..c63c34c4ebb 100644
--- a/app/views/projects/forks/index.html.haml
+++ b/app/views/projects/forks/index.html.haml
@@ -9,7 +9,7 @@
spellcheck: false, data: { 'filter-selector' => 'span.namespace-name' }
.dropdown
- %button.dropdown-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
+ %button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
%span.light sort:
- if @sort.present?
= sort_options_hash[@sort]
diff --git a/app/views/projects/mirrors/_mirror_repos.html.haml b/app/views/projects/mirrors/_mirror_repos.html.haml
index 2f9bd5b04b6..dde0fae740b 100644
--- a/app/views/projects/mirrors/_mirror_repos.html.haml
+++ b/app/views/projects/mirrors/_mirror_repos.html.haml
@@ -32,7 +32,7 @@
= link_to icon('question-circle'), help_page_path('user/project/protected_branches')
.panel-footer
- = f.submit _('Mirror repository'), class: 'btn btn-success', name: :update_remote_mirror
+ = f.submit _('Mirror repository'), class: 'btn btn-success js-mirror-submit', name: :update_remote_mirror
.panel.panel-default
.table-responsive
diff --git a/app/views/projects/tags/index.html.haml b/app/views/projects/tags/index.html.haml
index 37535370940..026bc44a05f 100644
--- a/app/views/projects/tags/index.html.haml
+++ b/app/views/projects/tags/index.html.haml
@@ -14,7 +14,7 @@
= search_field_tag :search, params[:search], { placeholder: s_('TagsPage|Filter by tag name'), id: 'tag-search', class: 'form-control search-text-input input-short', spellcheck: false }
.dropdown
- %button.dropdown-toggle{ type: 'button', data: { toggle: 'dropdown'} }
+ %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown'} }
%span.light
= tags_sort_options_hash[@sort]
= icon('chevron-down')
diff --git a/app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml b/app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml
index 6c4607b2f16..0d0a3c1aa64 100644
--- a/app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml
+++ b/app/views/shared/_auto_devops_implicitly_enabled_banner.html.haml
@@ -1,6 +1,6 @@
- if show_auto_devops_implicitly_enabled_banner?(project)
.auto-devops-implicitly-enabled-banner.alert.alert-warning
- - more_information_link = link_to _('More information'), 'https://docs.gitlab.com/ee/topics/autodevops/', class: 'alert-link'
+ - more_information_link = link_to _('More information'), help_page_path('topics/autodevops/index.md'), target: '_blank', class: 'alert-link'
- auto_devops_message = s_("AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}") % { more_information_link: more_information_link }
= auto_devops_message.html_safe
.alert-link-group
diff --git a/app/views/shared/_milestones_sort_dropdown.html.haml b/app/views/shared/_milestones_sort_dropdown.html.haml
index a6ba3b59365..bd68a3e4c84 100644
--- a/app/views/shared/_milestones_sort_dropdown.html.haml
+++ b/app/views/shared/_milestones_sort_dropdown.html.haml
@@ -1,5 +1,5 @@
.dropdown.inline.prepend-left-10
- %button.dropdown-toggle{ type: 'button', data: { toggle: 'dropdown' } }
+ %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown' } }
%span.light
- if @sort.present?
= milestone_sort_options_hash[@sort]
diff --git a/app/views/shared/_sort_dropdown.html.haml b/app/views/shared/_sort_dropdown.html.haml
index be6d4f1c32b..e4463c1e0d8 100644
--- a/app/views/shared/_sort_dropdown.html.haml
+++ b/app/views/shared/_sort_dropdown.html.haml
@@ -2,7 +2,7 @@
- viewing_issues = controller.controller_name == 'issues' || controller.action_name == 'issues'
.dropdown.inline.prepend-left-10
- %button.dropdown-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' } }
+ %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown', display: 'static' } }
= sorted_by
= icon('chevron-down')
%ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable.dropdown-menu-sort
diff --git a/app/views/shared/groups/_dropdown.html.haml b/app/views/shared/groups/_dropdown.html.haml
index 2237b93a10b..1ae6d1f5ee3 100644
--- a/app/views/shared/groups/_dropdown.html.haml
+++ b/app/views/shared/groups/_dropdown.html.haml
@@ -9,7 +9,7 @@
- default_sort_by = sort_value_recently_created
.dropdown.inline.js-group-filter-dropdown-wrap.append-right-10
- %button.dropdown-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
+ %button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' }
%span.dropdown-label
= options_hash[default_sort_by]
= icon('chevron-down')
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 6939aba6896..7c5af0b9775 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -95,7 +95,10 @@
%ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'none' } }
%button.btn.btn-link{ type: 'button' }
- = _('No Label')
+ = _('None')
+ %li.filter-dropdown-item{ data: { value: 'any' } }
+ %button.btn.btn-link{ type: 'button' }
+ = _('Any')
%li.divider.droplab-item-ignore
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
diff --git a/app/views/shared/labels/_sort_dropdown.html.haml b/app/views/shared/labels/_sort_dropdown.html.haml
index 8a7d037e15b..d664ef1cc2f 100644
--- a/app/views/shared/labels/_sort_dropdown.html.haml
+++ b/app/views/shared/labels/_sort_dropdown.html.haml
@@ -1,6 +1,6 @@
- sort_title = label_sort_options_hash[@sort] || sort_title_name_desc
.dropdown.inline
- %button.dropdown-toggle{ type: 'button', data: { toggle: 'dropdown' } }
+ %button.dropdown-menu-toggle{ type: 'button', data: { toggle: 'dropdown' } }
= sort_title
= icon('chevron-down')
%ul.dropdown-menu.dropdown-menu-right.dropdown-menu-sort
diff --git a/changelogs/unreleased/1979-redesign-mr-widget-approvals-ce.yml b/changelogs/unreleased/1979-redesign-mr-widget-approvals-ce.yml
new file mode 100644
index 00000000000..d05b6054b22
--- /dev/null
+++ b/changelogs/unreleased/1979-redesign-mr-widget-approvals-ce.yml
@@ -0,0 +1,5 @@
+---
+title: Redesign of MR header sections (CE)
+merge_request: 23465
+author:
+type: changed
diff --git a/changelogs/unreleased/52370-filter-by-none-any-for-labels-in-issues-mrs-boards.yml b/changelogs/unreleased/52370-filter-by-none-any-for-labels-in-issues-mrs-boards.yml
new file mode 100644
index 00000000000..9e1ee3ede5e
--- /dev/null
+++ b/changelogs/unreleased/52370-filter-by-none-any-for-labels-in-issues-mrs-boards.yml
@@ -0,0 +1,5 @@
+---
+title: Adds Any option to label filters
+merge_request: 23111
+author: Jacopo Beschi @jacopo-beschi
+type: added
diff --git a/changelogs/unreleased/53400-unstar-icon-button-is-misaligned.yml b/changelogs/unreleased/53400-unstar-icon-button-is-misaligned.yml
new file mode 100644
index 00000000000..b393795f491
--- /dev/null
+++ b/changelogs/unreleased/53400-unstar-icon-button-is-misaligned.yml
@@ -0,0 +1,5 @@
+---
+title: 'Fix: Unstar icon button is misaligned'
+merge_request: 23444
+author:
+type: fixed
diff --git a/changelogs/unreleased/53763-fix-encrypt-columns-data-loss.yml b/changelogs/unreleased/53763-fix-encrypt-columns-data-loss.yml
deleted file mode 100644
index 44362a8622e..00000000000
--- a/changelogs/unreleased/53763-fix-encrypt-columns-data-loss.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Correctly handle data-loss scenarios when encrypting columns
-merge_request: 23306
-author:
-type: fixed
diff --git a/changelogs/unreleased/53778-remove-site-statistics.yml b/changelogs/unreleased/53778-remove-site-statistics.yml
deleted file mode 100644
index fe006e43671..00000000000
--- a/changelogs/unreleased/53778-remove-site-statistics.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Removed Site Statistics optimization as it was causing problems
-merge_request: 23314
-author:
-type: removed
diff --git a/changelogs/unreleased/54048-Line-numbers-are-misaligned-in-file-blame-view.yml b/changelogs/unreleased/54048-Line-numbers-are-misaligned-in-file-blame-view.yml
new file mode 100644
index 00000000000..8ceac4ec869
--- /dev/null
+++ b/changelogs/unreleased/54048-Line-numbers-are-misaligned-in-file-blame-view.yml
@@ -0,0 +1,5 @@
+---
+title: Fix line height of numbers in file blame view
+merge_request: 23090
+author: Johann Hubert Sonntagbauer
+type: fixed
diff --git a/changelogs/unreleased/54282-tooltip-stuck.yml b/changelogs/unreleased/54282-tooltip-stuck.yml
deleted file mode 100644
index 655870499a0..00000000000
--- a/changelogs/unreleased/54282-tooltip-stuck.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixes stuck tooltip on stop env button
-merge_request: 23244
-author:
-type: fixed
diff --git a/changelogs/unreleased/54648-fix-order-by-dropdown-tablet-screens.yml b/changelogs/unreleased/54648-fix-order-by-dropdown-tablet-screens.yml
new file mode 100644
index 00000000000..671d1590991
--- /dev/null
+++ b/changelogs/unreleased/54648-fix-order-by-dropdown-tablet-screens.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Order By dropdown menu styling in tablet and mobile screens
+merge_request: 23446
+author:
+type: fixed
diff --git a/changelogs/unreleased/bump_gpgme_gem.yml b/changelogs/unreleased/bump_gpgme_gem.yml
new file mode 100644
index 00000000000..4c0067cb824
--- /dev/null
+++ b/changelogs/unreleased/bump_gpgme_gem.yml
@@ -0,0 +1,5 @@
+---
+title: Bump gpgme gem version from 2.0.13 to 2.0.18
+merge_request:
+author: asaparov
+type: other
diff --git a/changelogs/unreleased/ce-53347_fix_impersonation_tokens.yml b/changelogs/unreleased/ce-53347_fix_impersonation_tokens.yml
deleted file mode 100644
index 6cc743d6f3a..00000000000
--- a/changelogs/unreleased/ce-53347_fix_impersonation_tokens.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Display impersonation token value only after creation
-merge_request: 22916
-author:
-type: fixed
diff --git a/changelogs/unreleased/dm-batch-loader-sidekiq.yml b/changelogs/unreleased/dm-batch-loader-sidekiq.yml
deleted file mode 100644
index 87936dc2603..00000000000
--- a/changelogs/unreleased/dm-batch-loader-sidekiq.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Clear BatchLoader context between Sidekiq jobs
-merge_request: 23308
-author:
-type: fixed
diff --git a/changelogs/unreleased/fix-mr-widget-unrelated-deployment-status.yml b/changelogs/unreleased/fix-mr-widget-unrelated-deployment-status.yml
new file mode 100644
index 00000000000..ab926fbd43b
--- /dev/null
+++ b/changelogs/unreleased/fix-mr-widget-unrelated-deployment-status.yml
@@ -0,0 +1,5 @@
+---
+title: Fix unrelated deployment status in MR widget
+merge_request: 23175
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-not-render-emoji.yml b/changelogs/unreleased/fix-not-render-emoji.yml
deleted file mode 100644
index 857b97004f0..00000000000
--- a/changelogs/unreleased/fix-not-render-emoji.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix not render emoji in filter dropdown
-merge_request: 23112
-author: Hiroyuki Sato
-type: fixed
diff --git a/changelogs/unreleased/improve_auto_devops_migration_debug.yml b/changelogs/unreleased/improve_auto_devops_migration_debug.yml
new file mode 100644
index 00000000000..96a78808361
--- /dev/null
+++ b/changelogs/unreleased/improve_auto_devops_migration_debug.yml
@@ -0,0 +1,6 @@
+---
+title: 'Auto DevOps: Add echo for each branch of the deploy() function where we run
+ helm upgrade'
+merge_request: 23499
+author:
+type: changed
diff --git a/changelogs/unreleased/jupyter-tls.yml b/changelogs/unreleased/jupyter-tls.yml
new file mode 100644
index 00000000000..4111edd34ff
--- /dev/null
+++ b/changelogs/unreleased/jupyter-tls.yml
@@ -0,0 +1,5 @@
+---
+title: "#52753: HTTPS for JupyterHub installation"
+merge_request: 23479
+author: Amit Rathi
+type: added
diff --git a/changelogs/unreleased/order-of-notification-settings.yml b/changelogs/unreleased/order-of-notification-settings.yml
new file mode 100644
index 00000000000..0f0243bcb40
--- /dev/null
+++ b/changelogs/unreleased/order-of-notification-settings.yml
@@ -0,0 +1,5 @@
+---
+title: reorder notification settings by noisy-ness
+merge_request:
+author: C.J. Jameson
+type: changed
diff --git a/changelogs/unreleased/render-text-deprecated.yml b/changelogs/unreleased/render-text-deprecated.yml
new file mode 100644
index 00000000000..7dbbd13bcef
--- /dev/null
+++ b/changelogs/unreleased/render-text-deprecated.yml
@@ -0,0 +1,6 @@
+---
+title: 'Fix deprecation: render :text is deprecated because it does not actually render
+ a text/plain response'
+merge_request: 23425
+author: Jasper Maes
+type: other
diff --git a/changelogs/unreleased/sh-fix-hash-filename-handling.yml b/changelogs/unreleased/sh-fix-hash-filename-handling.yml
deleted file mode 100644
index cb32051a4ab..00000000000
--- a/changelogs/unreleased/sh-fix-hash-filename-handling.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix handling of filenames with hash characters in tree view
-merge_request: 23368
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-mirrors-protected-branches.yml b/changelogs/unreleased/sh-fix-mirrors-protected-branches.yml
new file mode 100644
index 00000000000..627de25650d
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-mirrors-protected-branches.yml
@@ -0,0 +1,5 @@
+---
+title: Fix "protected branches only" checkbox not set properly at init
+merge_request: 23409
+author:
+type: fixed
diff --git a/doc/api/repositories.md b/doc/api/repositories.md
index c8de7f2191d..55f5a4cc3b2 100644
--- a/doc/api/repositories.md
+++ b/doc/api/repositories.md
@@ -108,14 +108,18 @@ Get an archive of the repository. This endpoint can be accessed without
authentication if the repository is publicly accessible.
```
-GET /projects/:id/repository/archive
+GET /projects/:id/repository/archive[.format]
```
+`format` is an optional suffix for the archive format. Default is
+`tar.gz`. Options are `tar.gz`, `tar.bz2`, `tbz`, 'tbz2`, `tb2`,
+`bz2`, `tar`, and `zip`. For example, specifying `archive.zip`
+would send an archive in ZIP format.
+
Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `sha` (optional) - The commit SHA to download. A tag, branch reference or sha can be used. This defaults to the tip of the default branch if not specified
-- `format` (optional) - The archive format. Default is `tar.gz`. Options are `tar.gz`, `tar.bz2`, `tbz`, `tbz2`, `tb2`, `bz2`, `tar`, `zip`
## Compare branches, tags or commits
diff --git a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
index b090ea014dc..b1ccce744d8 100644
--- a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
+++ b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md
@@ -273,6 +273,8 @@ The `releases` directory will hold all our deployments:
echo 'Cloning repository'
[ -d {{ $releases_dir }} ] || mkdir {{ $releases_dir }}
git clone --depth 1 {{ $repository }} {{ $new_release_dir }}
+ cd {{ $releases_dir }}
+ git reset --hard {{ $commit }}
@endtask
...
@@ -349,6 +351,8 @@ At the end, our `Envoy.blade.php` file will look like this:
echo 'Cloning repository'
[ -d {{ $releases_dir }} ] || mkdir {{ $releases_dir }}
git clone --depth 1 {{ $repository }} {{ $new_release_dir }}
+ cd {{ $releases_dir }}
+ git reset --hard {{ $commit }}
@endtask
@task('run_composer')
@@ -519,7 +523,7 @@ deploy_production:
- mkdir -p ~/.ssh
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
- - ~/.composer/vendor/bin/envoy run deploy
+ - ~/.composer/vendor/bin/envoy run deploy --commit="$CI_COMMIT_SHA"
environment:
name: production
url: http://192.168.1.1
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index e46b2bbc79c..af7e41db443 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -1590,7 +1590,7 @@ Possible values for `when` are:
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/22631) in GitLab 11.5.
`parallel` allows you to configure how many instances of a job to run in
-parallel. This value has to be greater than or equal to two (2) and less or equal than 50.
+parallel. This value has to be greater than or equal to two (2) and less than or equal to 50.
This creates N instances of the same job that run in parallel. They're named
sequentially from `job_name 1/N` to `job_name N/N`.
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index 931a7a8e6d5..e65c5f05505 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -55,7 +55,7 @@ GitLab can be considered to have two layers from a process perspective:
### gitaly
-- [Omnibus confiugration options](https://gitlab.com/gitlab-org/gitaly/tree/master/doc/configuration)
+- [Omnibus configuration options](https://gitlab.com/gitlab-org/gitaly/tree/master/doc/configuration)
- Layer: Core Service (Data)
Gitaly is a service designed by GitLab to remove our need for NFS for Git storage in distributed deployments of GitLab. (Think GitLab.com or High Availablity Deployments) As of 11.3.0, This service handles all Git level access in GitLab. You can read more about the project [in the project's readme](https://gitlab.com/gitlab-org/gitaly).
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index 6bb2e236dc1..a8b088395aa 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -479,14 +479,23 @@ no longer be valid as soon as the deployment job finishes. This means that
Kubernetes can run the application, but in case it should be restarted or
executed somewhere else, it cannot be accessed again.
+#### Migrations
+
> [Introduced][ce-21955] in GitLab 11.4
Database initialization and migrations for PostgreSQL can be configured to run
within the application pod by setting the project variables `DB_INITIALIZE` and
`DB_MIGRATE` respectively.
-If present, `DB_INITIALIZE` will be run as a shell command within an application pod as a helm
-post-install hook. Note that this means that if any deploy succeeds,
+If present, `DB_INITIALIZE` will be run as a shell command within an
+application pod as a helm post-install hook. As some applications will
+not run without a successful database initialization step, GitLab will
+deploy the first release without the application deployment and only the
+database initialization step. After the database initialization completes,
+GitLab will deploy a second release with the application deployment as
+normal.
+
+Note that a post-install hook means that if any deploy succeeds,
`DB_INITIALIZE` will not be processed thereafter.
If present, `DB_MIGRATE` will be run as a shell command within an application pod as
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index 6c6119a2691..debebd4c081 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -1022,7 +1022,7 @@ A link starting with a `/` is relative to the wiki root.
[rouge]: http://rouge.jneen.net/ "Rouge website"
[redcarpet]: https://github.com/vmg/redcarpet "Redcarpet website"
[katex]: https://github.com/Khan/KaTeX "KaTeX website"
-[katex-subset]: https://github.com/Khan/KaTeX/wiki/Function-Support-in-KaTeX "Macros supported by KaTeX"
+[katex-subset]: https://katex.org/docs/supported.html "Macros supported by KaTeX"
[asciidoctor-manual]: http://asciidoctor.org/docs/user-manual/#activating-stem-support "Asciidoctor user manual"
[commonmarker]: https://github.com/gjtorikian/commonmarker
[commonmark-spec]: https://spec.commonmark.org/current/
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
index c90976b2040..49f03d2ae19 100644
--- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -658,6 +658,7 @@ rollout 100%:
fi
if [[ -n "$DB_INITIALIZE" && -z "$(helm ls -q "^$name$")" ]]; then
+ echo "Deploying first release with database initialization..."
helm upgrade --install \
--wait \
--set service.enabled="$service_enabled" \
@@ -680,6 +681,7 @@ rollout 100%:
"$name" \
chart/
+ echo "Deploying second release..."
helm upgrade --reuse-values \
--wait \
--set application.initializeCommand="" \
@@ -688,6 +690,7 @@ rollout 100%:
"$name" \
chart/
else
+ echo "Deploying new release..."
helm upgrade --install \
--wait \
--set service.enabled="$service_enabled" \
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 3769dfab143..60274d883fa 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -4297,9 +4297,6 @@ msgstr ""
msgid "No"
msgstr ""
-msgid "No Label"
-msgstr ""
-
msgid "No assignee"
msgstr ""
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
index 1b585bcd4c6..ac92b2ca657 100644
--- a/spec/controllers/application_controller_spec.rb
+++ b/spec/controllers/application_controller_spec.rb
@@ -114,7 +114,7 @@ describe ApplicationController do
skip_before_action :authenticate_user!, only: :index
def index
- render text: 'authenticated'
+ render html: 'authenticated'
end
end
@@ -401,7 +401,7 @@ describe ApplicationController do
context 'terms' do
controller(described_class) do
def index
- render text: 'authenticated'
+ render html: 'authenticated'
end
end
@@ -444,7 +444,7 @@ describe ApplicationController do
attr_reader :last_payload
def index
- render text: 'authenticated'
+ render html: 'authenticated'
end
def append_info_to_payload(payload)
diff --git a/spec/features/boards/modal_filter_spec.rb b/spec/features/boards/modal_filter_spec.rb
index 2cdd3f55b50..d96707e55fd 100644
--- a/spec/features/boards/modal_filter_spec.rb
+++ b/spec/features/boards/modal_filter_spec.rb
@@ -176,7 +176,7 @@ describe 'Issue Boards add issue modal filtering', :js do
it 'filters by no label' do
set_filter('label')
- click_filter_link('No Label')
+ click_filter_link('None')
submit_filter
page.within('.add-issues-modal') do
diff --git a/spec/features/issues/filtered_search/dropdown_label_spec.rb b/spec/features/issues/filtered_search/dropdown_label_spec.rb
index ca5d506ab04..b25b1514d62 100644
--- a/spec/features/issues/filtered_search/dropdown_label_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_label_spec.rb
@@ -45,7 +45,8 @@ describe 'Dropdown label', :js do
bug_label = create(:label, project: project, title: 'bug-label')
init_label_search
- filtered_search.native.send_keys(:down, :down, :enter)
+ # navigate to the bug_label option and selects it
+ filtered_search.native.send_keys(:down, :down, :down, :enter)
expect_tokens([label_token(bug_label.title)])
expect_filtered_search_input_empty
@@ -234,12 +235,20 @@ describe 'Dropdown label', :js do
end
it 'selects `no label`' do
- find("#{js_dropdown_label} .filter-dropdown-item", text: 'No Label').click
+ find("#{js_dropdown_label} .filter-dropdown-item", text: 'None').click
expect(page).not_to have_css(js_dropdown_label)
expect_tokens([label_token('none', false)])
expect_filtered_search_input_empty
end
+
+ it 'selects `any label`' do
+ find("#{js_dropdown_label} .filter-dropdown-item", text: 'Any').click
+
+ expect(page).not_to have_css(js_dropdown_label)
+ expect_tokens([label_token('any', false)])
+ expect_filtered_search_input_empty
+ end
end
describe 'input has existing content' do
diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb
index 35d57b3896d..4d9b8262f21 100644
--- a/spec/features/issues/filtered_search/filter_issues_spec.rb
+++ b/spec/features/issues/filtered_search/filter_issues_spec.rb
@@ -430,10 +430,10 @@ describe 'Filter issues', :js do
expect_issues_list_count(2)
- sort_toggle = find('.filtered-search-wrapper .dropdown-toggle')
+ sort_toggle = find('.filter-dropdown-container .dropdown-menu-toggle')
sort_toggle.click
- find('.filtered-search-wrapper .dropdown-menu li a', text: 'Created date').click
+ find('.filter-dropdown-container .dropdown-menu li a', text: 'Created date').click
wait_for_requests
expect(find('.issues-list .issue:first-of-type .issue-title-text a')).to have_content(new_issue.title)
diff --git a/spec/features/issues/user_sorts_issues_spec.rb b/spec/features/issues/user_sorts_issues_spec.rb
index 4771d2c6d28..3bc93933183 100644
--- a/spec/features/issues/user_sorts_issues_spec.rb
+++ b/spec/features/issues/user_sorts_issues_spec.rb
@@ -20,7 +20,7 @@ describe "User sorts issues" do
end
it 'keeps the sort option' do
- find('button.dropdown-toggle').click
+ find('.filter-dropdown-container button.dropdown-menu-toggle').click
page.within('.content ul.dropdown-menu.dropdown-menu-right li') do
click_link('Milestone')
@@ -40,7 +40,7 @@ describe "User sorts issues" do
end
it "sorts by popularity" do
- find("button.dropdown-toggle").click
+ find(".filter-dropdown-container button.dropdown-menu-toggle").click
page.within(".content ul.dropdown-menu.dropdown-menu-right li") do
click_link("Popularity")
diff --git a/spec/features/merge_request/user_sees_deployment_widget_spec.rb b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
index 3e40179ad9a..fe8e0b07d39 100644
--- a/spec/features/merge_request/user_sees_deployment_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_deployment_widget_spec.rb
@@ -29,6 +29,22 @@ describe 'Merge request > User sees deployment widget', :js do
expect(page).to have_content("Deployed to #{environment.name}")
expect(find('.js-deploy-time')['data-original-title']).to eq(deployment.created_at.to_time.in_time_zone.to_s(:medium))
end
+
+ context 'when a user created a new merge request with the same SHA' do
+ let(:pipeline2) { create(:ci_pipeline_without_jobs, sha: sha, project: project, ref: 'new-patch-1') }
+ let(:build2) { create(:ci_build, :success, pipeline: pipeline2) }
+ let(:environment2) { create(:environment, project: project) }
+ let!(:deployment2) { create(:deployment, environment: environment2, sha: sha, ref: 'new-patch-1', deployable: build2) }
+
+ it 'displays one environment which is related to the pipeline' do
+ visit project_merge_request_path(project, merge_request)
+ wait_for_requests
+
+ expect(page).to have_selector('.js-deployment-info', count: 1)
+ expect(page).to have_content("#{environment.name}")
+ expect(page).not_to have_content("#{environment2.name}")
+ end
+ end
end
context 'when deployment failed' do
diff --git a/spec/features/merge_request/user_sees_merge_widget_spec.rb b/spec/features/merge_request/user_sees_merge_widget_spec.rb
index 582be101399..d8ebd3c92af 100644
--- a/spec/features/merge_request/user_sees_merge_widget_spec.rb
+++ b/spec/features/merge_request/user_sees_merge_widget_spec.rb
@@ -60,7 +60,7 @@ describe 'Merge request > User sees merge widget', :js do
it 'shows environments link' do
wait_for_requests
- page.within('.js-pre-merge-deploy') do
+ page.within('.js-pre-deployment') do
expect(page).to have_content("Deployed to #{environment.name}")
expect(find('.js-deploy-url')[:href]).to include(environment.formatted_external_url)
end
diff --git a/spec/features/merge_requests/user_sorts_merge_requests_spec.rb b/spec/features/merge_requests/user_sorts_merge_requests_spec.rb
index e163868e8e7..61e8f1c4662 100644
--- a/spec/features/merge_requests/user_sorts_merge_requests_spec.rb
+++ b/spec/features/merge_requests/user_sorts_merge_requests_spec.rb
@@ -19,7 +19,7 @@ describe 'User sorts merge requests' do
end
it 'keeps the sort option' do
- find('button.dropdown-toggle').click
+ find('.filter-dropdown-container button.dropdown-menu-toggle').click
page.within('.content ul.dropdown-menu.dropdown-menu-right li') do
click_link('Milestone')
@@ -49,7 +49,7 @@ describe 'User sorts merge requests' do
it 'separates remember sorting with issues' do
create(:issue, project: project)
- find('button.dropdown-toggle').click
+ find('.filter-dropdown-container button.dropdown-menu-toggle').click
page.within('.content ul.dropdown-menu.dropdown-menu-right li') do
click_link('Milestone')
@@ -70,7 +70,7 @@ describe 'User sorts merge requests' do
end
it 'sorts by popularity' do
- find('button.dropdown-toggle').click
+ find('.filter-dropdown-container button.dropdown-menu-toggle').click
page.within('.content ul.dropdown-menu.dropdown-menu-right li') do
click_link('Popularity')
diff --git a/spec/features/projects/labels/issues_sorted_by_priority_spec.rb b/spec/features/projects/labels/issues_sorted_by_priority_spec.rb
index 6178f11ded7..b778c72bc76 100644
--- a/spec/features/projects/labels/issues_sorted_by_priority_spec.rb
+++ b/spec/features/projects/labels/issues_sorted_by_priority_spec.rb
@@ -32,7 +32,7 @@ describe 'Issue prioritization' do
visit project_issues_path(project, sort: 'label_priority')
# Ensure we are indicating that issues are sorted by priority
- expect(page).to have_selector('.dropdown-toggle', text: 'Label priority')
+ expect(page).to have_selector('.dropdown-menu-toggle', text: 'Label priority')
page.within('.issues-holder') do
issue_titles = all('.issues-list .issue-title-text').map(&:text)
@@ -70,7 +70,7 @@ describe 'Issue prioritization' do
sign_in user
visit project_issues_path(project, sort: 'label_priority')
- expect(page).to have_selector('.dropdown-toggle', text: 'Label priority')
+ expect(page).to have_selector('.dropdown-menu-toggle', text: 'Label priority')
page.within('.issues-holder') do
issue_titles = all('.issues-list .issue-title-text').map(&:text)
diff --git a/spec/features/projects/settings/repository_settings_spec.rb b/spec/features/projects/settings/repository_settings_spec.rb
index 401aac9478d..b7a22316d26 100644
--- a/spec/features/projects/settings/repository_settings_spec.rb
+++ b/spec/features/projects/settings/repository_settings_spec.rb
@@ -133,18 +133,49 @@ describe 'Projects > Settings > Repository settings' do
expect(page).to have_selector('#mirror_direction')
end
+ it 'creates a push mirror that mirrors all branches', :js do
+ expect(find('.js-mirror-protected-hidden', visible: false).value).to eq('0')
+
+ fill_in 'url', with: 'ssh://user@localhost/project.git'
+ select 'SSH public key', from: 'Authentication method'
+
+ select_direction
+
+ Sidekiq::Testing.fake! do
+ click_button 'Mirror repository'
+ end
+
+ project.reload
+
+ expect(page).to have_content('Mirroring settings were successfully updated')
+ expect(project.remote_mirrors.first.only_protected_branches).to eq(false)
+ end
+
+ it 'creates a push mirror that only mirrors protected branches', :js do
+ find('#only_protected_branches').click
+
+ expect(find('.js-mirror-protected-hidden', visible: false).value).to eq('1')
+
+ fill_in 'url', with: 'ssh://user@localhost/project.git'
+ select 'SSH public key', from: 'Authentication method'
+
+ select_direction
+
+ Sidekiq::Testing.fake! do
+ click_button 'Mirror repository'
+ end
+
+ project.reload
+
+ expect(page).to have_content('Mirroring settings were successfully updated')
+ expect(project.remote_mirrors.first.only_protected_branches).to eq(true)
+ end
+
it 'generates an SSH public key on submission', :js do
fill_in 'url', with: 'ssh://user@localhost/project.git'
select 'SSH public key', from: 'Authentication method'
- direction_select = find('#mirror_direction')
-
- # In CE, this select box is disabled, but in EE, it is enabled
- if direction_select.disabled?
- expect(direction_select.value).to eq('push')
- else
- direction_select.select('Push')
- end
+ select_direction
Sidekiq::Testing.fake! do
click_button 'Mirror repository'
@@ -153,6 +184,17 @@ describe 'Projects > Settings > Repository settings' do
expect(page).to have_content('Mirroring settings were successfully updated')
expect(page).to have_selector('[title="Copy SSH public key"]')
end
+
+ def select_direction(direction = 'push')
+ direction_select = find('#mirror_direction')
+
+ # In CE, this select box is disabled, but in EE, it is enabled
+ if direction_select.disabled?
+ expect(direction_select.value).to eq(direction)
+ else
+ direction_select.select(direction.capitalize)
+ end
+ end
end
end
end
diff --git a/spec/fixtures/security-reports/feature-branch/gl-dependency-scanning-report.json b/spec/fixtures/security-reports/feature-branch/gl-dependency-scanning-report.json
index 4b47e259c0f..314f04107eb 100644
--- a/spec/fixtures/security-reports/feature-branch/gl-dependency-scanning-report.json
+++ b/spec/fixtures/security-reports/feature-branch/gl-dependency-scanning-report.json
@@ -1,46 +1,154 @@
[
{
- "priority": "Unknown",
- "file": "pom.xml",
- "cve": "CVE-2012-4387",
- "url": "http://struts.apache.org/docs/s2-011.html",
- "message": "Long parameter name DoS for org.apache.struts/struts2-core",
- "tools": [
- "gemnasium"
+ "category": "dependency_scanning",
+ "name": "io.netty/netty - CVE-2014-3488",
+ "message": "DoS by CPU exhaustion when using malicious SSL packets",
+ "cve": "app/pom.xml:io.netty/netty@3.9.1.Final:CVE-2014-3488",
+ "severity": "Unknown",
+ "solution": "Upgrade to the latest version",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "app/pom.xml"
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-d1bf36d9-9f07-46cd-9cfc-8675338ada8f",
+ "value": "d1bf36d9-9f07-46cd-9cfc-8675338ada8f",
+ "url": "https://deps.sec.gitlab.com/packages/maven/io.netty/netty/versions/3.9.1.Final/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2014-3488",
+ "value": "CVE-2014-3488",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3488"
+ }
],
+ "links": [
+ {
+ "url": "https://bugzilla.redhat.com/CVE-2014-3488"
+ },
+ {
+ "url": "http://netty.io/news/2014/06/11/3.html"
+ },
+ {
+ "url": "https://github.com/netty/netty/issues/2562"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "app/pom.xml",
+ "url": "https://bugzilla.redhat.com/CVE-2014-3488",
"tool": "gemnasium"
},
{
- "priority": "Unknown",
- "file": "pom.xml",
- "cve": "CVE-2013-1966",
- "url": "http://struts.apache.org/docs/s2-014.html",
- "message": "Remote command execution due to flaw in the includeParams attribute of URL and Anchor tags for org.apache.struts/struts2-core",
- "tools": [
- "gemnasium"
+ "category": "dependency_scanning",
+ "name": "Django - CVE-2017-12794",
+ "message": "Possible XSS in traceback section of technical 500 debug page",
+ "cve": "app/requirements.txt:Django@1.11.3:CVE-2017-12794",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest version or apply patch.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "app/requirements.txt"
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-6162a015-8635-4a15-8d7c-dc9321db366f",
+ "value": "6162a015-8635-4a15-8d7c-dc9321db366f",
+ "url": "https://deps.sec.gitlab.com/packages/pypi/Django/versions/1.11.3/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2017-12794",
+ "value": "CVE-2017-12794",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-12794"
+ }
],
+ "links": [
+ {
+ "url": "https://www.djangoproject.com/weblog/2017/sep/05/security-releases/"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "app/requirements.txt",
+ "url": "https://www.djangoproject.com/weblog/2017/sep/05/security-releases/",
"tool": "gemnasium"
},
{
- "priority": "Unknown",
- "file": "pom.xml",
- "cve": "CVE-2013-2115",
- "url": "http://struts.apache.org/docs/s2-014.html",
- "message": "Remote command execution due to flaw in the includeParams attribute of URL and Anchor tags for org.apache.struts/struts2-core",
- "tools": [
- "gemnasium"
+ "category": "dependency_scanning",
+ "name": "nokogiri - USN-3424-1",
+ "message": "Vulnerabilities in libxml2",
+ "cve": "rails/Gemfile.lock:nokogiri@1.8.0:USN-3424-1",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest version.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "rails/Gemfile.lock"
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-06565b64-486d-4326-b906-890d9915804d",
+ "value": "06565b64-486d-4326-b906-890d9915804d",
+ "url": "https://deps.sec.gitlab.com/packages/gem/nokogiri/versions/1.8.0/advisories"
+ },
+ {
+ "type": "usn",
+ "name": "USN-3424-1",
+ "value": "USN-3424-1",
+ "url": "https://usn.ubuntu.com/3424-1/"
+ }
],
+ "links": [
+ {
+ "url": "https://github.com/sparklemotion/nokogiri/issues/1673"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "rails/Gemfile.lock",
+ "url": "https://github.com/sparklemotion/nokogiri/issues/1673",
"tool": "gemnasium"
},
{
- "priority": "Unknown",
- "file": "pom.xml",
- "cve": "CVE-2013-2134",
- "url": "http://struts.apache.org/docs/s2-015.html",
- "message": "Arbitrary OGNL code execution via unsanitized wildcard matching for org.apache.struts/struts2-core",
- "tools": [
- "gemnasium"
+ "category": "dependency_scanning",
+ "name": "ffi - CVE-2018-1000201",
+ "message": "ruby-ffi DDL loading issue on Windows OS",
+ "cve": "ffi:1.9.18:CVE-2018-1000201",
+ "severity": "High",
+ "solution": "upgrade to \u003e= 1.9.24",
+ "scanner": {
+ "id": "bundler_audit",
+ "name": "bundler-audit"
+ },
+ "location": {
+ "file": "sast-sample-rails/Gemfile.lock"
+ },
+ "identifiers": [
+ {
+ "type": "cve",
+ "name": "CVE-2018-1000201",
+ "value": "CVE-2018-1000201",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-1000201"
+ }
],
- "tool": "gemnasium"
+ "links": [
+ {
+ "url": "https://github.com/ffi/ffi/releases/tag/1.9.24"
+ }
+ ],
+ "priority": "High",
+ "file": "sast-sample-rails/Gemfile.lock",
+ "url": "https://github.com/ffi/ffi/releases/tag/1.9.24",
+ "tool": "bundler_audit"
}
]
diff --git a/spec/fixtures/security-reports/master/gl-dependency-scanning-report.json b/spec/fixtures/security-reports/master/gl-dependency-scanning-report.json
index b4e4e8e7dd5..314f04107eb 100644
--- a/spec/fixtures/security-reports/master/gl-dependency-scanning-report.json
+++ b/spec/fixtures/security-reports/master/gl-dependency-scanning-report.json
@@ -1,35 +1,154 @@
[
{
- "priority": "Unknown",
- "file": "pom.xml",
- "cve": "CVE-2012-4386",
- "url": "http://struts.apache.org/docs/s2-010.html",
- "message": "CSRF protection bypass for org.apache.struts/struts2-core",
- "tools": [
- "gemnasium"
+ "category": "dependency_scanning",
+ "name": "io.netty/netty - CVE-2014-3488",
+ "message": "DoS by CPU exhaustion when using malicious SSL packets",
+ "cve": "app/pom.xml:io.netty/netty@3.9.1.Final:CVE-2014-3488",
+ "severity": "Unknown",
+ "solution": "Upgrade to the latest version",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "app/pom.xml"
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-d1bf36d9-9f07-46cd-9cfc-8675338ada8f",
+ "value": "d1bf36d9-9f07-46cd-9cfc-8675338ada8f",
+ "url": "https://deps.sec.gitlab.com/packages/maven/io.netty/netty/versions/3.9.1.Final/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2014-3488",
+ "value": "CVE-2014-3488",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-3488"
+ }
],
+ "links": [
+ {
+ "url": "https://bugzilla.redhat.com/CVE-2014-3488"
+ },
+ {
+ "url": "http://netty.io/news/2014/06/11/3.html"
+ },
+ {
+ "url": "https://github.com/netty/netty/issues/2562"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "app/pom.xml",
+ "url": "https://bugzilla.redhat.com/CVE-2014-3488",
"tool": "gemnasium"
},
{
- "priority": "Unknown",
- "file": "pom.xml",
- "cve": "CVE-2012-4387",
- "url": "http://struts.apache.org/docs/s2-011.html",
- "message": "Long parameter name DoS for org.apache.struts/struts2-core",
- "tools": [
- "gemnasium"
+ "category": "dependency_scanning",
+ "name": "Django - CVE-2017-12794",
+ "message": "Possible XSS in traceback section of technical 500 debug page",
+ "cve": "app/requirements.txt:Django@1.11.3:CVE-2017-12794",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest version or apply patch.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "app/requirements.txt"
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-6162a015-8635-4a15-8d7c-dc9321db366f",
+ "value": "6162a015-8635-4a15-8d7c-dc9321db366f",
+ "url": "https://deps.sec.gitlab.com/packages/pypi/Django/versions/1.11.3/advisories"
+ },
+ {
+ "type": "cve",
+ "name": "CVE-2017-12794",
+ "value": "CVE-2017-12794",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-12794"
+ }
],
+ "links": [
+ {
+ "url": "https://www.djangoproject.com/weblog/2017/sep/05/security-releases/"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "app/requirements.txt",
+ "url": "https://www.djangoproject.com/weblog/2017/sep/05/security-releases/",
"tool": "gemnasium"
},
{
- "priority": "Unknown",
- "file": "pom.xml",
- "cve": "CVE-2013-1966",
- "url": "http://struts.apache.org/docs/s2-014.html",
- "message": "Remote command execution due to flaw in the includeParams attribute of URL and Anchor tags for org.apache.struts/struts2-core",
- "tools": [
- "gemnasium"
+ "category": "dependency_scanning",
+ "name": "nokogiri - USN-3424-1",
+ "message": "Vulnerabilities in libxml2",
+ "cve": "rails/Gemfile.lock:nokogiri@1.8.0:USN-3424-1",
+ "severity": "Unknown",
+ "solution": "Upgrade to latest version.",
+ "scanner": {
+ "id": "gemnasium",
+ "name": "Gemnasium"
+ },
+ "location": {
+ "file": "rails/Gemfile.lock"
+ },
+ "identifiers": [
+ {
+ "type": "gemnasium",
+ "name": "Gemnasium-06565b64-486d-4326-b906-890d9915804d",
+ "value": "06565b64-486d-4326-b906-890d9915804d",
+ "url": "https://deps.sec.gitlab.com/packages/gem/nokogiri/versions/1.8.0/advisories"
+ },
+ {
+ "type": "usn",
+ "name": "USN-3424-1",
+ "value": "USN-3424-1",
+ "url": "https://usn.ubuntu.com/3424-1/"
+ }
],
+ "links": [
+ {
+ "url": "https://github.com/sparklemotion/nokogiri/issues/1673"
+ }
+ ],
+ "priority": "Unknown",
+ "file": "rails/Gemfile.lock",
+ "url": "https://github.com/sparklemotion/nokogiri/issues/1673",
"tool": "gemnasium"
+ },
+ {
+ "category": "dependency_scanning",
+ "name": "ffi - CVE-2018-1000201",
+ "message": "ruby-ffi DDL loading issue on Windows OS",
+ "cve": "ffi:1.9.18:CVE-2018-1000201",
+ "severity": "High",
+ "solution": "upgrade to \u003e= 1.9.24",
+ "scanner": {
+ "id": "bundler_audit",
+ "name": "bundler-audit"
+ },
+ "location": {
+ "file": "sast-sample-rails/Gemfile.lock"
+ },
+ "identifiers": [
+ {
+ "type": "cve",
+ "name": "CVE-2018-1000201",
+ "value": "CVE-2018-1000201",
+ "url": "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-1000201"
+ }
+ ],
+ "links": [
+ {
+ "url": "https://github.com/ffi/ffi/releases/tag/1.9.24"
+ }
+ ],
+ "priority": "High",
+ "file": "sast-sample-rails/Gemfile.lock",
+ "url": "https://github.com/ffi/ffi/releases/tag/1.9.24",
+ "tool": "bundler_audit"
}
]
diff --git a/spec/javascripts/pipelines/graph/job_item_spec.js b/spec/javascripts/pipelines/graph/job_item_spec.js
index 88e1789184d..1cdb0aff524 100644
--- a/spec/javascripts/pipelines/graph/job_item_spec.js
+++ b/spec/javascripts/pipelines/graph/job_item_spec.js
@@ -139,57 +139,17 @@ describe('pipeline graph job item', () => {
});
});
- describe('tooltip placement', () => {
- it('does not set tooltip boundary by default', () => {
- component = mountComponent(JobComponent, {
- job: mockJob,
- });
-
- expect(component.tooltipBoundary).toBeNull();
- });
-
- it('sets tooltip boundary to viewport for small dropdowns', () => {
- component = mountComponent(JobComponent, {
- job: mockJob,
- dropdownLength: 1,
- });
-
- expect(component.tooltipBoundary).toEqual('viewport');
- });
-
- it('does not set tooltip boundary for large lists', () => {
- component = mountComponent(JobComponent, {
- job: mockJob,
- dropdownLength: 7,
- });
-
- expect(component.tooltipBoundary).toBeNull();
- });
- });
-
describe('for delayed job', () => {
- beforeEach(() => {
- const fifteenMinutesInMilliseconds = 900000;
- spyOn(Date, 'now').and.callFake(
- () => new Date(delayedJobFixture.scheduled_at).getTime() - fifteenMinutesInMilliseconds,
- );
- });
-
- it('displays remaining time in tooltip', done => {
+ it('displays remaining time in tooltip', () => {
component = mountComponent(JobComponent, {
job: delayedJobFixture,
});
- Vue.nextTick()
- .then(() => {
- expect(
- component.$el
- .querySelector('.js-pipeline-graph-job-link')
- .getAttribute('data-original-title'),
- ).toEqual('delayed job - delayed manual action (00:15:00)');
- })
- .then(done)
- .catch(done.fail);
+ expect(
+ component.$el
+ .querySelector('.js-pipeline-graph-job-link')
+ .getAttribute('data-original-title'),
+ ).toEqual(`delayed job - delayed manual action (${component.remainingTime})`);
});
});
});
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_container_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_container_spec.js
new file mode 100644
index 00000000000..16c8c939a6f
--- /dev/null
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_container_spec.js
@@ -0,0 +1,51 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import MrWidgetContainer from '~/vue_merge_request_widget/components/mr_widget_container.vue';
+
+const BODY_HTML = '
Hello World
';
+const FOOTER_HTML = '';
+
+describe('MrWidgetContainer', () => {
+ let wrapper;
+
+ const factory = (options = {}) => {
+ const localVue = createLocalVue();
+
+ wrapper = shallowMount(localVue.extend(MrWidgetContainer), {
+ localVue,
+ ...options,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('has layout', () => {
+ factory();
+
+ expect(wrapper.is('.mr-widget-heading')).toBe(true);
+ expect(wrapper.contains('.mr-widget-content')).toBe(true);
+ });
+
+ it('accepts default slot', () => {
+ factory({
+ slots: {
+ default: BODY_HTML,
+ },
+ });
+
+ expect(wrapper.contains('.mr-widget-content .test-body')).toBe(true);
+ });
+
+ it('accepts footer slot', () => {
+ factory({
+ slots: {
+ default: BODY_HTML,
+ footer: FOOTER_HTML,
+ },
+ });
+
+ expect(wrapper.contains('.mr-widget-content .test-body')).toBe(true);
+ expect(wrapper.contains('.test-footer')).toBe(true);
+ });
+});
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_icon_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_icon_spec.js
new file mode 100644
index 00000000000..f7c2376eebf
--- /dev/null
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_icon_spec.js
@@ -0,0 +1,30 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import MrWidgetIcon from '~/vue_merge_request_widget/components/mr_widget_icon.vue';
+import Icon from '~/vue_shared/components/icon.vue';
+
+const TEST_ICON = 'commit';
+
+describe('MrWidgetIcon', () => {
+ let wrapper;
+
+ beforeEach(() => {
+ const localVue = createLocalVue();
+
+ wrapper = shallowMount(localVue.extend(MrWidgetIcon), {
+ propsData: {
+ name: TEST_ICON,
+ },
+ sync: false,
+ localVue,
+ });
+ });
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ it('renders icon and container', () => {
+ expect(wrapper.is('.circle-icon-container')).toBe(true);
+ expect(wrapper.find(Icon).props('name')).toEqual(TEST_ICON);
+ });
+});
diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js
new file mode 100644
index 00000000000..e5155573f6f
--- /dev/null
+++ b/spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_container_spec.js
@@ -0,0 +1,90 @@
+import { shallowMount, createLocalVue } from '@vue/test-utils';
+import MrWidgetPipelineContainer from '~/vue_merge_request_widget/components/mr_widget_pipeline_container.vue';
+import MrWidgetPipeline from '~/vue_merge_request_widget/components/mr_widget_pipeline.vue';
+import { mockStore } from '../mock_data';
+
+describe('MrWidgetPipelineContainer', () => {
+ let wrapper;
+
+ const factory = (props = {}) => {
+ const localVue = createLocalVue();
+
+ wrapper = shallowMount(localVue.extend(MrWidgetPipelineContainer), {
+ propsData: {
+ mr: Object.assign({}, mockStore),
+ ...props,
+ },
+ localVue,
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('when pre merge', () => {
+ beforeEach(() => {
+ factory();
+ });
+
+ it('renders pipeline', () => {
+ expect(wrapper.find(MrWidgetPipeline).exists()).toBe(true);
+ expect(wrapper.find(MrWidgetPipeline).props()).toEqual(
+ jasmine.objectContaining({
+ pipeline: mockStore.pipeline,
+ ciStatus: mockStore.ciStatus,
+ hasCi: mockStore.hasCI,
+ sourceBranch: mockStore.sourceBranch,
+ sourceBranchLink: mockStore.sourceBranchLink,
+ }),
+ );
+ });
+
+ it('renders deployments', () => {
+ const expectedProps = mockStore.deployments.map(dep =>
+ jasmine.objectContaining({
+ deployment: dep,
+ showMetrics: false,
+ }),
+ );
+
+ const deployments = wrapper.findAll('.mr-widget-extension .js-pre-deployment');
+
+ expect(deployments.wrappers.map(x => x.props())).toEqual(expectedProps);
+ });
+ });
+
+ describe('when post merge', () => {
+ beforeEach(() => {
+ factory({
+ isPostMerge: true,
+ });
+ });
+
+ it('renders pipeline', () => {
+ expect(wrapper.find(MrWidgetPipeline).exists()).toBe(true);
+ expect(wrapper.find(MrWidgetPipeline).props()).toEqual(
+ jasmine.objectContaining({
+ pipeline: mockStore.mergePipeline,
+ ciStatus: mockStore.ciStatus,
+ hasCi: mockStore.hasCI,
+ sourceBranch: mockStore.targetBranch,
+ sourceBranchLink: mockStore.targetBranch,
+ }),
+ );
+ });
+
+ it('renders deployments', () => {
+ const expectedProps = mockStore.postMergeDeployments.map(dep =>
+ jasmine.objectContaining({
+ deployment: dep,
+ showMetrics: true,
+ }),
+ );
+
+ const deployments = wrapper.findAll('.mr-widget-extension .js-post-deployment');
+
+ expect(deployments.wrappers.map(x => x.props())).toEqual(expectedProps);
+ });
+ });
+});
diff --git a/spec/javascripts/vue_mr_widget/mock_data.js b/spec/javascripts/vue_mr_widget/mock_data.js
index 17554c4fe42..072e98fc0e8 100644
--- a/spec/javascripts/vue_mr_widget/mock_data.js
+++ b/spec/javascripts/vue_mr_widget/mock_data.js
@@ -222,3 +222,16 @@ export default {
'http://localhost:3000/root/acets-app/commit/53027d060246c8f47e4a9310fb332aa52f221775',
troubleshooting_docs_path: 'help',
};
+
+export const mockStore = {
+ pipeline: { id: 0 },
+ mergePipeline: { id: 1 },
+ targetBranch: 'target-branch',
+ sourceBranch: 'source-branch',
+ sourceBranchLink: 'source-branch-link',
+ deployments: [{ id: 0, name: 'bogus' }, { id: 1, name: 'bogus-docs' }],
+ postMergeDeployments: [{ id: 0, name: 'prod' }, { id: 1, name: 'prod-docs' }],
+ troubleshootingDocsPath: 'troubleshooting-docs-path',
+ ciStatus: 'ci-status',
+ hasCI: true,
+};
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index 8d2f60d7a8b..31ab11bbf8d 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -121,6 +121,8 @@ pipelines:
- artifacts
- pipeline_schedule
- merge_requests
+- deployments
+- environments
pipeline_variables:
- pipeline
stages:
diff --git a/spec/models/environment_status_spec.rb b/spec/models/environment_status_spec.rb
index 90f7e4a4590..9da16dea929 100644
--- a/spec/models/environment_status_spec.rb
+++ b/spec/models/environment_status_spec.rb
@@ -92,16 +92,12 @@ describe EnvironmentStatus do
end
describe '.build_environments_status' do
- subject { described_class.send(:build_environments_status, merge_request, user, sha) }
+ subject { described_class.send(:build_environments_status, merge_request, user, pipeline) }
let!(:build) { create(:ci_build, :deploy_to_production, pipeline: pipeline) }
let(:environment) { build.deployment.environment }
let(:user) { project.owner }
- before do
- build.deployment&.update!(sha: sha)
- end
-
context 'when environment is created on a forked project' do
let(:project) { create(:project, :repository) }
let(:forked) { fork_project(project, user, repository: true) }
@@ -160,6 +156,39 @@ describe EnvironmentStatus do
expect(subject.count).to eq(0)
end
end
+
+ context 'when multiple deployments with the same SHA in different environments' do
+ let(:pipeline2) { create(:ci_pipeline, sha: sha, project: project) }
+ let!(:build2) { create(:ci_build, :start_review_app, pipeline: pipeline2) }
+
+ it 'returns deployments related to the head pipeline' do
+ expect(subject.count).to eq(1)
+ expect(subject[0].environment).to eq(environment)
+ expect(subject[0].merge_request).to eq(merge_request)
+ expect(subject[0].sha).to eq(sha)
+ end
+ end
+
+ context 'when multiple deployments in the same pipeline for the same environments' do
+ let!(:build2) { create(:ci_build, :deploy_to_production, pipeline: pipeline) }
+
+ it 'returns unique entries' do
+ expect(subject.count).to eq(1)
+ expect(subject[0].environment).to eq(environment)
+ expect(subject[0].merge_request).to eq(merge_request)
+ expect(subject[0].sha).to eq(sha)
+ end
+ end
+
+ context 'when environment is stopped' do
+ before do
+ environment.stop!
+ end
+
+ it 'does not return environment status' do
+ expect(subject.count).to eq(0)
+ end
+ end
end
end
end
diff --git a/spec/support/helpers/features/sorting_helpers.rb b/spec/support/helpers/features/sorting_helpers.rb
index ad0053ec5cf..a1ae428586e 100644
--- a/spec/support/helpers/features/sorting_helpers.rb
+++ b/spec/support/helpers/features/sorting_helpers.rb
@@ -13,7 +13,7 @@ module Spec
module Features
module SortingHelpers
def sort_by(value)
- find('button.dropdown-toggle').click
+ find('.filter-dropdown-container button.dropdown-menu-toggle').click
page.within('.content ul.dropdown-menu.dropdown-menu-right li') do
click_link(value)
diff --git a/spec/support/helpers/sorting_helper.rb b/spec/support/helpers/sorting_helper.rb
index 9496a94d8f4..e505a6b7258 100644
--- a/spec/support/helpers/sorting_helper.rb
+++ b/spec/support/helpers/sorting_helper.rb
@@ -10,7 +10,7 @@
#
module SortingHelper
def sorting_by(value)
- find('button.dropdown-toggle').click
+ find('.filter-dropdown-container button.dropdown-menu-toggle').click
page.within('.content ul.dropdown-menu.dropdown-menu-right li') do
click_link value
end
diff --git a/vendor/jupyter/values.yaml b/vendor/jupyter/values.yaml
index 24136a7aca5..781d6e3042f 100644
--- a/vendor/jupyter/values.yaml
+++ b/vendor/jupyter/values.yaml
@@ -22,3 +22,4 @@ ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: "nginx"
+ kubernetes.io/tls-acme: "true"