diff options
48 files changed, 604 insertions, 454 deletions
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index 39f2097c174..0ddf40b0405 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -35,6 +35,7 @@ import initPerformanceBar from './performance_bar'; import initSearchAutocomplete from './search_autocomplete'; import GlFieldErrors from './gl_field_errors'; import initUserPopovers from './user_popovers'; +import { initUserTracking } from './tracking'; import { __ } from './locale'; import 'ee_else_ce/main_ee'; @@ -94,6 +95,7 @@ function deferredInitialisation() { initLogoAnimation(); initUsagePingConsent(); initUserPopovers(); + initUserTracking(); if (document.querySelector('.search')) initSearchAutocomplete(); diff --git a/app/assets/javascripts/notes/components/notes_app.vue b/app/assets/javascripts/notes/components/notes_app.vue index a0695f9e191..16a0fb3f33a 100644 --- a/app/assets/javascripts/notes/components/notes_app.vue +++ b/app/assets/javascripts/notes/components/notes_app.vue @@ -75,9 +75,9 @@ export default { }, allDiscussions() { if (this.isLoading) { - const totalNotes = parseInt(this.notesData.totalNotes, 10) || 0; + const prerenderedNotesCount = parseInt(this.notesData.prerenderedNotesCount, 10) || 0; - return new Array(totalNotes).fill({ + return new Array(prerenderedNotesCount).fill({ isSkeletonNote: true, }); } diff --git a/app/assets/javascripts/tracking.js b/app/assets/javascripts/tracking.js index a852f937eec..03281b5ef49 100644 --- a/app/assets/javascripts/tracking.js +++ b/app/assets/javascripts/tracking.js @@ -1,5 +1,23 @@ import $ from 'jquery'; +const DEFAULT_SNOWPLOW_OPTIONS = { + namespace: 'gl', + hostname: window.location.hostname, + cookieDomain: window.location.hostname, + appId: '', + userFingerprint: false, + respectDoNotTrack: true, + forceSecureTracker: true, + eventMethod: 'post', + contexts: { webPage: true }, + // Page tracking tracks a single event when the page loads. + pageTrackingEnabled: false, + // Activity tracking tracks when a user is still interacting with the page. + // Events like scrolling and mouse movements are used to determine if the + // user has the tab active and is still actively engaging. + activityTrackingEnabled: false, +}; + const extractData = (el, opts = {}) => { const { trackEvent, trackLabel = '', trackProperty = '' } = el.dataset; let trackValue = el.dataset.trackValue || el.value || ''; @@ -71,3 +89,13 @@ export default class Tracking { }; } } + +export function initUserTracking() { + if (!Tracking.enabled()) return; + + const opts = Object.assign({}, DEFAULT_SNOWPLOW_OPTIONS, window.snowplowOptions); + window.snowplow('newTracker', opts.namespace, opts.hostname, opts); + + if (opts.activityTrackingEnabled) window.snowplow('enableActivityTracking', 30, 30); + if (opts.pageTrackingEnabled) window.snowplow('trackPageView'); // must be after enableActivityTracking +} diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index 2e31a5e2ed4..4e88b379e16 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -1,6 +1,8 @@ # frozen_string_literal: true module NotesHelper + MAX_PRERENDERED_NOTES = 10 + def note_target_fields(note) if note.noteable hidden_field_tag(:target_type, note.noteable.class.name.underscore) + @@ -169,7 +171,7 @@ module NotesHelper closePath: close_issuable_path(issuable), reopenPath: reopen_issuable_path(issuable), notesPath: notes_url, - totalNotes: issuable.discussions.length, + prerenderedNotesCount: issuable.capped_notes_count(MAX_PRERENDERED_NOTES), lastFetchedAt: Time.now.to_i } end diff --git a/app/models/commit.rb b/app/models/commit.rb index 0889ce7e287..1470b50f396 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -35,6 +35,7 @@ class Commit MIN_SHA_LENGTH = Gitlab::Git::Commit::MIN_SHA_LENGTH COMMIT_SHA_PATTERN = /\h{#{MIN_SHA_LENGTH},40}/.freeze + EXACT_COMMIT_SHA_PATTERN = /\A#{COMMIT_SHA_PATTERN}\z/.freeze # Used by GFM to match and present link extensions on node texts and hrefs. LINK_EXTENSION_PATTERN = /(patch)/.freeze @@ -90,7 +91,7 @@ class Commit end def valid_hash?(key) - !!(/\A#{COMMIT_SHA_PATTERN}\z/ =~ key) + !!(EXACT_COMMIT_SHA_PATTERN =~ key) end def lazy(project, oid) @@ -139,6 +140,10 @@ class Commit '@' end + def self.reference_valid?(reference) + !!(reference =~ EXACT_COMMIT_SHA_PATTERN) + end + # Pattern used to extract commit references from text # # This pattern supports cross-project references. diff --git a/app/models/concerns/noteable.rb b/app/models/concerns/noteable.rb index 4b428b0af83..6a44bc7c401 100644 --- a/app/models/concerns/noteable.rb +++ b/app/models/concerns/noteable.rb @@ -73,6 +73,10 @@ module Noteable .discussions(self) end + def capped_notes_count(max) + notes.limit(max).count + end + def grouped_diff_discussions(*args) # Doesn't use `discussion_notes`, because this may include commit diff notes # besides MR diff notes, that we do not want to display on the MR Changes tab. diff --git a/app/models/lfs_object.rb b/app/models/lfs_object.rb index 79a376ff0fd..40695a97d97 100644 --- a/app/models/lfs_object.rb +++ b/app/models/lfs_object.rb @@ -2,6 +2,7 @@ class LfsObject < ApplicationRecord include AfterCommitQueue + include EachBatch include ObjectStorage::BackgroundMove has_many :lfs_objects_projects, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent diff --git a/app/services/projects/lfs_pointers/lfs_link_service.rb b/app/services/projects/lfs_pointers/lfs_link_service.rb index e3c956250f0..38de2af9c1e 100644 --- a/app/services/projects/lfs_pointers/lfs_link_service.rb +++ b/app/services/projects/lfs_pointers/lfs_link_service.rb @@ -4,6 +4,8 @@ module Projects module LfsPointers class LfsLinkService < BaseService + BATCH_SIZE = 1000 + # Accept an array of oids to link # # Returns an array with the oid of the existent lfs objects @@ -18,16 +20,33 @@ module Projects # rubocop: disable CodeReuse/ActiveRecord def link_existing_lfs_objects(oids) - existent_lfs_objects = LfsObject.where(oid: oids) + all_existing_objects = [] + iterations = 0 + + LfsObject.where(oid: oids).each_batch(of: BATCH_SIZE) do |existent_lfs_objects| + next unless existent_lfs_objects.any? + + iterations += 1 + not_linked_lfs_objects = existent_lfs_objects.where.not(id: project.all_lfs_objects) + project.all_lfs_objects << not_linked_lfs_objects - return [] unless existent_lfs_objects.any? + all_existing_objects += existent_lfs_objects.pluck(:oid) + end - not_linked_lfs_objects = existent_lfs_objects.where.not(id: project.all_lfs_objects) - project.all_lfs_objects << not_linked_lfs_objects + log_lfs_link_results(all_existing_objects.count, iterations) - existent_lfs_objects.pluck(:oid) + all_existing_objects end # rubocop: enable CodeReuse/ActiveRecord + + def log_lfs_link_results(lfs_objects_linked_count, iterations) + Gitlab::Import::Logger.info( + class: self.class.name, + project_id: project.id, + project_path: project.full_path, + lfs_objects_linked_count: lfs_objects_linked_count, + iterations: iterations) + end end end end diff --git a/app/views/layouts/_snowplow.html.haml b/app/views/layouts/_snowplow.html.haml index 5f5c5e984c5..d7ff5ad1094 100644 --- a/app/views/layouts/_snowplow.html.haml +++ b/app/views/layouts/_snowplow.html.haml @@ -7,23 +7,4 @@ };p[i].q=p[i].q||[];n=l.createElement(o);g=l.getElementsByTagName(o)[0];n.async=1; n.src=w;g.parentNode.insertBefore(n,g)}}(window,document,"script","#{asset_url('snowplow/sp.js')}","snowplow")); - window.snowplow('newTracker', '#{Gitlab::SnowplowTracker::NAMESPACE}', '#{Gitlab::CurrentSettings.snowplow_collector_hostname}', { - appId: '#{Gitlab::CurrentSettings.snowplow_site_id}', - cookieDomain: '#{Gitlab::CurrentSettings.snowplow_cookie_domain}', - userFingerprint: false, - respectDoNotTrack: true, - forceSecureTracker: true, - post: true, - contexts: { webPage: true }, - stateStorageStrategy: "localStorage" - }); - - window.snowplow('enableActivityTracking', 30, 30); - window.snowplow('trackPageView'); - -- return unless Feature.enabled?(:additional_snowplow_tracking, @group) - -= javascript_tag nonce: true do - :plain - window.snowplow('enableFormTracking'); - window.snowplow('enableLinkClickTracking'); + window.snowplowOptions = #{Gitlab::Tracking.snowplow_options(@group).to_json} diff --git a/app/views/shared/runners/_form.html.haml b/app/views/shared/runners/_form.html.haml index 559b5aa9c1e..24b4eae0c58 100644 --- a/app/views/shared/runners/_form.html.haml +++ b/app/views/shared/runners/_form.html.haml @@ -26,11 +26,6 @@ = f.check_box :locked, { class: 'form-check-input' } %label.light{ for: :runner_locked }= _('When a runner is locked, it cannot be assigned to other projects') .form-group.row - = label_tag :token, class: 'col-form-label col-sm-2' do - = _('Token') - .col-sm-10 - = f.text_field :token, class: 'form-control', readonly: true - .form-group.row = label_tag :ip_address, class: 'col-form-label col-sm-2' do = _('IP Address') .col-sm-10 diff --git a/changelogs/unreleased/35060-remove-token-field.yml b/changelogs/unreleased/35060-remove-token-field.yml new file mode 100644 index 00000000000..93a7b459dd8 --- /dev/null +++ b/changelogs/unreleased/35060-remove-token-field.yml @@ -0,0 +1,5 @@ +--- +title: Remove token field from runners edit form +merge_request: 32231 +author: +type: fixed diff --git a/changelogs/unreleased/sh-fix-issue-move-api.yml b/changelogs/unreleased/sh-fix-issue-move-api.yml new file mode 100644 index 00000000000..e98d04b02d9 --- /dev/null +++ b/changelogs/unreleased/sh-fix-issue-move-api.yml @@ -0,0 +1,5 @@ +--- +title: Fix moving issues API failing when text includes commit URLs +merge_request: 32317 +author: +type: fixed diff --git a/changelogs/unreleased/sh-lfs-object-batches.yml b/changelogs/unreleased/sh-lfs-object-batches.yml new file mode 100644 index 00000000000..09043e286be --- /dev/null +++ b/changelogs/unreleased/sh-lfs-object-batches.yml @@ -0,0 +1,5 @@ +--- +title: Makes LFS object linker process OIDs in batches +merge_request: 32268 +author: +type: performance diff --git a/changelogs/unreleased/sh-upgrade-mermaid-8-2-4.yml b/changelogs/unreleased/sh-upgrade-mermaid-8-2-4.yml new file mode 100644 index 00000000000..bdb64e43ecf --- /dev/null +++ b/changelogs/unreleased/sh-upgrade-mermaid-8-2-4.yml @@ -0,0 +1,5 @@ +--- +title: Upgrade Mermaid to v8.2.4 +merge_request: 32186 +author: +type: fixed diff --git a/doc/README.md b/doc/README.md index f12c06199c2..9a0252cc334 100644 --- a/doc/README.md +++ b/doc/README.md @@ -358,7 +358,7 @@ The following documentation relates to the DevOps **Secure** stage: | [Dependency Scanning](user/application_security/dependency_scanning/index.md) **(ULTIMATE)** | Analyze your dependencies for known vulnerabilities. | | [Dynamic Application Security Testing (DAST)](user/application_security/dast/index.md) **(ULTIMATE)** | Analyze running web applications for known vulnerabilities. | | [Group Security Dashboard](user/application_security/security_dashboard/index.md) **(ULTIMATE)** | View vulnerabilities in all the projects in a group and its subgroups. | -| [License Compliance](user/application_security/license_management/index.md) **(ULTIMATE)** | Search your project's dependencies for their licenses. | +| [License Compliance](user/application_security/license_compliance/index.md) **(ULTIMATE)** | Search your project's dependencies for their licenses. | | [Project Security Dashboard](user/application_security/security_dashboard/index.md) **(ULTIMATE)** | View the latest security reports for your project. | | [Static Application Security Testing (SAST)](user/application_security/sast/index.md) **(ULTIMATE)** | Analyze source code for known vulnerabilities. | diff --git a/doc/ci/README.md b/doc/ci/README.md index 4be13204227..90d0e6a7dc6 100644 --- a/doc/ci/README.md +++ b/doc/ci/README.md @@ -131,7 +131,7 @@ Its feature set is listed on the table below according to DevOps stages. | **Secure** || | [Container Scanning](../user/application_security/container_scanning/index.md) **(ULTIMATE)** | Check your Docker containers for known vulnerabilities.| | [Dependency Scanning](../user/application_security/dependency_scanning/index.md) **(ULTIMATE)** | Analyze your dependencies for known vulnerabilities. | -| [License Compliance](../user/application_security/license_management/index.md) **(ULTIMATE)** | Search your project dependencies for their licenses. | +| [License Compliance](../user/application_security/license_compliance/index.md) **(ULTIMATE)** | Search your project dependencies for their licenses. | | [Security Test reports](../user/project/merge_requests/index.md#security-reports-ultimate) **(ULTIMATE)** | Check for app vulnerabilities. | ## Examples diff --git a/doc/ci/examples/license_management.md b/doc/ci/examples/license_management.md index 53e38111bf3..0d12c9a20f2 100644 --- a/doc/ci/examples/license_management.md +++ b/doc/ci/examples/license_management.md @@ -1,5 +1,5 @@ --- -redirect_to: '../../user/application_security/license_management/index.md' +redirect_to: '../../user/application_security/license_compliance/index.md' --- -This document was moved to [another location](../../user/application_security/license_management/index.md). +This document was moved to [another location](../../user/application_security/license_compliance/index.md). diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index 06dceeb37d4..7a60dedc206 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -1699,7 +1699,7 @@ dashboards. > Introduced in GitLab 11.5. Requires GitLab Runner 11.5 and above. -The `license_management` report collects [Licenses](../../user/project/merge_requests/license_management.md) +The `license_management` report collects [Licenses](../../user/application_security/license_compliance/index.md) as artifacts. The collected License Compliance report will be uploaded to GitLab as an artifact and will diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md index bfcda1dd7fc..283e8bea8d5 100644 --- a/doc/development/documentation/styleguide.md +++ b/doc/development/documentation/styleguide.md @@ -506,15 +506,6 @@ Example: For more information, see the [confidential issue](../../user/project/issues/confidential_issues.md) `https://gitlab.com/gitlab-org/gitlab-ce/issues/<issue_number>`. ``` -### Unlinking emails - -By default, all email addresses will render in an email tag on docs.gitlab.com. -To escape the code block and unlink email addresses, use two backticks: - -```md -`` example@email.com `` -``` - ## Navigation To indicate the steps of navigation through the UI: diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md index 83444093f9c..2df0e846671 100644 --- a/doc/development/go_guide/index.md +++ b/doc/development/go_guide/index.md @@ -94,7 +94,7 @@ become available, you will be able to share job templates like this Dependencies should be kept to the minimum. The introduction of a new dependency should be argued in the merge request, as per our [Approval Guidelines](../code_review.md#approval-guidelines). Both [License -Management](../../user/project/merge_requests/license_management.md) +Management](../../user/application_security/license_compliance/index.md) **(ULTIMATE)** and [Dependency Scanning](../../user/application_security/dependency_scanning/index.md) **(ULTIMATE)** should be activated on all projects to ensure new dependencies diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md index 6021e8cff1d..19d8a6b5e2b 100644 --- a/doc/topics/autodevops/index.md +++ b/doc/topics/autodevops/index.md @@ -414,7 +414,7 @@ report is created, it's uploaded as an artifact which you can later download and check out. Any licenses are also shown in the merge request widget. Read more how -[License Compliance works](../../user/application_security/license_management/index.md). +[License Compliance works](../../user/application_security/license_compliance/index.md). ### Auto Container Scanning **(ULTIMATE)** diff --git a/doc/user/application_security/license_management/img/license_management.png b/doc/user/application_security/license_compliance/img/license_compliance.png Binary files differindex cdce6b5fe38..cdce6b5fe38 100644 --- a/doc/user/application_security/license_management/img/license_management.png +++ b/doc/user/application_security/license_compliance/img/license_compliance.png diff --git a/doc/user/application_security/license_management/img/license_management_add_license.png b/doc/user/application_security/license_compliance/img/license_compliance_add_license.png Binary files differindex c9a5dc14c57..c9a5dc14c57 100644 --- a/doc/user/application_security/license_management/img/license_management_add_license.png +++ b/doc/user/application_security/license_compliance/img/license_compliance_add_license.png diff --git a/doc/user/application_security/license_management/img/license_management_decision.png b/doc/user/application_security/license_compliance/img/license_compliance_decision.png Binary files differindex fbf90bec7fd..fbf90bec7fd 100644 --- a/doc/user/application_security/license_management/img/license_management_decision.png +++ b/doc/user/application_security/license_compliance/img/license_compliance_decision.png diff --git a/doc/user/application_security/license_management/img/license_management_pipeline_tab.png b/doc/user/application_security/license_compliance/img/license_compliance_pipeline_tab.png Binary files differindex 80ffca815b9..80ffca815b9 100644 --- a/doc/user/application_security/license_management/img/license_management_pipeline_tab.png +++ b/doc/user/application_security/license_compliance/img/license_compliance_pipeline_tab.png diff --git a/doc/user/application_security/license_management/img/license_management_search.png b/doc/user/application_security/license_compliance/img/license_compliance_search.png Binary files differindex b3ffd8d95a1..b3ffd8d95a1 100644 --- a/doc/user/application_security/license_management/img/license_management_search.png +++ b/doc/user/application_security/license_compliance/img/license_compliance_search.png diff --git a/doc/user/application_security/license_management/img/license_management_settings.png b/doc/user/application_security/license_compliance/img/license_compliance_settings.png Binary files differindex 2e3e8888e93..2e3e8888e93 100644 --- a/doc/user/application_security/license_management/img/license_management_settings.png +++ b/doc/user/application_security/license_compliance/img/license_compliance_settings.png diff --git a/doc/user/application_security/license_compliance/index.md b/doc/user/application_security/license_compliance/index.md new file mode 100644 index 00000000000..f74b958cf67 --- /dev/null +++ b/doc/user/application_security/license_compliance/index.md @@ -0,0 +1,243 @@ +--- +type: reference, howto +--- + +# License Compliance **(ULTIMATE)** + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5483) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0. + +## Overview + +If you are using [GitLab CI/CD](../../../ci/README.md), you can search your project dependencies for their licenses +using License Compliance. + +You can take advantage of License Compliance by either [including the job](#configuration) +in your existing `.gitlab-ci.yml` file or by implicitly using +[Auto License Compliance](../../../topics/autodevops/index.md#auto-license-compliance-ultimate) +that is provided by [Auto DevOps](../../../topics/autodevops/index.md). + +GitLab checks the License Compliance report, compares the licenses between the +source and target branches, and shows the information right on the merge request. +Blacklisted licenses will be clearly visible with an `x` red icon next to them +as well as new licenses which need a decision from you. In addition, you can +[manually approve or blacklist](#project-policies-for-license-compliance) +licenses in your project's settings. + +NOTE: **Note:** +If the license compliance report doesn't have anything to compare to, no information +will be displayed in the merge request area. That is the case when you add the +`license_management` job in your `.gitlab-ci.yml` for the first time. +Consecutive merge requests will have something to compare to and the license +compliance report will be shown properly. + +![License Compliance Widget](img/license_compliance.png) + +If you are a project or group Maintainer, you can click on a license to be given +the choice to approve it or blacklist it. + +![License approval decision](img/license_compliance_decision.png) + +## Use cases + +It helps you find what licenses your project uses in its dependencies, and decide for each of then +whether to allow it or forbid it. For example, your application is using an external (open source) +library whose license is incompatible with yours. + +## Supported languages and package managers + +The following languages and package managers are supported. + +| Language | Package managers | Scan Tool | +|------------|-------------------------------------------------------------------|----------------------------------------------------------| +| JavaScript | [Bower](https://bower.io/), [npm](https://www.npmjs.com/), [yarn](https://yarnpkg.com/) ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)) |[License Finder](https://github.com/pivotal/LicenseFinder)| +| Go | [Godep](https://github.com/tools/godep), go get ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)), gvt ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)), glide ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)), dep ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)), trash ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)) and govendor ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)), [go mod](https://github.com/golang/go/wiki/Modules) ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)) |[License Finder](https://github.com/pivotal/LicenseFinder)| +| Java | [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/) |[License Finder](https://github.com/pivotal/LicenseFinder)| +| .NET | [Nuget](https://www.nuget.org/) |[License Finder](https://github.com/pivotal/LicenseFinder)| +| Python | [pip](https://pip.pypa.io/en/stable/) |[License Finder](https://github.com/pivotal/LicenseFinder)| +| Ruby | [gem](https://rubygems.org/) |[License Finder](https://github.com/pivotal/LicenseFinder)| +| Erlang | [rebar](https://www.rebar3.org/) ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types))|[License Finder](https://github.com/pivotal/LicenseFinder)| +| Objective-C, Swift | [Carthage](https://github.com/Carthage/Carthage) , [CocoaPods v0.39 and below](https://cocoapods.org/) ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)) |[License Finder](https://github.com/pivotal/LicenseFinder)| +| Elixir | [mix](https://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html) ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)) |[License Finder](https://github.com/pivotal/LicenseFinder)| +| C++/C | [conan](https://conan.io/) ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types))|[License Finder](https://github.com/pivotal/LicenseFinder)| +| Scala | [sbt](https://www.scala-sbt.org/) ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types))|[License Finder](https://github.com/pivotal/LicenseFinder)| +| Rust | [cargo](https://crates.io/) ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types))|[License Finder](https://github.com/pivotal/LicenseFinder)| +| PHP | [composer](https://getcomposer.org/) ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types))|[License Finder](https://github.com/pivotal/LicenseFinder)| + +## Requirements + +To run a License Compliance scanning job, you need GitLab Runner with the +[`docker` executor](https://docs.gitlab.com/runner/executors/docker.html). + +## Configuration + +For GitLab 11.9 and later, to enable License Compliance, you must +[include](../../../ci/yaml/README.md#includetemplate) the +[`License-Management.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/lib/gitlab/ci/templates/Security/License-Management.gitlab-ci.yml) +that's provided as a part of your GitLab installation. +For GitLab versions earlier than 11.9, you can copy and use the job as defined +that template. + +Add the following to your `.gitlab-ci.yml` file: + +```yaml +include: + template: License-Management.gitlab-ci.yml +``` + +The included template will create a `license_management` job in your CI/CD pipeline +and scan your dependencies to find their licenses. + +The results will be saved as a +[License Compliance report artifact](../../../ci/yaml/README.md#artifactsreportslicense_management-ultimate) +that you can later download and analyze. Due to implementation limitations, we +always take the latest License Compliance artifact available. Behind the scenes, the +[GitLab License Compliance Docker image](https://gitlab.com/gitlab-org/security-products/license-management) +is used to detect the languages/frameworks and in turn analyzes the licenses. + +The License Compliance settings can be changed through environment variables by using the +[`variables`](../../../ci/yaml/README.md#variables) parameter in `.gitlab-ci.yml`. These variables are documented in the [License Compliance documentation](https://gitlab.com/gitlab-org/security-products/license-management#settings). + +### Installing custom dependencies + +> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.4. + +The `license_management` image already embeds many auto-detection scripts, languages, +and packages. Nevertheless, it's almost impossible to cover all cases for all projects. +That's why sometimes it's necessary to install extra packages, or to have extra steps +in the project automated setup, like the download and installation of a certificate. +For that, a `LICENSE_MANAGEMENT_SETUP_CMD` environment variable can be passed to the container, +with the required commands to run before the license detection. + +If present, this variable will override the setup step necessary to install all the packages +of your application (e.g.: for a project with a `Gemfile`, the setup step could be +`bundle install`). + +For example: + +```yaml +include: + template: License-Management.gitlab-ci.yml + +variables: + LICENSE_MANAGEMENT_SETUP_CMD: sh my-custom-install-script.sh +``` + +In this example, `my-custom-install-script.sh` is a shell script at the root +directory of your project. + +### Overriding the template + +If you want to override the job definition (for example, change properties like +`variables` or `dependencies`), you need to declare a `license_management` job +after the template inclusion and specify any additional keys under it. For example: + +```yaml +include: + template: License-Management.gitlab-ci.yml + +license_management: + variables: + CI_DEBUG_TRACE: "true" +``` + +### Configuring Maven projects + +The License Compliance tool provides a `MAVEN_CLI_OPTS` environment variable which can hold +the command line arguments to pass to the `mvn install` command which is executed under the hood. +Feel free to use it for the customization of Maven execution. For example: + +```yaml +include: + template: License-Management.gitlab-ci.yml + +license_management: + variables: + MAVEN_CLI_OPTS: --debug +``` + +`mvn install` runs through all of the [build life cycle](http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html) +stages prior to `install`, including `test`. Running unit tests is not directly +necessary for the license scanning purposes and consumes time, so it's skipped +by having the default value of `MAVEN_CLI_OPTS` as `-DskipTests`. If you want +to supply custom `MAVEN_CLI_OPTS` and skip tests at the same time, don't forget +to explicitly add `-DskipTests` to your options. +If you still need to run tests during `mvn install`, add `-DskipTests=false` to +`MAVEN_CLI_OPTS`. + +### Selecting the version of Python + +> - [Introduced](https://gitlab.com/gitlab-org/security-products/license-management/merge_requests/36) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0. +> - In GitLab 12.2, Python 3.5 became the default. + +License Compliance uses Python 3.5 and pip 19.1 by default. +If your project requires Python 2, you can switch to Python 2.7 and pip 10.0 +by setting the `LM_PYTHON_VERSION` environment variable to `2`. + +```yaml +include: + template: License-Management.gitlab-ci.yml + +license_management: + variables: + LM_PYTHON_VERSION: 2 +``` + +## Project policies for License Compliance + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5940) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.4. + +From the project's settings: + +- The list of licenses and their status can be managed. +- Licenses can be manually approved or blacklisted. + +To approve or blacklist a license: + +1. Either use the **Manage licenses** button in the merge request widget, or + navigate to the project's **Settings > CI/CD** and expand the + **License Compliance** section. +1. Click the **Add a license** button. + + ![License Compliance Add License](img/license_compliance_add_license.png) + +1. In the **License name** dropdown, either: + - Select one of the available licenses. You can search for licenses in the field + at the top of the list. + - Enter arbitrary text in the field at the top of the list. This will cause the text to be + added as a license name to the list. +1. Select the **Approve** or **Blacklist** radio button to approve or blacklist respectively + the selected license. + +To modify an existing license: + +1. In the **License Compliance** list, click the **Approved/Declined** dropdown to change it to the desired status. + + ![License Compliance Settings](img/license_compliance_settings.png) + +Searching for Licenses: + +1. Use the **Search** box to search for a specific license. + + ![License Compliance Search](img/license_compliance_search.png) + +## License Compliance report under pipelines + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5491) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.2. + +From your project's left sidebar, navigate to **CI/CD > Pipelines** and click on the +pipeline ID that has a `license_management` job to see the Licenses tab with the listed +licenses (if any). + +![License Compliance Pipeline Tab](img/license_compliance_pipeline_tab.png) + +<!-- ## Troubleshooting + +Include any troubleshooting steps that you can foresee. If you know beforehand what issues +one might have when setting this up, or when something is changed, or on upgrading, it's +important to describe those, too. Think of things that may go wrong and include them here. +This is important to minimize requests for support, and to avoid doc comments with +questions that you know someone might ask. + +Each scenario can be a third-level heading, e.g. `### Getting error message X`. +If you have none to add when creating a doc, leave this section in place +but commented out to help encourage others to add to it in the future. --> diff --git a/doc/user/application_security/license_management/index.md b/doc/user/application_security/license_management/index.md index 44b2671930e..319da2c3a6e 100644 --- a/doc/user/application_security/license_management/index.md +++ b/doc/user/application_security/license_management/index.md @@ -1,245 +1,5 @@ --- -type: reference, howto +redirect_to: ../license_compliance/index.md --- -# License Compliance **(ULTIMATE)** - -> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5483) -in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.0. - -## Overview - -If you are using [GitLab CI/CD](../../../ci/README.md), you can search your project dependencies for their licenses -using License Compliance. - -You can take advantage of License Compliance by either [including the job](#configuration) -in your existing `.gitlab-ci.yml` file or by implicitly using -[Auto License Compliance](../../../topics/autodevops/index.md#auto-license-compliance-ultimate) -that is provided by [Auto DevOps](../../../topics/autodevops/index.md). - -GitLab checks the License Compliance report, compares the licenses between the -source and target branches, and shows the information right on the merge request. -Blacklisted licenses will be clearly visible with an `x` red icon next to them -as well as new licenses which need a decision from you. In addition, you can -[manually approve or blacklist](#project-policies-for-license-compliance) -licenses in your project's settings. - -NOTE: **Note:** -If the license management report doesn't have anything to compare to, no information -will be displayed in the merge request area. That is the case when you add the -`license_management` job in your `.gitlab-ci.yml` for the first time. -Consecutive merge requests will have something to compare to and the license -management report will be shown properly. - -![License Compliance Widget](img/license_management.png) - -If you are a project or group Maintainer, you can click on a license to be given -the choice to approve it or blacklist it. - -![License approval decision](img/license_management_decision.png) - -## Use cases - -It helps you find what licenses your project uses in its dependencies, and decide for each of then -whether to allow it or forbid it. For example, your application is using an external (open source) -library whose license is incompatible with yours. - -## Supported languages and package managers - -The following languages and package managers are supported. - -| Language | Package managers | Scan Tool | -|------------|-------------------------------------------------------------------|----------------------------------------------------------| -| JavaScript | [Bower](https://bower.io/), [npm](https://www.npmjs.com/), [yarn](https://yarnpkg.com/) ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)) |[License Finder](https://github.com/pivotal/LicenseFinder)| -| Go | [Godep](https://github.com/tools/godep), go get ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)), gvt ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)), glide ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)), dep ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)), trash ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)) and govendor ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)), [go mod](https://github.com/golang/go/wiki/Modules) ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)) |[License Finder](https://github.com/pivotal/LicenseFinder)| -| Java | [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/) |[License Finder](https://github.com/pivotal/LicenseFinder)| -| .NET | [Nuget](https://www.nuget.org/) |[License Finder](https://github.com/pivotal/LicenseFinder)| -| Python | [pip](https://pip.pypa.io/en/stable/) |[License Finder](https://github.com/pivotal/LicenseFinder)| -| Ruby | [gem](https://rubygems.org/) |[License Finder](https://github.com/pivotal/LicenseFinder)| -| Erlang | [rebar](https://www.rebar3.org/) ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types))|[License Finder](https://github.com/pivotal/LicenseFinder)| -| Objective-C, Swift | [Carthage](https://github.com/Carthage/Carthage) , [CocoaPods v0.39 and below](https://cocoapods.org/) ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)) |[License Finder](https://github.com/pivotal/LicenseFinder)| -| Elixir | [mix](https://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html) ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types)) |[License Finder](https://github.com/pivotal/LicenseFinder)| -| C++/C | [conan](https://conan.io/) ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types))|[License Finder](https://github.com/pivotal/LicenseFinder)| -| Scala | [sbt](https://www.scala-sbt.org/) ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types))|[License Finder](https://github.com/pivotal/LicenseFinder)| -| Rust | [cargo](https://crates.io/) ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types))|[License Finder](https://github.com/pivotal/LicenseFinder)| -| PHP | [composer](https://getcomposer.org/) ([experimental support](https://github.com/pivotal/LicenseFinder#experimental-project-types))|[License Finder](https://github.com/pivotal/LicenseFinder)| - -## Requirements - -To run a License Compliance scanning job, you need GitLab Runner with the -[`docker` executor](https://docs.gitlab.com/runner/executors/docker.html). - -## Configuration - -For GitLab 11.9 and later, to enable License Compliance, you must -[include](../../../ci/yaml/README.md#includetemplate) the -[`License-Management.gitlab-ci.yml` template](https://gitlab.com/gitlab-org/gitlab-ee/blob/master/lib/gitlab/ci/templates/Security/License-Management.gitlab-ci.yml) -that's provided as a part of your GitLab installation. -For GitLab versions earlier than 11.9, you can copy and use the job as defined -that template. - -Add the following to your `.gitlab-ci.yml` file: - -```yaml -include: - template: License-Management.gitlab-ci.yml -``` - -The included template will create a `license_management` job in your CI/CD pipeline -and scan your dependencies to find their licenses. - -The results will be saved as a -[License Compliance report artifact](../../../ci/yaml/README.md#artifactsreportslicense_management-ultimate) -that you can later download and analyze. Due to implementation limitations, we -always take the latest License Compliance artifact available. Behind the scenes, the -[GitLab License Compliance Docker image](https://gitlab.com/gitlab-org/security-products/license-management) -is used to detect the languages/frameworks and in turn analyzes the licenses. - -The License Compliance settings can be changed through environment variables by using the -[`variables`](../../../ci/yaml/README.md#variables) parameter in `.gitlab-ci.yml`. These variables are documented in the [License Compliance documentation](https://gitlab.com/gitlab-org/security-products/license-management#settings). - -### Installing custom dependencies - -> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.4. - -The `license_management` image already embeds many auto-detection scripts, languages, -and packages. Nevertheless, it's almost impossible to cover all cases for all projects. -That's why sometimes it's necessary to install extra packages, or to have extra steps -in the project automated setup, like the download and installation of a certificate. -For that, a `LICENSE_MANAGEMENT_SETUP_CMD` environment variable can be passed to the container, -with the required commands to run before the license detection. - -If present, this variable will override the setup step necessary to install all the packages -of your application (e.g.: for a project with a `Gemfile`, the setup step could be -`bundle install`). - -For example: - -```yaml -include: - template: License-Management.gitlab-ci.yml - -variables: - LICENSE_MANAGEMENT_SETUP_CMD: sh my-custom-install-script.sh -``` - -In this example, `my-custom-install-script.sh` is a shell script at the root -directory of your project. - -### Overriding the template - -If you want to override the job definition (for example, change properties like -`variables` or `dependencies`), you need to declare a `license_management` job -after the template inclusion and specify any additional keys under it. For example: - -```yaml -include: - template: License-Management.gitlab-ci.yml - -license_management: - variables: - CI_DEBUG_TRACE: "true" -``` - -### Configuring Maven projects - -The License Compliance tool provides a `MAVEN_CLI_OPTS` environment variable which can hold -the command line arguments to pass to the `mvn install` command which is executed under the hood. -Feel free to use it for the customization of Maven execution. For example: - -```yaml -include: - template: License-Management.gitlab-ci.yml - -license_management: - variables: - MAVEN_CLI_OPTS: --debug -``` - -`mvn install` runs through all of the [build life cycle](http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html) -stages prior to `install`, including `test`. Running unit tests is not directly -necessary for the license scanning purposes and consumes time, so it's skipped -by having the default value of `MAVEN_CLI_OPTS` as `-DskipTests`. If you want -to supply custom `MAVEN_CLI_OPTS` and skip tests at the same time, don't forget -to explicitly add `-DskipTests` to your options. -If you still need to run tests during `mvn install`, add `-DskipTests=false` to -`MAVEN_CLI_OPTS`. - -### Selecting the version of Python - -> [Introduced](https://gitlab.com/gitlab-org/security-products/license-management/merge_requests/36) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.0. - -License Compliance uses Python 3.5 and pip 19.1 by default. -If your project requires Python 2, you can switch to Python 2.7 and pip 10.0 -by setting the `LM_PYTHON_VERSION` environment variable to `2`. - -```yaml -include: - template: License-Management.gitlab-ci.yml - -license_management: - variables: - LM_PYTHON_VERSION: 2 -``` - -## Project policies for License Compliance - -> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5940) -in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.4. - -From the project's settings: - -- The list of licenses and their status can be managed. -- Licenses can be manually approved or blacklisted. - -To approve or blacklist a license: - -1. Either use the **Manage licenses** button in the merge request widget, or - navigate to the project's **Settings > CI/CD** and expand the - **License Compliance** section. -1. Click the **Add a license** button. - - ![License Compliance Add License](img/license_management_add_license.png) - -1. In the **License name** dropdown, either: - - Select one of the available licenses. You can search for licenses in the field - at the top of the list. - - Enter arbitrary text in the field at the top of the list. This will cause the text to be - added as a license name to the list. -1. Select the **Approve** or **Blacklist** radio button to approve or blacklist respectively - the selected license. - -To modify an existing license: - -1. In the **License Compliance** list, click the **Approved/Declined** dropdown to change it to the desired status. - - ![License Compliance Settings](img/license_management_settings.png) - -Searching for Licenses: - -1. Use the **Search** box to search for a specific license. - - ![License Compliance Search](img/license_management_search.png) - -## License Compliance report under pipelines - -> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/5491) -in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.2. - -From your project's left sidebar, navigate to **CI/CD > Pipelines** and click on the -pipeline ID that has a `license_management` job to see the Licenses tab with the listed -licenses (if any). - -![License Compliance Pipeline Tab](img/license_management_pipeline_tab.png) - -<!-- ## Troubleshooting - -Include any troubleshooting steps that you can foresee. If you know beforehand what issues -one might have when setting this up, or when something is changed, or on upgrading, it's -important to describe those, too. Think of things that may go wrong and include them here. -This is important to minimize requests for support, and to avoid doc comments with -questions that you know someone might ask. - -Each scenario can be a third-level heading, e.g. `### Getting error message X`. -If you have none to add when creating a doc, leave this section in place -but commented out to help encourage others to add to it in the future. --> +This document was moved to [another location](../license_compliance/index.md). diff --git a/doc/user/markdown.md b/doc/user/markdown.md index 17bbed2945d..840e1856dd9 100644 --- a/doc/user/markdown.md +++ b/doc/user/markdown.md @@ -181,9 +181,6 @@ graph TD; #### Subgraphs -NOTE: **Note:** GitLab 12.1 and up now [requires quotes around subgraph -titles that contain multiple words](https://github.com/knsv/mermaid/pull/845). - Subgraphs can also be included: ~~~ diff --git a/doc/user/project/index.md b/doc/user/project/index.md index 64c4066683b..c63d5308536 100644 --- a/doc/user/project/index.md +++ b/doc/user/project/index.md @@ -98,7 +98,7 @@ When you create a project in GitLab, you'll have access to a large number of - [Maven packages](packages/maven_repository.md): your private Maven repository in GitLab. **(PREMIUM)** - [NPM packages](packages/npm_registry.md): your private NPM package registry in GitLab. **(PREMIUM)** - [Code owners](code_owners.md): specify code owners for certain files **(STARTER)** -- [License Compliance](../application_security/license_management/index.md): approve and blacklist licenses for projects. **(ULTIMATE)** +- [License Compliance](../application_security/license_compliance/index.md): approve and blacklist licenses for projects. **(ULTIMATE)** - [Dependency List](../application_security/dependency_list/index.md): view project dependencies. **(ULTIMATE)** ### Project integrations diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md index 04db54872d3..a94057dc3a1 100644 --- a/doc/user/project/merge_requests/index.md +++ b/doc/user/project/merge_requests/index.md @@ -41,7 +41,7 @@ With **[GitLab Enterprise Edition][ee]**, you can also: - View the deployment process across projects with [Multi-Project Pipelines](../../../ci/multi_project_pipelines.md) **(PREMIUM)** - Request [approvals](merge_request_approvals.md) from your managers **(STARTER)** - Analyze the impact of your changes with [Code Quality reports](code_quality.md) **(STARTER)** -- Manage the licenses of your dependencies with [License Compliance](../../application_security/license_management/index.md) **(ULTIMATE)** +- Manage the licenses of your dependencies with [License Compliance](../../application_security/license_compliance/index.md) **(ULTIMATE)** - Analyze your source code for vulnerabilities with [Static Application Security Testing](../../application_security/sast/index.md) **(ULTIMATE)** - Analyze your running web applications for vulnerabilities with [Dynamic Application Security Testing](../../application_security/dast/index.md) **(ULTIMATE)** - Analyze your dependencies for vulnerabilities with [Dependency Scanning](../../application_security/dependency_scanning/index.md) **(ULTIMATE)** @@ -57,7 +57,7 @@ A. Consider you are a software developer working in a team: 1. You gather feedback from your team 1. You work on the implementation optimizing code with [Code Quality reports](code_quality.md) **(STARTER)** 1. You verify your changes with [JUnit test reports](../../../ci/junit_test_reports.md) in GitLab CI/CD -1. You avoid using dependencies whose license is not compatible with your project with [License Compliance reports](license_management.md) **(ULTIMATE)** +1. You avoid using dependencies whose license is not compatible with your project with [License Compliance reports](../../application_security/license_compliance/index.md) **(ULTIMATE)** 1. You request the [approval](#merge-request-approvals-starter) from your manager 1. Your manager pushes a commit with their final review, [approves the merge request](merge_request_approvals.md), and set it to [merge when pipeline succeeds](#merge-when-pipeline-succeeds) (Merge Request Approvals are available in GitLab Starter) 1. Your changes get deployed to production with [manual actions](../../../ci/yaml/README.md#whenmanual) for GitLab CI/CD diff --git a/doc/user/project/merge_requests/license_management.md b/doc/user/project/merge_requests/license_management.md index 93116ebd7c6..df5bd073ade 100644 --- a/doc/user/project/merge_requests/license_management.md +++ b/doc/user/project/merge_requests/license_management.md @@ -1,5 +1,5 @@ --- -redirect_to: '../../application_security/license_management/index.md' +redirect_to: '../../application_security/license_compliance/index.md' --- -This document was moved to [another location](../../application_security/license_management/index.md). +This document was moved to [another location](../../application_security/license_compliance/index.md). diff --git a/lib/gitlab/snowplow_tracker.rb b/lib/gitlab/snowplow_tracker.rb deleted file mode 100644 index 9f12513e09e..00000000000 --- a/lib/gitlab/snowplow_tracker.rb +++ /dev/null @@ -1,35 +0,0 @@ -# frozen_string_literal: true - -require 'snowplow-tracker' - -module Gitlab - module SnowplowTracker - NAMESPACE = 'cf' - - class << self - def track_event(category, action, label: nil, property: nil, value: nil, context: nil) - tracker&.track_struct_event(category, action, label, property, value, context, Time.now.to_i) - end - - private - - def tracker - return unless enabled? - - @tracker ||= ::SnowplowTracker::Tracker.new(emitter, subject, NAMESPACE, Gitlab::CurrentSettings.snowplow_site_id) - end - - def subject - ::SnowplowTracker::Subject.new - end - - def emitter - ::SnowplowTracker::Emitter.new(Gitlab::CurrentSettings.snowplow_collector_hostname) - end - - def enabled? - Gitlab::CurrentSettings.snowplow_enabled? - end - end - end -end diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb new file mode 100644 index 00000000000..ef669b03c87 --- /dev/null +++ b/lib/gitlab/tracking.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +require 'snowplow-tracker' + +module Gitlab + module Tracking + SNOWPLOW_NAMESPACE = 'gl' + + class << self + def enabled? + Gitlab::CurrentSettings.snowplow_enabled? + end + + def event(category, action, label: nil, property: nil, value: nil, context: nil) + return unless enabled? + + snowplow.track_struct_event(category, action, label, property, value, context, Time.now.to_i) + end + + def snowplow_options(group) + additional_features = Feature.enabled?(:additional_snowplow_tracking, group) + { + namespace: SNOWPLOW_NAMESPACE, + hostname: Gitlab::CurrentSettings.snowplow_collector_hostname, + cookie_domain: Gitlab::CurrentSettings.snowplow_cookie_domain, + app_id: Gitlab::CurrentSettings.snowplow_site_id, + page_tracking_enabled: additional_features, + activity_tracking_enabled: additional_features + }.transform_keys! { |key| key.to_s.camelize(:lower).to_sym } + end + + private + + def snowplow + @snowplow ||= SnowplowTracker::Tracker.new( + SnowplowTracker::Emitter.new(Gitlab::CurrentSettings.snowplow_collector_hostname), + SnowplowTracker::Subject.new, + SNOWPLOW_NAMESPACE, + Gitlab::CurrentSettings.snowplow_site_id + ) + end + end + end +end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index c8827c683f8..12138d2db3a 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -12115,9 +12115,6 @@ msgstr "" msgid "Toggles :%{name}: emoji award." msgstr "" -msgid "Token" -msgstr "" - msgid "Tomorrow" msgstr "" diff --git a/package.json b/package.json index 8fa34cdea28..3d785b305f1 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "jszip-utils": "^0.0.2", "katex": "^0.10.0", "marked": "^0.3.12", - "mermaid": "^8.2.3", + "mermaid": "^8.2.4", "monaco-editor": "^0.15.6", "monaco-editor-webpack-plugin": "^1.7.0", "mousetrap": "^1.4.6", diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb index 4ad90c96558..0d5f5df71b6 100644 --- a/spec/features/admin/admin_runners_spec.rb +++ b/spec/features/admin/admin_runners_spec.rb @@ -282,10 +282,6 @@ describe "Admin Runners" do visit admin_runner_path(runner) end - describe 'runner info' do - it { expect(find_field('runner_token').value).to eq runner.token } - end - describe 'projects' do it 'contains project names' do expect(page).to have_content(@project1.full_name) diff --git a/spec/frontend/tracking_spec.js b/spec/frontend/tracking_spec.js index 0e862c683d3..7c98a1a66c9 100644 --- a/spec/frontend/tracking_spec.js +++ b/spec/frontend/tracking_spec.js @@ -1,20 +1,56 @@ import $ from 'jquery'; import { setHTMLFixture } from './helpers/fixtures'; -import Tracking from '~/tracking'; +import Tracking, { initUserTracking } from '~/tracking'; describe('Tracking', () => { + let snowplowSpy; + beforeEach(() => { window.snowplow = window.snowplow || (() => {}); + window.snowplowOptions = { + namespace: '_namespace_', + hostname: 'app.gitfoo.com', + cookieDomain: '.gitfoo.com', + }; + snowplowSpy = jest.spyOn(window, 'snowplow'); }); - describe('.event', () => { - let snowplowSpy = null; + describe('initUserTracking', () => { + it('calls through to get a new tracker with the expected options', () => { + initUserTracking(); + expect(snowplowSpy).toHaveBeenCalledWith('newTracker', '_namespace_', 'app.gitfoo.com', { + namespace: '_namespace_', + hostname: 'app.gitfoo.com', + cookieDomain: '.gitfoo.com', + appId: '', + userFingerprint: false, + respectDoNotTrack: true, + forceSecureTracker: true, + eventMethod: 'post', + contexts: { webPage: true }, + activityTrackingEnabled: false, + pageTrackingEnabled: false, + }); + }); - beforeEach(() => { - snowplowSpy = jest.spyOn(window, 'snowplow'); + it('should activate features based on what has been enabled', () => { + initUserTracking(); + expect(snowplowSpy).not.toHaveBeenCalledWith('enableActivityTracking', 30, 30); + expect(snowplowSpy).not.toHaveBeenCalledWith('trackPageView'); + + window.snowplowOptions = Object.assign({}, window.snowplowOptions, { + activityTrackingEnabled: true, + pageTrackingEnabled: true, + }); + + initUserTracking(); + expect(snowplowSpy).toHaveBeenCalledWith('enableActivityTracking', 30, 30); + expect(snowplowSpy).toHaveBeenCalledWith('trackPageView'); }); + }); + describe('.event', () => { afterEach(() => { window.doNotTrack = undefined; navigator.doNotTrack = undefined; diff --git a/spec/javascripts/notes/mock_data.js b/spec/javascripts/notes/mock_data.js index 5f81a168498..3812d46f838 100644 --- a/spec/javascripts/notes/mock_data.js +++ b/spec/javascripts/notes/mock_data.js @@ -8,7 +8,7 @@ export const notesDataMock = { notesPath: '/gitlab-org/gitlab-ce/noteable/issue/98/notes', quickActionsDocsPath: '/help/user/project/quick_actions', registerPath: '/users/sign_in?redirect_to_referer=yes#register-pane', - totalNotes: 1, + prerenderedNotesCount: 1, closePath: '/twitter/flight/issues/9.json?issue%5Bstate_event%5D=close', reopenPath: '/twitter/flight/issues/9.json?issue%5Bstate_event%5D=reopen', canAwardEmoji: true, diff --git a/spec/lib/gitlab/gfm/reference_rewriter_spec.rb b/spec/lib/gitlab/gfm/reference_rewriter_spec.rb index 4d2f08f95fc..790b0428d19 100644 --- a/spec/lib/gitlab/gfm/reference_rewriter_spec.rb +++ b/spec/lib/gitlab/gfm/reference_rewriter_spec.rb @@ -102,6 +102,23 @@ describe Gitlab::Gfm::ReferenceRewriter do end end + context 'with a commit' do + let(:old_project) { create(:project, :repository, name: 'old-project', group: group) } + let(:commit) { old_project.commit } + + context 'reference to an absolute URL to a commit' do + let(:text) { Gitlab::UrlBuilder.build(commit) } + + it { is_expected.to eq(text) } + end + + context 'reference to a commit' do + let(:text) { commit.id } + + it { is_expected.to eq("#{old_project_ref}@#{text}") } + end + end + context 'reference contains project milestone' do let!(:milestone) do create(:milestone, title: '9.0', project: old_project) diff --git a/spec/lib/gitlab/snowplow_tracker_spec.rb b/spec/lib/gitlab/snowplow_tracker_spec.rb deleted file mode 100644 index 073a33e5973..00000000000 --- a/spec/lib/gitlab/snowplow_tracker_spec.rb +++ /dev/null @@ -1,45 +0,0 @@ -# frozen_string_literal: true -require 'spec_helper' - -describe Gitlab::SnowplowTracker do - let(:timestamp) { Time.utc(2017, 3, 22) } - - around do |example| - Timecop.freeze(timestamp) { example.run } - end - - subject { described_class.track_event('epics', 'action', property: 'what', value: 'doit') } - - context '.track_event' do - context 'when Snowplow tracker is disabled' do - it 'does not track the event' do - expect(SnowplowTracker::Tracker).not_to receive(:new) - - subject - end - end - - context 'when Snowplow tracker is enabled' do - before do - stub_application_setting(snowplow_enabled: true) - stub_application_setting(snowplow_site_id: 'awesome gitlab') - stub_application_setting(snowplow_collector_hostname: 'url.com') - end - - it 'tracks the event' do - tracker = double - - expect(::SnowplowTracker::Tracker).to receive(:new) - .with( - an_instance_of(::SnowplowTracker::Emitter), - an_instance_of(::SnowplowTracker::Subject), - 'cf', 'awesome gitlab' - ).and_return(tracker) - expect(tracker).to receive(:track_struct_event) - .with('epics', 'action', nil, 'what', 'doit', nil, timestamp.to_i) - - subject - end - end - end -end diff --git a/spec/lib/gitlab/tracking_spec.rb b/spec/lib/gitlab/tracking_spec.rb new file mode 100644 index 00000000000..f14e74427e1 --- /dev/null +++ b/spec/lib/gitlab/tracking_spec.rb @@ -0,0 +1,88 @@ +# frozen_string_literal: true +require 'spec_helper' + +describe Gitlab::Tracking do + let(:timestamp) { Time.utc(2017, 3, 22) } + + before do + stub_application_setting(snowplow_enabled: true) + stub_application_setting(snowplow_collector_hostname: 'gitfoo.com') + stub_application_setting(snowplow_cookie_domain: '.gitfoo.com') + stub_application_setting(snowplow_site_id: '_abc123_') + end + + describe '.snowplow_options' do + subject(&method(:described_class)) + + it 'returns useful client options' do + expect(subject.snowplow_options(nil)).to eq( + namespace: 'gl', + hostname: 'gitfoo.com', + cookieDomain: '.gitfoo.com', + appId: '_abc123_', + pageTrackingEnabled: true, + activityTrackingEnabled: true + ) + end + + it 'enables features using feature flags' do + stub_feature_flags(additional_snowplow_tracking: true) + allow(Feature).to receive(:enabled?).with( + :additional_snowplow_tracking, + '_group_' + ).and_return(false) + + expect(subject.snowplow_options('_group_')).to include( + pageTrackingEnabled: false, + activityTrackingEnabled: false + ) + end + end + + describe '.event' do + subject(&method(:described_class)) + + around do |example| + Timecop.freeze(timestamp) { example.run } + end + + it 'can track events' do + tracker = double + + expect(SnowplowTracker::Emitter).to receive(:new).with( + 'gitfoo.com' + ).and_return('_emitter_') + + expect(SnowplowTracker::Tracker).to receive(:new).with( + '_emitter_', + an_instance_of(SnowplowTracker::Subject), + 'gl', + '_abc123_' + ).and_return(tracker) + + expect(tracker).to receive(:track_struct_event).with( + 'category', + 'action', + '_label_', + '_property_', + '_value_', + '_context_', + timestamp.to_i + ) + + subject.event('category', 'action', + label: '_label_', + property: '_property_', + value: '_value_', + context: '_context_' + ) + end + + it 'does not track when not enabled' do + stub_application_setting(snowplow_enabled: false) + expect(SnowplowTracker::Tracker).not_to receive(:new) + + subject.event('epics', 'action', property: 'what', value: 'doit') + end + end +end diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb index 7b35c2ffd36..5ef824b9950 100644 --- a/spec/models/commit_spec.rb +++ b/spec/models/commit_spec.rb @@ -192,6 +192,24 @@ describe Commit do end end + describe '.reference_valid?' do + using RSpec::Parameterized::TableSyntax + + where(:ref, :result) do + '1234567' | true + '123456' | false + '1' | false + '0' * 40 | true + 'c1acaa58bbcbc3eafe538cb8274ba387047b69f8' | true + 'H1acaa58bbcbc3eafe538cb8274ba387047b69f8' | false + nil | false + end + + with_them do + it { expect(described_class.reference_valid?(ref)).to eq(result) } + end + end + describe '#reference_link_text' do let(:project) { create(:project, :repository, path: 'sample-project') } diff --git a/spec/models/concerns/noteable_spec.rb b/spec/models/concerns/noteable_spec.rb index e17b98536fa..929b5f52c7c 100644 --- a/spec/models/concerns/noteable_spec.rb +++ b/spec/models/concerns/noteable_spec.rb @@ -272,4 +272,22 @@ describe Noteable do expect(described_class.resolvable_types).to include('MergeRequest') end end + + describe '#capped_notes_count' do + context 'notes number < 10' do + it 'the number of notes is returned' do + expect(subject.capped_notes_count(10)).to eq(9) + end + end + + context 'notes number > 10' do + before do + create_list(:note, 2, project: project, noteable: subject) + end + + it '10 is returned' do + expect(subject.capped_notes_count(10)).to eq(10) + end + end + end end diff --git a/spec/services/projects/lfs_pointers/lfs_link_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_link_service_spec.rb index 849601c4a63..66233787d3a 100644 --- a/spec/services/projects/lfs_pointers/lfs_link_service_spec.rb +++ b/spec/services/projects/lfs_pointers/lfs_link_service_spec.rb @@ -30,5 +30,23 @@ describe Projects::LfsPointers::LfsLinkService do expect(subject.execute(new_oid_list.keys)).to eq linked end + + it 'links in batches' do + stub_const("#{described_class}::BATCH_SIZE", 3) + + expect(Gitlab::Import::Logger) + .to receive(:info) + .with(class: described_class.name, + project_id: project.id, + project_path: project.full_path, + lfs_objects_linked_count: 7, + iterations: 3) + + lfs_objects = create_list(:lfs_object, 7) + linked = subject.execute(lfs_objects.pluck(:oid)) + + expect(project.all_lfs_objects.count).to eq 9 + expect(linked.size).to eq 7 + end end end diff --git a/spec/support/helpers/query_recorder.rb b/spec/support/helpers/query_recorder.rb index d936dc6de41..9d47a0c23df 100644 --- a/spec/support/helpers/query_recorder.rb +++ b/spec/support/helpers/query_recorder.rb @@ -8,7 +8,10 @@ module ActiveRecord @log = [] @cached = [] @skip_cached = skip_cached - ActiveSupport::Notifications.subscribed(method(:callback), 'sql.active_record', &block) + # force replacement of bind parameters to give tests the ability to check for ids + ActiveRecord::Base.connection.unprepared_statement do + ActiveSupport::Notifications.subscribed(method(:callback), 'sql.active_record', &block) + end end def show_backtrace(values) diff --git a/yarn.lock b/yarn.lock index 712cdace0d7..6d83f3f89ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1637,7 +1637,7 @@ ansi-align@^2.0.0: dependencies: string-width "^2.0.0" -ansi-colors@^3.0.0, ansi-colors@^3.2.4: +ansi-colors@^3.0.0: version "3.2.4" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== @@ -1647,13 +1647,6 @@ ansi-escapes@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== -ansi-gray@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" - integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE= - dependencies: - ansi-wrap "0.1.0" - ansi-html@0.0.7, ansi-html@^0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" @@ -1686,11 +1679,6 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-wrap@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" - integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= - anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" @@ -2985,11 +2973,6 @@ color-name@1.1.3, color-name@^1.0.0: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= -color-support@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" - integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== - colors@^1.1.0: version "1.3.3" resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.3.tgz#39e005d546afe01e01f9c4ca8fa50f686a01205d" @@ -5027,16 +5010,6 @@ extsprintf@1.3.0, extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= -fancy-log@^1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz#dbc19154f558690150a23953a0adbd035be45fc7" - integrity sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw== - dependencies: - ansi-gray "^0.1.1" - color-support "^1.1.3" - parse-node-version "^1.0.0" - time-stamp "^1.0.0" - fast-deep-equal@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" @@ -5782,16 +5755,6 @@ growly@^1.3.0: resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= -gulp-print@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/gulp-print/-/gulp-print-5.0.2.tgz#8f379148218d2e168461baa74352e11d1bf7aa75" - integrity sha512-iIpHMzC/b3gFvVXOfP9Jk94SWGIsDLVNUrxULRleQev+08ug07mh84b1AOlW6QDQdmInQiqDFqJN1UvhU2nXdg== - dependencies: - ansi-colors "^3.2.4" - fancy-log "^1.3.3" - map-stream "0.0.7" - vinyl "^2.2.0" - gzip-size@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.0.0.tgz#a55ecd99222f4c48fd8c01c625ce3b349d0a0e80" @@ -7965,11 +7928,6 @@ map-obj@^2.0.0: resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk= -map-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.0.7.tgz#8a1f07896d82b10926bd3744a2420009f88974a8" - integrity sha1-ih8HiW2CsQkmvTdEokIACfiJdKg= - map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" @@ -8165,10 +8123,10 @@ merge2@^1.2.3: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA== -mermaid@^8.2.3: - version "8.2.3" - resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-8.2.3.tgz#609bad45bedc3ee1a935161c11c3c22689cfecd9" - integrity sha512-G2p9BAAEeTtogPs4YXM8KyX+TsZULlgk0tGvmBPfBZ5j3YCPxgAxG9ZzleiYNItF7M1hGkE485BDLN8DbfR+/Q== +mermaid@^8.2.4: + version "8.2.4" + resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-8.2.4.tgz#52bcd45611fd8552ab9ac4e385d2766a0e38dcf7" + integrity sha512-2la1eJhu4n+Uug4zbxFnkETFDJ9U32OY/fRP8g8A1DrRdfT3Er+7CuUSvxfhIDxl+AxSEU4dXdqCiToZAVMCmQ== dependencies: "@braintree/sanitize-url" "^3.1.0" d3 "^5.7.0" @@ -8176,7 +8134,6 @@ mermaid@^8.2.3: dagre-layout "^0.8.8" documentation "^12.0.1" graphlibrary "^2.2.0" - gulp-print "^5.0.2" he "^1.2.0" lodash "^4.17.11" minify "^4.1.1" @@ -9145,11 +9102,6 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" -parse-node-version@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" - integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== - parse-passwd@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" @@ -11783,11 +11735,6 @@ thunky@^0.1.0: resolved "https://registry.yarnpkg.com/thunky/-/thunky-0.1.0.tgz#bf30146824e2b6e67b0f2d7a4ac8beb26908684e" integrity sha1-vzAUaCTituZ7Dy16Ssi+smkIaE4= -time-stamp@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" - integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= - timeago.js@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/timeago.js/-/timeago.js-3.0.2.tgz#32a67e7c0d887ea42ca588d3aae26f77de5e76cc" @@ -12618,7 +12565,7 @@ vinyl-sourcemap@^1.1.0: remove-bom-buffer "^3.0.0" vinyl "^2.0.0" -vinyl@^2.0.0, vinyl@^2.1.0, vinyl@^2.2.0: +vinyl@^2.0.0, vinyl@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.0.tgz#d85b07da96e458d25b2ffe19fece9f2caa13ed86" integrity sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg== |