summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-11-07 21:06:14 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2019-11-07 21:06:14 +0000
commitc324100967bbdd3f2f0ca3406c9261d35e69f148 (patch)
treeecfd5d521d90792cbc922309e6930b1ba2badff6
parentd8ccc7a00b7a1ea954263170a2044257424a2cfe (diff)
downloadgitlab-ce-c324100967bbdd3f2f0ca3406c9261d35e69f148.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/user_popovers.js5
-rw-r--r--app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue4
-rw-r--r--app/controllers/concerns/milestone_actions.rb8
-rw-r--r--app/helpers/milestones_helper.rb50
-rw-r--r--app/models/concerns/milestoneish.rb4
-rw-r--r--app/models/dashboard_group_milestone.rb4
-rw-r--r--app/models/global_milestone.rb4
-rw-r--r--app/models/milestone.rb2
-rw-r--r--app/views/groups/milestones/show.html.haml2
-rw-r--r--app/views/projects/milestones/show.html.haml53
-rw-r--r--app/views/shared/milestones/_description.html.haml8
-rw-r--r--app/views/shared/milestones/_header.html.haml38
-rw-r--r--app/views/shared/milestones/_tabs.html.haml47
-rw-r--r--app/views/shared/milestones/_top.html.haml56
-rw-r--r--changelogs/unreleased/19445-native-group-milestone-page-needs-same-info-as-project-milestones.yml5
-rw-r--r--changelogs/unreleased/34423-user-popover-immediately-closed-when-hovering-over-certain-areas.yml5
-rw-r--r--changelogs/unreleased/34577-add-dep-scanner-var-maven.yml5
-rw-r--r--doc/topics/git/partial_clone.md20
-rw-r--r--doc/user/application_security/container_scanning/index.md43
-rw-r--r--doc/user/application_security/dependency_scanning/index.md27
-rw-r--r--doc/user/project/milestones/index.md35
-rw-r--r--lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml1
-rw-r--r--locale/gitlab.pot12
-rw-r--r--spec/features/groups/milestone_spec.rb141
-rw-r--r--spec/features/projects/milestones/milestone_spec.rb9
25 files changed, 344 insertions, 244 deletions
diff --git a/app/assets/javascripts/user_popovers.js b/app/assets/javascripts/user_popovers.js
index c0b7587be10..7d6a725b30f 100644
--- a/app/assets/javascripts/user_popovers.js
+++ b/app/assets/javascripts/user_popovers.js
@@ -73,9 +73,14 @@ const handleUserPopoverMouseOver = event => {
location: userData.location,
bio: userData.bio,
organization: userData.organization,
+ status: userData.status,
loaded: true,
});
+ if (userData.status) {
+ return Promise.resolve();
+ }
+
return UsersCache.retrieveStatusById(userId);
})
.then(status => {
diff --git a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
index 7c7d46ee759..4a72cca5f02 100644
--- a/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
+++ b/app/assets/javascripts/vue_shared/components/user_popover/user_popover.vue
@@ -51,7 +51,7 @@ export default {
</script>
<template>
- <gl-popover :target="target" boundary="viewport" placement="top" show>
+ <gl-popover :target="target" boundary="viewport" placement="top" offset="0, 1" show>
<div class="user-popover d-flex">
<div class="p-1 flex-shrink-1">
<user-avatar-image :img-src="user.avatarUrl" :size="60" css-classes="mr-2" />
@@ -90,7 +90,7 @@ export default {
name="location"
class="category-icon flex-shrink-0"
/>
- <span class="ml-1">{{ user.location }}</span>
+ <span v-if="user.location" class="ml-1">{{ user.location }}</span>
<gl-skeleton-loading
v-if="locationIsLoading"
:lines="1"
diff --git a/app/controllers/concerns/milestone_actions.rb b/app/controllers/concerns/milestone_actions.rb
index 672d31ec779..dbc575a1487 100644
--- a/app/controllers/concerns/milestone_actions.rb
+++ b/app/controllers/concerns/milestone_actions.rb
@@ -53,12 +53,10 @@ module MilestoneActions
# rubocop:disable Gitlab/ModuleWithInstanceVariables
def milestone_redirect_path
- if @project
- project_milestone_path(@project, @milestone)
- elsif @group
- group_milestone_path(@group, @milestone.safe_title, title: @milestone.title)
+ if @milestone.global_milestone?
+ url_for(action: :show, title: @milestone.title)
else
- dashboard_milestone_path(@milestone.safe_title, title: @milestone.title)
+ url_for(action: :show)
end
end
# rubocop:enable Gitlab/ModuleWithInstanceVariables
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb
index 0e9cdbf7d23..b12b39073ef 100644
--- a/app/helpers/milestones_helper.rb
+++ b/app/helpers/milestones_helper.rb
@@ -4,6 +4,18 @@ module MilestonesHelper
include EntityDateHelper
include Gitlab::Utils::StrongMemoize
+ def milestone_status_string(milestone)
+ if milestone.closed?
+ _('Closed')
+ elsif milestone.expired?
+ _('Past due')
+ elsif milestone.upcoming?
+ _('Upcoming')
+ else
+ _('Open')
+ end
+ end
+
def milestones_filter_path(opts = {})
if @project
project_milestones_path(@project, opts)
@@ -213,33 +225,19 @@ module MilestonesHelper
end
end
- def milestone_merge_request_tab_path(milestone)
- if @project
- merge_requests_project_milestone_path(@project, milestone, format: :json)
- elsif @group
- merge_requests_group_milestone_path(@group, milestone.safe_title, title: milestone.title, format: :json)
+ def milestone_tab_path(milestone, tab)
+ if milestone.global_milestone?
+ url_for(action: tab, title: milestone.title, format: :json)
else
- merge_requests_dashboard_milestone_path(milestone, title: milestone.title, format: :json)
+ url_for(action: tab, format: :json)
end
end
- def milestone_participants_tab_path(milestone)
- if @project
- participants_project_milestone_path(@project, milestone, format: :json)
- elsif @group
- participants_group_milestone_path(@group, milestone.safe_title, title: milestone.title, format: :json)
+ def update_milestone_path(milestone, params = {})
+ if milestone.project_milestone?
+ project_milestone_path(milestone.project, milestone, milestone: params)
else
- participants_dashboard_milestone_path(milestone, title: milestone.title, format: :json)
- end
- end
-
- def milestone_labels_tab_path(milestone)
- if @project
- labels_project_milestone_path(@project, milestone, format: :json)
- elsif @group
- labels_group_milestone_path(@group, milestone.safe_title, title: milestone.title, format: :json)
- else
- labels_dashboard_milestone_path(milestone, title: milestone.title, format: :json)
+ group_milestone_route(milestone, params)
end
end
@@ -264,6 +262,14 @@ module MilestonesHelper
milestone_path(milestone.milestone, params)
end
+ def edit_milestone_path(milestone)
+ if milestone.group_milestone?
+ edit_group_milestone_path(milestone.group, milestone)
+ elsif milestone.project_milestone?
+ edit_project_milestone_path(milestone.project, milestone)
+ end
+ end
+
def can_admin_project_milestones?
strong_memoize(:can_admin_project_milestones) do
can?(current_user, :admin_milestone, @project)
diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb
index 42b370990ac..b1a7d7ec819 100644
--- a/app/models/concerns/milestoneish.rb
+++ b/app/models/concerns/milestoneish.rb
@@ -101,6 +101,10 @@ module Milestoneish
false
end
+ def global_milestone?
+ false
+ end
+
def total_issue_time_spent
@total_issue_time_spent ||= issues.joins(:timelogs).sum(:time_spent)
end
diff --git a/app/models/dashboard_group_milestone.rb b/app/models/dashboard_group_milestone.rb
index ec52f1ed370..cf6094682f3 100644
--- a/app/models/dashboard_group_milestone.rb
+++ b/app/models/dashboard_group_milestone.rb
@@ -18,4 +18,8 @@ class DashboardGroupMilestone < GlobalMilestone
milestones = milestones.search_title(params[:search_title]) if params[:search_title].present?
Milestone.filter_by_state(milestones, params[:state]).map { |m| new(m) }
end
+
+ def dashboard_milestone?
+ true
+ end
end
diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb
index 61c62929b61..65fd5c1b35a 100644
--- a/app/models/global_milestone.rb
+++ b/app/models/global_milestone.rb
@@ -100,4 +100,8 @@ class GlobalMilestone
def labels
@labels ||= GlobalLabel.build_collection(milestone.labels).sort_by!(&:title)
end
+
+ def global_milestone?
+ true
+ end
end
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index a9f4cdec901..3552efbdd7b 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -330,6 +330,6 @@ class Milestone < ApplicationRecord
end
def issues_finder_params
- { project_id: project_id }
+ { project_id: project_id, group_id: group_id }.compact
end
end
diff --git a/app/views/groups/milestones/show.html.haml b/app/views/groups/milestones/show.html.haml
index 23b1a22240f..33e68bc766e 100644
--- a/app/views/groups/milestones/show.html.haml
+++ b/app/views/groups/milestones/show.html.haml
@@ -1,4 +1,4 @@
= render "header_title"
= render 'shared/milestones/top', milestone: @milestone, group: @group
-= render 'shared/milestones/tabs', milestone: @milestone, show_project_name: true if @milestone.legacy_group_milestone?
+= render 'shared/milestones/tabs', milestone: @milestone, show_project_name: true
= render 'shared/milestones/sidebar', milestone: @milestone, affix_offset: 102
diff --git a/app/views/projects/milestones/show.html.haml b/app/views/projects/milestones/show.html.haml
index 49d3039d0c9..5f244d3a6c3 100644
--- a/app/views/projects/milestones/show.html.haml
+++ b/app/views/projects/milestones/show.html.haml
@@ -3,57 +3,8 @@
- page_title @milestone.title, _('Milestones')
- page_description @milestone.description
-.detail-page-header.milestone-page-header
- .status-box{ class: status_box_class(@milestone) }
- - if @milestone.closed?
- = _('Closed')
- - elsif @milestone.expired?
- = _('Past due')
- - elsif @milestone.upcoming?
- = _('Upcoming')
- - else
- = _('Open')
- .header-text-content
- %span.identifier
- %strong
- = _('Milestone')
- - if @milestone.due_date || @milestone.start_date
- = milestone_date_range(@milestone)
- .milestone-buttons
- - if can?(current_user, :admin_milestone, @project)
- = link_to edit_project_milestone_path(@project, @milestone), class: 'btn btn-grouped btn-nr' do
- = _('Edit')
-
- - if @project.group
- %button.js-promote-project-milestone-button.btn.btn-grouped{ data: { toggle: 'modal',
- target: '#promote-milestone-modal',
- milestone_title: @milestone.title,
- group_name: @project.group.name,
- url: promote_project_milestone_path(@milestone.project, @milestone),
- container: 'body' },
- disabled: true,
- type: 'button' }
- = _('Promote')
- #promote-milestone-modal
-
- - if @milestone.active?
- = link_to _('Close milestone'), project_milestone_path(@project, @milestone, milestone: {state_event: :close }), method: :put, class: 'btn btn-close btn-nr btn-grouped'
- - else
- = link_to _('Reopen milestone'), project_milestone_path(@project, @milestone, milestone: {state_event: :activate }), method: :put, class: 'btn btn-reopen btn-nr btn-grouped'
-
- = render 'shared/milestones/delete_button'
-
- %a.btn.btn-default.btn-grouped.float-right.d-block.d-sm-none.js-sidebar-toggle{ href: '#' }
- = icon('angle-double-left')
-
-.detail-page-description.milestone-detail
- %h2.title.qa-milestone-title
- = markdown_field(@milestone, :title)
-
- %div
- - if @milestone.description.present?
- .description.md
- = markdown_field(@milestone, :description)
+= render 'shared/milestones/header', milestone: @milestone
+= render 'shared/milestones/description', milestone: @milestone
= render_if_exists 'shared/milestones/burndown', milestone: @milestone, project: @project
diff --git a/app/views/shared/milestones/_description.html.haml b/app/views/shared/milestones/_description.html.haml
new file mode 100644
index 00000000000..5ff110bf94b
--- /dev/null
+++ b/app/views/shared/milestones/_description.html.haml
@@ -0,0 +1,8 @@
+.detail-page-description.milestone-detail
+ %h2.title
+ = markdown_field(milestone, :title)
+
+ - if milestone.try(:description).present?
+ %div
+ .description.md
+ = markdown_field(milestone, :description)
diff --git a/app/views/shared/milestones/_header.html.haml b/app/views/shared/milestones/_header.html.haml
new file mode 100644
index 00000000000..2da857261d1
--- /dev/null
+++ b/app/views/shared/milestones/_header.html.haml
@@ -0,0 +1,38 @@
+.detail-page-header.milestone-page-header
+ .status-box{ class: status_box_class(milestone) }
+ = milestone_status_string(milestone)
+
+ .header-text-content
+ %span.identifier
+ %strong
+ = _('Milestone')
+ - if milestone.due_date || milestone.start_date
+ = milestone_date_range(milestone)
+
+ .milestone-buttons
+ - if can?(current_user, :admin_milestone, @group || @project)
+ - unless milestone.legacy_group_milestone?
+ = link_to _('Edit'), edit_milestone_path(milestone), class: 'btn btn-grouped'
+
+ - if milestone.project_milestone? && milestone.project.group
+ %button.js-promote-project-milestone-button.btn.btn-grouped{ data: { toggle: 'modal',
+ target: '#promote-milestone-modal',
+ milestone_title: milestone.title,
+ group_name: milestone.project.group.name,
+ url: promote_project_milestone_path(milestone.project, milestone),
+ container: 'body' },
+ disabled: true,
+ type: 'button' }
+ = _('Promote')
+ #promote-milestone-modal
+
+ - if milestone.active?
+ = link_to _('Close milestone'), update_milestone_path(milestone, { state_event: :close }), method: :put, class: 'btn btn-grouped btn-close'
+ - else
+ = link_to _('Reopen milestone'), update_milestone_path(milestone, { state_event: :activate }), method: :put, class: 'btn btn-grouped btn-reopen'
+
+ - unless milestone.legacy_group_milestone?
+ = render 'shared/milestones/delete_button'
+
+ %button.btn.btn-default.btn-grouped.float-right.d-block.d-sm-none.js-sidebar-toggle{ type: 'button' }
+ = icon('angle-double-left')
diff --git a/app/views/shared/milestones/_tabs.html.haml b/app/views/shared/milestones/_tabs.html.haml
index b877f66c71e..f718c5767d1 100644
--- a/app/views/shared/milestones/_tabs.html.haml
+++ b/app/views/shared/milestones/_tabs.html.haml
@@ -1,30 +1,22 @@
-- issues_accessible = milestone.is_a?(GlobalMilestone) || can?(current_user, :read_issue, @project)
-
.scrolling-tabs-container.inner-page-scroll-tabs.is-smaller
.fade-left= icon('angle-left')
.fade-right= icon('angle-right')
%ul.nav-links.scrolling-tabs.js-milestone-tabs.nav.nav-tabs
- - if issues_accessible
- %li.nav-item
- = link_to '#tab-issues', class: 'nav-link active', 'data-toggle' => 'tab', 'data-show' => '.tab-issues-buttons' do
- Issues
- %span.badge.badge-pill= milestone.issues_visible_to_user(current_user).size
- %li.nav-item
- = link_to '#tab-merge-requests', class: 'nav-link', 'data-toggle' => 'tab', 'data-endpoint': milestone_merge_request_tab_path(milestone) do
- Merge Requests
- %span.badge.badge-pill= milestone.merge_requests_visible_to_user(current_user).size
- - else
- %li.nav-item
- = link_to '#tab-merge-requests', class: 'nav-link active', 'data-toggle' => 'tab', 'data-endpoint': milestone_merge_request_tab_path(milestone) do
- Merge Requests
- %span.badge.badge-pill= milestone.merge_requests.size
%li.nav-item
- = link_to '#tab-participants', class: 'nav-link', 'data-toggle' => 'tab', 'data-endpoint': milestone_participants_tab_path(milestone) do
- Participants
+ = link_to '#tab-issues', class: 'nav-link active', data: { toggle: 'tab', show: '.tab-issues-buttons' } do
+ = _('Issues')
+ %span.badge.badge-pill= milestone.issues_visible_to_user(current_user).size
+ %li.nav-item
+ = link_to '#tab-merge-requests', class: 'nav-link', data: { toggle: 'tab', endpoint: milestone_tab_path(milestone, 'merge_requests') } do
+ = _('Merge Requests')
+ %span.badge.badge-pill= milestone.merge_requests_visible_to_user(current_user).size
+ %li.nav-item
+ = link_to '#tab-participants', class: 'nav-link', data: { toggle: 'tab', endpoint: milestone_tab_path(milestone, 'participants') } do
+ = _('Participants')
%span.badge.badge-pill= milestone.issue_participants_visible_by_user(current_user).count
%li.nav-item
- = link_to '#tab-labels', class: 'nav-link', 'data-toggle' => 'tab', 'data-endpoint': milestone_labels_tab_path(milestone) do
- Labels
+ = link_to '#tab-labels', class: 'nav-link', data: { toggle: 'tab', endpoint: milestone_tab_path(milestone, 'labels') } do
+ = _('Labels')
%span.badge.badge-pill= milestone.issue_labels_visible_by_user(current_user).count
- issues = milestone.sorted_issues(current_user)
@@ -32,16 +24,11 @@
- show_full_project_name = local_assigns.fetch(:show_full_project_name, false)
.tab-content.milestone-content
- - if issues_accessible
- .tab-pane.active#tab-issues{ data: { sort_endpoint: (sort_issues_project_milestone_path(@project, @milestone) if @project && current_user) } }
- = render 'shared/milestones/issues_tab', issues: issues, show_project_name: show_project_name, show_full_project_name: show_full_project_name
- .tab-pane#tab-merge-requests
- -# loaded async
- = render "shared/milestones/tab_loading"
- - else
- .tab-pane.active#tab-merge-requests
- -# loaded async
- = render "shared/milestones/tab_loading"
+ .tab-pane.active#tab-issues{ data: { sort_endpoint: (sort_issues_project_milestone_path(@project, @milestone) if @project && current_user) } }
+ = render 'shared/milestones/issues_tab', issues: issues, show_project_name: show_project_name, show_full_project_name: show_full_project_name
+ .tab-pane#tab-merge-requests
+ -# loaded async
+ = render "shared/milestones/tab_loading"
.tab-pane#tab-participants
-# loaded async
= render "shared/milestones/tab_loading"
diff --git a/app/views/shared/milestones/_top.html.haml b/app/views/shared/milestones/_top.html.haml
index fd3317341f6..12575b30a6c 100644
--- a/app/views/shared/milestones/_top.html.haml
+++ b/app/views/shared/milestones/_top.html.haml
@@ -4,54 +4,15 @@
- group = local_assigns[:group]
- is_dynamic_milestone = milestone.legacy_group_milestone? || milestone.dashboard_milestone?
-.detail-page-header.milestone-page-header
- .status-box{ class: "status-box-#{milestone.closed? ? 'closed' : 'open'}" }
- - if milestone.closed?
- Closed
- - elsif milestone.expired?
- Expired
- - else
- Open
-
- .header-text-content
- %span.identifier
- Milestone #{milestone.title}
- - if milestone.due_date || milestone.start_date
- %span.creator
- &nbsp;&middot;
- = milestone_date_range(milestone)
-
- .milestone-buttons
- - if group
- - if can?(current_user, :admin_milestone, group)
- - if milestone.group_milestone?
- = link_to edit_group_milestone_path(group, milestone), class: "btn btn btn-grouped" do
- Edit
- - if milestone.active?
- = link_to 'Close Milestone', group_milestone_route(milestone, {state_event: :close }), method: :put, class: "btn btn-grouped btn-close"
- - else
- = link_to 'Reopen Milestone', group_milestone_route(milestone, {state_event: :activate }), method: :put, class: "btn btn-grouped btn-reopen"
-
- - unless is_dynamic_milestone
- = render 'shared/milestones/delete_button'
-
- %a.btn.btn-default.btn-grouped.float-right.d-block.d-sm-none.js-sidebar-toggle{ href: "#" }
- = icon('angle-double-left')
-
+= render 'shared/milestones/header', milestone: milestone
= render 'shared/milestones/deprecation_message' if is_dynamic_milestone
-
-.detail-page-description.milestone-detail
- %h2.title
- = markdown_field(milestone, :title)
- - if milestone.group_milestone? && milestone.description.present?
- %div
- .description.md
- = markdown_field(milestone, :description)
+= render 'shared/milestones/description', milestone: milestone
- if milestone.complete?(current_user) && milestone.active?
.alert.alert-success.prepend-top-default
- - close_msg = group ? 'You may close the milestone now.' : 'Navigate to the project to close the milestone.'
- %span All issues for this milestone are closed. #{close_msg}
+ %span
+ = _('All issues for this milestone are closed.')
+ = group ? _('You may close the milestone now.') : _('Navigate to the project to close the milestone.')
= render_if_exists 'shared/milestones/burndown', milestone: milestone, project: @project
@@ -77,10 +38,3 @@
Open
%td
= milestone.expires_at
-- elsif milestone.group_milestone?
- %br
- View
- = link_to 'Issues', issues_group_path(@group, milestone_title: milestone.title)
- or
- = link_to 'Merge Requests', merge_requests_group_path(@group, milestone_title: milestone.title)
- in this milestone
diff --git a/changelogs/unreleased/19445-native-group-milestone-page-needs-same-info-as-project-milestones.yml b/changelogs/unreleased/19445-native-group-milestone-page-needs-same-info-as-project-milestones.yml
new file mode 100644
index 00000000000..0e804e1322f
--- /dev/null
+++ b/changelogs/unreleased/19445-native-group-milestone-page-needs-same-info-as-project-milestones.yml
@@ -0,0 +1,5 @@
+---
+title: Add issues, MRs, participants, and labels tabs in group milestone page
+merge_request: 18818
+author:
+type: added
diff --git a/changelogs/unreleased/34423-user-popover-immediately-closed-when-hovering-over-certain-areas.yml b/changelogs/unreleased/34423-user-popover-immediately-closed-when-hovering-over-certain-areas.yml
new file mode 100644
index 00000000000..56a36830b54
--- /dev/null
+++ b/changelogs/unreleased/34423-user-popover-immediately-closed-when-hovering-over-certain-areas.yml
@@ -0,0 +1,5 @@
+---
+title: Fix user popover not being displayed when the user has a status message
+merge_request: 19519
+author:
+type: fixed
diff --git a/changelogs/unreleased/34577-add-dep-scanner-var-maven.yml b/changelogs/unreleased/34577-add-dep-scanner-var-maven.yml
new file mode 100644
index 00000000000..8b28cead295
--- /dev/null
+++ b/changelogs/unreleased/34577-add-dep-scanner-var-maven.yml
@@ -0,0 +1,5 @@
+---
+title: Add maven cli opts flag to maven security analyzer (part of dependency scanning)
+merge_request: 19174
+author:
+type: changed
diff --git a/doc/topics/git/partial_clone.md b/doc/topics/git/partial_clone.md
index ce1b551ddb6..e6f84ee8251 100644
--- a/doc/topics/git/partial_clone.md
+++ b/doc/topics/git/partial_clone.md
@@ -39,16 +39,20 @@ Follow [Git for enormous repositories](https://gitlab.com/groups/gitlab-org/-/ep
## Enabling partial clone
-GitLab 12.1 uses Git 2.21.0 which has an arbitrary file access security
-vulnerability when `uploadpack.allowFilter` is enabled, and should not be
-enabled in production environments.
+> [Introduced](https://gitlab.com/gitlab-org/gitaly/issues/1553) in GitLab 12.4.
-A feature flag is planned to enable `uploadpack.allowFilter` and
-`uploadpack.allowAnySHA1InWant` once the version of Git used by GitLab has been
-updated to Git 2.22.0.
+To enable partial clone, use the [feature flags API](../../api/features.md).
+For example:
-Follow [this issue](https://gitlab.com/gitlab-org/gitaly/issues/1553) for
-updated.
+```sh
+curl --data "value=true" --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/features/gitaly_upload_pack_filter
+```
+
+Alternatively, flip the switch and enable the feature flag:
+
+```ruby
+Feature.enable(:gitaly_upload_pack_filter)
+```
## Excluding objects by size
diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md
index 0da9157a636..c5aae41b587 100644
--- a/doc/user/application_security/container_scanning/index.md
+++ b/doc/user/application_security/container_scanning/index.md
@@ -149,17 +149,18 @@ container_scanning:
Container Scanning can be [configured](#overriding-the-container-scanning-template)
using environment variables.
-| Environment Variable | Description | Default |
-| ------ | ------ | ------ |
-| `KLAR_TRACE` | Set to true to enable more verbose output from klar. | `"false"` |
-| `DOCKER_USER` | Username for accessing a Docker registry requiring authentication. | `$CI_REGISTRY_USER` |
-| `DOCKER_PASSWORD` | Password for accessing a Docker registry requiring authentication. | `$CI_REGISTRY_PASSWORD` |
-| `CLAIR_OUTPUT` | Severity level threshold. Vulnerabilities with severity level higher than or equal to this threshold will be outputted. Supported levels are `Unknown`, `Negligible`, `Low`, `Medium`, `High`, `Critical` and `Defcon1`. | `Unknown` |
-| `REGISTRY_INSECURE` | Allow [Klar](https://github.com/optiopay/klar) to access insecure registries (HTTP only). Should only be set to `true` when testing the image locally. | `"false"` |
-| `CLAIR_VULNERABILITIES_DB_URL` | This variable is explicitly set in the [services section](https://gitlab.com/gitlab-org/gitlab/blob/30522ca8b901223ac8c32b633d8d67f340b159c1/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L17-19) of the `Container-Scanning.gitlab-ci.yml` file and defaults to `clair-vulnerabilities-db`. This value represents the address that the [postgres server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db) is running on and **shouldn't be changed** unless you're running the image locally as described in the [Running the scanning tool](https://gitlab.com/gitlab-org/security-products/analyzers/klar/#running-the-scanning-tool) section of the [klar readme](https://gitlab.com/gitlab-org/security-products/analyzers/klar). | `clair-vulnerabilities-db` |
-| `CI_APPLICATION_REPOSITORY` | Docker repository URL for the image to be scanned. | `$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG` |
-| `CI_APPLICATION_TAG` | Docker respository tag for the image to be scanned. | `$CI_COMMIT_SHA` |
-| `CLAIR_DB_IMAGE_TAG` | The Docker image tag for the [postgres server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db). It can be useful to override this value with a specific version, for example, to provide a consistent set of vulnerabilities for integration testing purposes. | `latest` |
+| Environment Variable | Description | Default |
+| ------ | ------ | ------ |
+| `KLAR_TRACE` | Set to true to enable more verbose output from klar. | `"false"` |
+| `DOCKER_USER` | Username for accessing a Docker registry requiring authentication. | `$CI_REGISTRY_USER` |
+| `DOCKER_PASSWORD` | Password for accessing a Docker registry requiring authentication. | `$CI_REGISTRY_PASSWORD` |
+| `CLAIR_OUTPUT` | Severity level threshold. Vulnerabilities with severity level higher than or equal to this threshold will be outputted. Supported levels are `Unknown`, `Negligible`, `Low`, `Medium`, `High`, `Critical` and `Defcon1`. | `Unknown` |
+| `REGISTRY_INSECURE` | Allow [Klar](https://github.com/optiopay/klar) to access insecure registries (HTTP only). Should only be set to `true` when testing the image locally. | `"false"` |
+| `CLAIR_VULNERABILITIES_DB_URL` | This variable is explicitly set in the [services section](https://gitlab.com/gitlab-org/gitlab/blob/30522ca8b901223ac8c32b633d8d67f340b159c1/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml#L17-19) of the `Container-Scanning.gitlab-ci.yml` file and defaults to `clair-vulnerabilities-db`. This value represents the address that the [postgres server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db) is running on and **shouldn't be changed** unless you're running the image locally as described in the [Running the scanning tool](https://gitlab.com/gitlab-org/security-products/analyzers/klar/#running-the-scanning-tool) section of the [GitLab klar analyzer readme](https://gitlab.com/gitlab-org/security-products/analyzers/klar). | `clair-vulnerabilities-db` |
+| `CI_APPLICATION_REPOSITORY` | Docker repository URL for the image to be scanned. | `$CI_REGISTRY_IMAGE/$CI_COMMIT_REF_SLUG` |
+| `CI_APPLICATION_TAG` | Docker respository tag for the image to be scanned. | `$CI_COMMIT_SHA` |
+| `CLAIR_DB_IMAGE` | The Docker image name and tag for the [postgres server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db). It can be useful to override this value with a specific version, for example, to provide a consistent set of vulnerabilities for integration testing purposes, or to refer to a locally hosted vulnerabilities database for an on-premise air-gapped installation. | `arminc/clair-db:latest` |
+| `CLAIR_DB_IMAGE_TAG` | (**DEPRECATED - use `CLAIR_DB_IMAGE` instead**) The Docker image tag for the [postgres server hosting the vulnerabilities definitions](https://hub.docker.com/r/arminc/clair-db). It can be useful to override this value with a specific version, for example, to provide a consistent set of vulnerabilities for integration testing purposes. | `latest` |
## Security Dashboard
@@ -177,6 +178,26 @@ Once a vulnerability is found, you can interact with it. Read more on how to
For more information about the vulnerabilities database update, check the
[maintenance table](../index.md#maintenance-and-update-of-the-vulnerabilities-database).
+## Running Container Scanning in an offline air-gapped installation
+
+Container Scanning can be executed on an offline air-gapped GitLab Ultimate installation using the following process:
+
+1. Host the following Docker images on a [local Docker container registry](../../packages/container_registry/index.md):
+ - [arminc/clair-db vulnerabilities database](https://hub.docker.com/r/arminc/clair-db)
+ - [GitLab klar analyzer](https://gitlab.com/gitlab-org/security-products/analyzers/klar)
+1. [Override the container scanning template](#overriding-the-container-scanning-template) in your `.gitlab-ci.yml` file to refer to the Docker
+ images hosted on your local Docker container registry:
+
+ ```yaml
+ include:
+ - template: Container-Scanning.gitlab-ci.yml
+
+ container_scanning:
+ image: your.local.registry:5000/gitlab-klar-analyzer
+ variables:
+ CLAIR_DB_IMAGE: your.local.registry:5000/clair-vulnerabilities-db
+ ```
+
## Troubleshooting
### docker: Error response from daemon: failed to copy xattrs
diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md
index 15f6ded2587..39de9c48520 100644
--- a/doc/user/application_security/dependency_scanning/index.md
+++ b/doc/user/application_security/dependency_scanning/index.md
@@ -140,6 +140,33 @@ using environment variables.
| `DS_RUN_ANALYZER_TIMEOUT` | Time limit when running an analyzer. Timeouts are parsed using Go's [`ParseDuration`](https://golang.org/pkg/time/#ParseDuration). Valid time units are `ns`, `us` (or `µs`), `ms`, `s`, `m`, `h`. For example, `300ms`, `1.5h`, or `2h45m`. | |
| `PIP_INDEX_URL` | Base URL of Python Package Index (default `https://pypi.org/simple`). | |
| `PIP_EXTRA_INDEX_URL` | Array of [extra URLs](https://pip.pypa.io/en/stable/reference/pip_install/#cmdoption-extra-index-url) of package indexes to use in addition to `PIP_INDEX_URL`. Comma separated. | |
+| `MAVEN_CLI_OPTS` | List of command line arguments that will be passed to the maven analyzer during the project's build phase (see example for [using private repos](#using-private-maven-repos)). | |
+
+### Using private Maven repos
+
+If you have a private Maven repository which requires login credentials,
+you can use the `MAVEN_CLI_OPTS` environment variable to pass variables
+specified in your settings (e.g., username, password, etc.).
+
+For example, if you have a settings file in your project source (e.g., `mysettings.xml`)
+that looks like the following, you can specify the variables
+[by adding an entry under your project's settings](../../../ci/variables/README.md#via-the-ui),
+so that you don't have to expose your private data in `.gitlab-ci.yml` (e.g., adding
+`MAVEN_CLI_OPTS` with value `--settings mysettings.xml -Dprivate.username=foo -Dprivate.password=bar`).
+
+```xml
+<!-- mysettings.xml -->
+<settings>
+ ...
+ <servers>
+ <server>
+ <id>private_server</id>
+ <username>${private.username}</username>
+ <password>${private.password}</password>
+ </server>
+ </servers>
+</settings>
+```
## Interacting with the vulnerabilities
diff --git a/doc/user/project/milestones/index.md b/doc/user/project/milestones/index.md
index 03f524f5582..4dc8dd927dc 100644
--- a/doc/user/project/milestones/index.md
+++ b/doc/user/project/milestones/index.md
@@ -103,30 +103,18 @@ When filtering by milestone, in addition to choosing a specific project mileston
## Milestone view
-Not all features in the project milestone view are available in the group milestone view. This table summarizes the differences:
-
-| Feature | Project milestone view | Group milestone view |
-|--------------------------------------|:----------------------:|:--------------------:|
-| Title and description | ✓ | ✓ |
-| Issues assigned to milestone | ✓ | |
-| Merge requests assigned to milestone | ✓ | |
-| Participants and labels used | ✓ | |
-| Percentage complete | ✓ | ✓ |
-| Start date and due date | ✓ | ✓ |
-| Total issue time spent | ✓ | ✓ |
-| Total issue weight | ✓ | |
-| Burndown chart **[STARTER}** | ✓ | ✓ |
-
The milestone view shows the title and description.
-### Project milestone features
-
-These features are only available for project milestones and not group milestones.
+There are also tabs below these that show the following:
-- Issues assigned to the milestone are displayed in three columns: Unstarted issues, ongoing issues, and completed issues.
-- Merge requests assigned to the milestone are displayed in four columns: Work in progress merge requests, waiting for merge, rejected, and closed.
-- Participants and labels that are used in issues and merge requests that have the milestone assigned are displayed.
-- [Burndown chart](#project-burndown-charts-starter).
+- Issues
+ Shows all issues assigned to the milestone. These are displayed in three columns: Unstarted issues, ongoing issues, and completed issues.
+- Merge requests
+ Shows all merge requests assigned to the milestone. These are displayed in four columns: Work in progress merge requests, waiting for merge, rejected, and closed.
+- Participants
+ Shows all assignees of issues assigned to the milestone.
+- Labels
+ Shows all labels that are used in issues assigned to the milestone.
### Project Burndown Charts **(STARTER)**
@@ -144,9 +132,8 @@ The milestone sidebar on the milestone view shows the following:
- Percentage complete, which is calculated as number of closed issues divided by total number of issues.
- The start date and due date.
-- The total time spent on all issues that have the milestone assigned.
-
-For project milestones only, the milestone sidebar shows the total issue weight of all issues that have the milestone assigned.
+- The total time spent on all issues assigned to the milestone.
+- The total issue weight of all issues assigned to the milestone.
![Project milestone page](img/milestones_project_milestone_page.png)
diff --git a/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
index 53ba9792bd0..4993d22d400 100644
--- a/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/Dependency-Scanning.gitlab-ci.yml
@@ -51,6 +51,7 @@ dependency_scanning:
DS_PIP_DEPENDENCY_PATH \
PIP_INDEX_URL \
PIP_EXTRA_INDEX_URL \
+ MAVEN_CLI_OPTS \
) \
--volume "$PWD:/code" \
--volume /var/run/docker.sock:/var/run/docker.sock \
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 405f6be75b3..c246741655e 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -1396,6 +1396,9 @@ msgstr ""
msgid "All groups and projects"
msgstr ""
+msgid "All issues for this milestone are closed."
+msgstr ""
+
msgid "All issues for this milestone are closed. You may close this milestone now."
msgstr ""
@@ -10941,6 +10944,9 @@ msgstr ""
msgid "Naming, visibility"
msgstr ""
+msgid "Navigate to the project to close the milestone."
+msgstr ""
+
msgid "Nav|Help"
msgstr ""
@@ -11782,6 +11788,9 @@ msgstr ""
msgid "Part of merge request changes"
msgstr ""
+msgid "Participants"
+msgstr ""
+
msgid "Passed"
msgstr ""
@@ -19497,6 +19506,9 @@ msgstr ""
msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
msgstr ""
+msgid "You may close the milestone now."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
diff --git a/spec/features/groups/milestone_spec.rb b/spec/features/groups/milestone_spec.rb
index 17738905e8d..65ef0af5be3 100644
--- a/spec/features/groups/milestone_spec.rb
+++ b/spec/features/groups/milestone_spec.rb
@@ -3,9 +3,9 @@
require 'spec_helper'
describe 'Group milestones' do
- let(:group) { create(:group) }
- let!(:project) { create(:project_empty_repo, group: group) }
- let(:user) { create(:group_member, :maintainer, user: create(:user), group: group ).user }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project_empty_repo, group: group) }
+ let_it_be(:user) { create(:group_member, :maintainer, user: create(:user), group: group ).user }
around do |example|
Timecop.freeze { example.run }
@@ -71,9 +71,9 @@ describe 'Group milestones' do
end
context 'when milestones exists' do
- let!(:other_project) { create(:project_empty_repo, group: group) }
+ let_it_be(:other_project) { create(:project_empty_repo, group: group) }
- let!(:active_project_milestone1) do
+ let_it_be(:active_project_milestone1) do
create(
:milestone,
project: project,
@@ -83,12 +83,12 @@ 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.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') }
- let!(:closed_group_milestone) { create(:milestone, group: group, state: 'closed') }
- let!(:issue) do
+ let_it_be(:active_project_milestone2) { create(:milestone, project: other_project, state: 'active', title: 'v1.1') }
+ let_it_be(:closed_project_milestone1) { create(:milestone, project: project, state: 'closed', title: 'v2.0') }
+ let_it_be(:closed_project_milestone2) { create(:milestone, project: other_project, state: 'closed', title: 'v2.0') }
+ let_it_be(:active_group_milestone) { create(:milestone, group: group, state: 'active', title: 'GL-113') }
+ let_it_be(:closed_group_milestone) { create(:milestone, group: group, state: 'closed') }
+ let_it_be(:issue) do
create :issue, project: project, assignees: [user], author: user, milestone: active_project_milestone1
end
@@ -143,38 +143,111 @@ describe 'Group milestones' do
expect(page).to have_content('Issues 1 Open: 1 Closed: 0')
expect(page).to have_link(issue.title, href: project_issue_path(issue.project, issue))
end
+ end
+ end
+
+ describe 'milestone tabs', :js do
+ context 'for a legacy group milestone' do
+ let_it_be(:milestone) { create(:milestone, project: project) }
+ let_it_be(:label) { create(:label, project: project) }
+ let_it_be(:issue) { create(:labeled_issue, project: project, milestone: milestone, labels: [label], assignees: [create(:user)]) }
+ let_it_be(:mr) { create(:merge_request, source_project: project, milestone: milestone) }
+
+ before do
+ visit group_milestone_path(group, milestone.title, title: milestone.title)
+ end
+
+ it 'renders the issues tab' do
+ within('#tab-issues') do
+ expect(page).to have_content issue.title
+ end
+ end
+
+ it 'renders the merge requests tab' do
+ within('.js-milestone-tabs') do
+ click_link('Merge Requests')
+ end
- describe 'labels' do
- before do
- create(:label, project: project, title: 'bug') do |label|
- issue.labels << label
- end
+ within('#tab-merge-requests') do
+ expect(page).to have_content mr.title
+ end
+ end
+
+ it 'renders the participants tab' do
+ within('.js-milestone-tabs') do
+ click_link('Participants')
+ end
- create(:label, project: project, title: 'feature') do |label|
- issue.labels << label
- end
+ within('#tab-participants') do
+ expect(page).to have_content issue.assignees.first.name
end
+ end
- it 'renders labels' do
- click_link 'v1.0'
+ it 'renders the labels tab' do
+ within('.js-milestone-tabs') do
+ click_link('Labels')
+ end
- page.within('#tab-issues') do
- expect(page).to have_content 'bug'
- expect(page).to have_content 'feature'
- end
+ within('#tab-labels') do
+ expect(page).to have_content label.title
end
+ end
+ end
+
+ context 'for a group milestone' do
+ let_it_be(:other_project) { create(:project_empty_repo, group: group) }
+ let_it_be(:milestone) { create(:milestone, group: group) }
- it 'renders labels list', :js do
- click_link 'v1.0'
+ let_it_be(:project_label) { create(:label, project: project) }
+ let_it_be(:other_project_label) { create(:label, project: other_project) }
- page.within('.content .nav-links') do
- page.find(:xpath, "//a[@href='#tab-labels']").click
- end
+ let_it_be(:project_issue) { create(:labeled_issue, project: project, milestone: milestone, labels: [project_label], assignees: [create(:user)]) }
+ let_it_be(:other_project_issue) { create(:labeled_issue, project: other_project, milestone: milestone, labels: [other_project_label], assignees: [create(:user)]) }
+
+ let_it_be(:project_mr) { create(:merge_request, source_project: project, milestone: milestone) }
+ let_it_be(:other_project_mr) { create(:merge_request, source_project: other_project, milestone: milestone) }
+
+ before do
+ visit group_milestone_path(group, milestone)
+ end
+
+ it 'renders the issues tab' do
+ within('#tab-issues') do
+ expect(page).to have_content project_issue.title
+ expect(page).to have_content other_project_issue.title
+ end
+ end
+
+ it 'renders the merge requests tab' do
+ within('.js-milestone-tabs') do
+ click_link('Merge Requests')
+ end
+
+ within('#tab-merge-requests') do
+ expect(page).to have_content project_mr.title
+ expect(page).to have_content other_project_mr.title
+ end
+ end
+
+ it 'renders the participants tab' do
+ within('.js-milestone-tabs') do
+ click_link('Participants')
+ end
+
+ within('#tab-participants') do
+ expect(page).to have_content project_issue.assignees.first.name
+ expect(page).to have_content other_project_issue.assignees.first.name
+ end
+ end
+
+ it 'renders the labels tab' do
+ within('.js-milestone-tabs') do
+ click_link('Labels')
+ end
- page.within('#tab-labels') do
- expect(page).to have_content 'bug'
- expect(page).to have_content 'feature'
- end
+ within('#tab-labels') do
+ expect(page).to have_content project_label.title
+ expect(page).to have_content other_project_label.title
end
end
end
diff --git a/spec/features/projects/milestones/milestone_spec.rb b/spec/features/projects/milestones/milestone_spec.rb
index 4b3cd7db1ed..fb9667cd67d 100644
--- a/spec/features/projects/milestones/milestone_spec.rb
+++ b/spec/features/projects/milestones/milestone_spec.rb
@@ -51,15 +51,16 @@ describe 'Project milestone' do
context 'when project has disabled issues' do
before do
+ create(:issue, project: project, milestone: milestone)
project.project_feature.update_attribute(:issues_access_level, ProjectFeature::DISABLED)
+
visit project_milestone_path(project, milestone)
end
- it 'hides issues tab' do
+ it 'does not show any issues under the issues tab' do
within('#content-body') do
- expect(page).not_to have_link 'Issues', href: '#tab-issues'
- expect(page).to have_selector '.nav-links li a.active', count: 1
- expect(find('.nav-links li a.active')).to have_content 'Merge Requests'
+ expect(find('.nav-links li a.active')).to have_content 'Issues'
+ expect(page).not_to have_selector '.issuable-row'
end
end