diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-07 21:06:14 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-07 21:06:14 +0000 |
commit | c324100967bbdd3f2f0ca3406c9261d35e69f148 (patch) | |
tree | ecfd5d521d90792cbc922309e6930b1ba2badff6 | |
parent | d8ccc7a00b7a1ea954263170a2044257424a2cfe (diff) | |
download | gitlab-ce-c324100967bbdd3f2f0ca3406c9261d35e69f148.tar.gz |
Add latest changes from gitlab-org/gitlab@master
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 - · - = 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 |