summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-12-12 15:08:41 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2019-12-12 15:08:41 +0000
commit27859ed5eaeae234162b7cce7fd8bd351b5f9369 (patch)
tree5a62db348c3fd73516df87262c78e3546d4ec770
parent784fae4b9d7e92350075df2a43d06893080ed1e6 (diff)
downloadgitlab-ce-27859ed5eaeae234162b7cce7fd8bd351b5f9369.tar.gz
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml4
-rw-r--r--Dangerfile1
-rw-r--r--app/models/error_tracking/project_error_tracking_setting.rb2
-rw-r--r--changelogs/unreleased/37772-add-ui-event-tracking-for-package-details-installation-instructions.yml5
-rw-r--r--danger/changelog/Dangerfile34
-rw-r--r--danger/plugins/changelog.rb10
-rw-r--r--doc/development/architecture.md3
-rw-r--r--lib/gitlab/danger/changelog.rb40
-rw-r--r--lib/sentry/client.rb39
-rw-r--r--lib/sentry/client/projects.rb46
-rw-r--r--locale/gitlab.pot7
-rw-r--r--spec/lib/gitlab/danger/changelog_spec.rb163
-rw-r--r--spec/lib/gitlab/danger/danger_spec_helper.rb17
-rw-r--r--spec/lib/gitlab/danger/helper_spec.rb17
-rw-r--r--spec/lib/sentry/client/projects_spec.rb119
-rw-r--r--spec/lib/sentry/client_spec.rb185
-rw-r--r--spec/models/error_tracking/project_error_tracking_setting_spec.rb2
-rw-r--r--spec/support/helpers/sentry_client_helpers.rb14
-rw-r--r--spec/support/shared_examples/lib/sentry/client_shared_examples.rb56
-rw-r--r--[-rwxr-xr-x]vendor/gitignore/C++.gitignore0
-rw-r--r--[-rwxr-xr-x]vendor/gitignore/Java.gitignore0
21 files changed, 500 insertions, 264 deletions
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index af69fdc239c..49447bc629b 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -23,8 +23,10 @@ build-qa-image:
stage: prepare
script:
- '[[ ! -d "ee/" ]] || export GITLAB_EDITION="ee"'
+ - export QA_MASTER_IMAGE="${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab/gitlab-${GITLAB_EDITION}-qa:master"
- export QA_IMAGE="${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab/gitlab-${GITLAB_EDITION}-qa:${CI_COMMIT_REF_SLUG}"
- - time docker build --cache-from gitlab/gitlab-${GITLAB_EDITION}-qa:nightly --tag ${QA_IMAGE} --file ./qa/Dockerfile ./
+ - time docker pull "${QA_MASTER_IMAGE}"
+ - time docker build --cache-from "${QA_MASTER_IMAGE}" --tag ${QA_IMAGE} --file ./qa/Dockerfile ./
- echo "${CI_JOB_TOKEN}" | docker login --username gitlab-ci-token --password-stdin ${CI_REGISTRY}
- time docker push ${QA_IMAGE}
diff --git a/Dangerfile b/Dangerfile
index b65a9074078..7879c14b31e 100644
--- a/Dangerfile
+++ b/Dangerfile
@@ -5,6 +5,7 @@ require_relative 'lib/gitlab/danger/request_helper'
danger.import_plugin('danger/plugins/helper.rb')
danger.import_plugin('danger/plugins/roulette.rb')
+danger.import_plugin('danger/plugins/changelog.rb')
unless helper.release_automation?
GitlabDanger.new(helper.gitlab_helper).rule_names.each do |file|
diff --git a/app/models/error_tracking/project_error_tracking_setting.rb b/app/models/error_tracking/project_error_tracking_setting.rb
index 3af14d7eef2..6a9986e806b 100644
--- a/app/models/error_tracking/project_error_tracking_setting.rb
+++ b/app/models/error_tracking/project_error_tracking_setting.rb
@@ -86,7 +86,7 @@ module ErrorTracking
end
def list_sentry_projects
- { projects: sentry_client.list_projects }
+ { projects: sentry_client.projects }
end
def issue_details(opts = {})
diff --git a/changelogs/unreleased/37772-add-ui-event-tracking-for-package-details-installation-instructions.yml b/changelogs/unreleased/37772-add-ui-event-tracking-for-package-details-installation-instructions.yml
new file mode 100644
index 00000000000..c23243dbf4c
--- /dev/null
+++ b/changelogs/unreleased/37772-add-ui-event-tracking-for-package-details-installation-instructions.yml
@@ -0,0 +1,5 @@
+---
+title: Added event tracking to the package details installation components
+merge_request: 20967
+author:
+type: changed
diff --git a/danger/changelog/Dangerfile b/danger/changelog/Dangerfile
index f8e31323f41..62b41d14bee 100644
--- a/danger/changelog/Dangerfile
+++ b/danger/changelog/Dangerfile
@@ -3,7 +3,6 @@
require 'yaml'
-NO_CHANGELOG_LABELS = %w[backstage ci-build meta].freeze
SEE_DOC = "See [the documentation](https://docs.gitlab.com/ce/development/changelog.html)."
CREATE_CHANGELOG_MESSAGE = <<~MSG
You can create one with:
@@ -21,18 +20,6 @@ bin/changelog --ee -m %<mr_iid>s "%<mr_title>s"
Note: Merge requests with %<labels>s do not trigger this check.
MSG
-def ee_changelog?(changelog_path)
- changelog_path =~ /unreleased-ee/
-end
-
-def ce_port_changelog?(changelog_path)
- helper.ee? && !ee_changelog?(changelog_path)
-end
-
-def categories_need_changelog?
- (helper.changes_by_category.keys - %i[docs none]).any?
-end
-
def check_changelog(path)
yaml = YAML.safe_load(File.read(path))
@@ -41,7 +28,7 @@ def check_changelog(path)
if yaml["merge_request"].nil?
message "Consider setting `merge_request` to #{gitlab.mr_json["iid"]} in #{gitlab.html_link(path)}. #{SEE_DOC}"
- elsif yaml["merge_request"] != gitlab.mr_json["iid"] && !ce_port_changelog?(path)
+ elsif yaml["merge_request"] != gitlab.mr_json["iid"] && !changelog.ce_port_changelog?(path)
fail "Merge request ID was not set to #{gitlab.mr_json["iid"]}! #{SEE_DOC}"
end
rescue Psych::SyntaxError, Psych::DisallowedClass, Psych::BadAlias
@@ -51,27 +38,18 @@ rescue StandardError => e
warn "There was a problem trying to check the Changelog. Exception: #{e.name} - #{e.message}"
end
-def presented_no_changelog_labels
- NO_CHANGELOG_LABELS.map { |label| "~#{label}" }.join(', ')
-end
-
-def sanitized_mr_title
- gitlab.mr_json["title"].gsub(/^WIP: */, '').gsub(/`/, '\\\`')
-end
-
-changelog_needed = categories_need_changelog? && (gitlab.mr_labels & NO_CHANGELOG_LABELS).empty?
-changelog_found = git.added_files.find { |path| path =~ %r{\A(ee/)?(changelogs/unreleased)(-ee)?/} }
-
if git.modified_files.include?("CHANGELOG.md")
fail "**CHANGELOG.md was edited.** Please remove the additions and create a CHANGELOG entry.\n\n" +
- format(CREATE_CHANGELOG_MESSAGE, mr_iid: gitlab.mr_json["iid"], mr_title: sanitized_mr_title, labels: presented_no_changelog_labels)
+ format(CREATE_CHANGELOG_MESSAGE, mr_iid: gitlab.mr_json["iid"], mr_title: changelog.sanitized_mr_title, labels: changelog.presented_no_changelog_labels)
end
-if changelog_needed
+changelog_found = changelog.found
+
+if changelog.needed?
if changelog_found
check_changelog(changelog_found)
else
message "**[CHANGELOG missing](https://docs.gitlab.com/ce/development/changelog.html)**: If this merge request [doesn't need a CHANGELOG entry](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry), feel free to ignore this message.\n\n" +
- format(CREATE_CHANGELOG_MESSAGE, mr_iid: gitlab.mr_json["iid"], mr_title: sanitized_mr_title, labels: presented_no_changelog_labels)
+ format(CREATE_CHANGELOG_MESSAGE, mr_iid: gitlab.mr_json["iid"], mr_title: changelog.sanitized_mr_title, labels: changelog.presented_no_changelog_labels)
end
end
diff --git a/danger/plugins/changelog.rb b/danger/plugins/changelog.rb
new file mode 100644
index 00000000000..84f399e9e97
--- /dev/null
+++ b/danger/plugins/changelog.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+require_relative '../../lib/gitlab/danger/changelog'
+
+module Danger
+ class Changelog < Plugin
+ # Put the helper code somewhere it can be tested
+ include Gitlab::Danger::Changelog
+ end
+end
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index b579f812d99..eff83da523b 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -116,6 +116,7 @@ graph TB
- ⚙ - Requires additional configuration, or GitLab Managed Apps
- ⤓ - Manual installation required
- ❌ - Not supported or no instructions available
+- N/A - Not applicable
Component statuses are linked to configuration documentation for each component.
@@ -144,7 +145,7 @@ Component statuses are linked to configuration documentation for each component.
| [Postgres Exporter](#postgres-exporter) | Prometheus endpoint with PostgreSQL metrics | [✅][postgres-exporter-omnibus] | [✅][postgres-exporter-charts] | [✅][postgres-exporter-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE |
| [PgBouncer Exporter](#pgbouncer-exporter) | Prometheus endpoint with PgBouncer metrics | [⚙][pgbouncer-exporter-omnibus] | [❌][pgbouncer-exporter-charts] | [❌][pgbouncer-exporter-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE |
| [GitLab Exporter](#gitlab-exporter) | Generates a variety of GitLab metrics | [✅][gitlab-exporter-omnibus] | [✅][gitlab-exporter-charts] | [✅][gitlab-exporter-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE |
-| [Node Exporter](#node-exporter) | Prometheus endpoint with system metrics | [✅][node-exporter-omnibus] | [❌][node-exporter-charts] | [❌][node-exporter-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE |
+| [Node Exporter](#node-exporter) | Prometheus endpoint with system metrics | [✅][node-exporter-omnibus] | [N/A][node-exporter-charts] | [N/A][node-exporter-charts] | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | ❌ | ❌ | CE & EE |
| [Mattermost](#mattermost) | Open-source Slack alternative | [⚙][mattermost-omnibus] | [⤓][mattermost-charts] | [⤓][mattermost-charts] | [⤓](../user/project/integrations/mattermost.md) | ❌ | ❌ | CE & EE |
| [MinIO](#minio) | Object storage service | [⤓][minio-omnibus] | [✅][minio-charts] | [✅][minio-charts] | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#storage-architecture) | ❌ | [⚙][minio-gdk] | CE & EE |
| [Runner](#gitlab-runner) | Executes GitLab CI jobs | [⤓][runner-omnibus] | [✅][runner-charts] | [⚙][runner-charts] | [✅](../user/gitlab_com/index.md#shared-runners) | [⚙][runner-source] | [⚙][runner-gdk] | CE & EE |
diff --git a/lib/gitlab/danger/changelog.rb b/lib/gitlab/danger/changelog.rb
new file mode 100644
index 00000000000..b53516081be
--- /dev/null
+++ b/lib/gitlab/danger/changelog.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Danger
+ module Changelog
+ NO_CHANGELOG_LABELS = %w[backstage ci-build meta].freeze
+ NO_CHANGELOG_CATEGORIES = %i[docs none].freeze
+
+ def needed?
+ categories_need_changelog? && (gitlab.mr_labels & NO_CHANGELOG_LABELS).empty?
+ end
+
+ def found
+ git.added_files.find { |path| path =~ %r{\A(ee/)?(changelogs/unreleased)(-ee)?/} }
+ end
+
+ def presented_no_changelog_labels
+ NO_CHANGELOG_LABELS.map { |label| "~#{label}" }.join(', ')
+ end
+
+ def sanitized_mr_title
+ gitlab.mr_json["title"].gsub(/^WIP: */, '').gsub(/`/, '\\\`')
+ end
+
+ def ee_changelog?(changelog_path)
+ changelog_path =~ /unreleased-ee/
+ end
+
+ def ce_port_changelog?(changelog_path)
+ helper.ee? && !ee_changelog?(changelog_path)
+ end
+
+ private
+
+ def categories_need_changelog?
+ (helper.changes_by_category.keys - NO_CHANGELOG_CATEGORIES).any?
+ end
+ end
+ end
+end
diff --git a/lib/sentry/client.rb b/lib/sentry/client.rb
index 6cbee830b17..47b497accc1 100644
--- a/lib/sentry/client.rb
+++ b/lib/sentry/client.rb
@@ -2,6 +2,8 @@
module Sentry
class Client
+ include Sentry::Client::Projects
+
Error = Class.new(StandardError)
MissingKeysError = Class.new(StandardError)
ResponseInvalidSizeError = Class.new(StandardError)
@@ -49,14 +51,6 @@ module Sentry
end
end
- def list_projects
- projects = get_projects
-
- handle_mapping_exceptions do
- map_to_projects(projects)
- end
- end
-
private
def validate_size(issues)
@@ -121,10 +115,6 @@ module Sentry
http_get(issue_latest_event_api_url(issue_id))[:body]
end
- def get_projects
- http_get(projects_api_url)[:body]
- end
-
def handle_request_exceptions
yield
rescue Gitlab::HTTP::Error => e
@@ -155,13 +145,6 @@ module Sentry
raise Client::Error, message
end
- def projects_api_url
- projects_url = URI(@url)
- projects_url.path = '/api/0/projects/'
-
- projects_url
- end
-
def issue_api_url(issue_id)
issue_url = URI(@url)
issue_url.path = "/api/0/issues/#{issue_id}/"
@@ -187,10 +170,6 @@ module Sentry
issues.map(&method(:map_to_error))
end
- def map_to_projects(projects)
- projects.map(&method(:map_to_project))
- end
-
def issue_url(id)
issues_url = @url + "/issues/#{id}"
@@ -289,19 +268,5 @@ module Sentry
project_slug: issue.dig('project', 'slug')
)
end
-
- def map_to_project(project)
- organization = project.fetch('organization')
-
- Gitlab::ErrorTracking::Project.new(
- id: project.fetch('id', nil),
- name: project.fetch('name'),
- slug: project.fetch('slug'),
- status: project.dig('status'),
- organization_name: organization.fetch('name'),
- organization_id: organization.fetch('id', nil),
- organization_slug: organization.fetch('slug')
- )
- end
end
end
diff --git a/lib/sentry/client/projects.rb b/lib/sentry/client/projects.rb
new file mode 100644
index 00000000000..68f8fe0f9c9
--- /dev/null
+++ b/lib/sentry/client/projects.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+module Sentry
+ class Client
+ module Projects
+ def projects
+ projects = get_projects
+
+ handle_mapping_exceptions do
+ map_to_projects(projects)
+ end
+ end
+
+ private
+
+ def get_projects
+ http_get(projects_api_url)[:body]
+ end
+
+ def projects_api_url
+ projects_url = URI(url)
+ projects_url.path = '/api/0/projects/'
+
+ projects_url
+ end
+
+ def map_to_projects(projects)
+ projects.map(&method(:map_to_project))
+ end
+
+ def map_to_project(project)
+ organization = project.fetch('organization')
+
+ Gitlab::ErrorTracking::Project.new(
+ id: project.fetch('id', nil),
+ name: project.fetch('name'),
+ slug: project.fetch('slug'),
+ status: project.dig('status'),
+ organization_name: organization.fetch('name'),
+ organization_id: organization.fetch('id', nil),
+ organization_slug: organization.fetch('slug')
+ )
+ end
+ end
+ end
+end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 5315f4e0d1a..9c7dcdcae63 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -53,10 +53,10 @@ msgstr ""
msgid " or <!merge request id>"
msgstr ""
-msgid " or <#epic id>"
+msgid " or <#issue id>"
msgstr ""
-msgid " or <#issue id>"
+msgid " or <&epic id>"
msgstr ""
msgid " or references (e.g. path/to/project!merge_request_id)"
@@ -18254,6 +18254,9 @@ msgstr ""
msgid "Those emails automatically become issues (with the comments becoming the email conversation) listed here."
msgstr ""
+msgid "Threat Monitoring"
+msgstr ""
+
msgid "Thursday"
msgstr ""
diff --git a/spec/lib/gitlab/danger/changelog_spec.rb b/spec/lib/gitlab/danger/changelog_spec.rb
new file mode 100644
index 00000000000..888094eaf6e
--- /dev/null
+++ b/spec/lib/gitlab/danger/changelog_spec.rb
@@ -0,0 +1,163 @@
+# frozen_string_literal: true
+
+require 'fast_spec_helper'
+require 'rspec-parameterized'
+require_relative 'danger_spec_helper'
+
+require 'gitlab/danger/changelog'
+
+describe Gitlab::Danger::Changelog do
+ using RSpec::Parameterized::TableSyntax
+ include DangerSpecHelper
+
+ let(:added_files) { nil }
+ let(:fake_git) { double('fake-git', added_files: added_files) }
+
+ let(:mr_labels) { nil }
+ let(:mr_json) { nil }
+ let(:fake_gitlab) { double('fake-gitlab', mr_labels: mr_labels, mr_json: mr_json) }
+
+ let(:changes_by_category) { nil }
+ let(:ee?) { false }
+ let(:fake_helper) { double('fake-helper', changes_by_category: changes_by_category, ee?: ee?) }
+
+ let(:fake_danger) { new_fake_danger.include(described_class) }
+
+ subject(:changelog) { fake_danger.new(git: fake_git, gitlab: fake_gitlab, helper: fake_helper) }
+
+ describe '#needed?' do
+ subject { changelog.needed? }
+
+ [
+ { docs: nil },
+ { none: nil },
+ { docs: nil, none: nil }
+ ].each do |categories|
+ let(:changes_by_category) { categories }
+ it "is falsy when categories don't require a changelog" do
+ is_expected.to be_falsy
+ end
+ end
+
+ where(:categories, :labels) do
+ { backend: nil } | %w[backend backstage]
+ { frontend: nil, docs: nil } | ['ci-build']
+ { engineering_productivity: nil, none: nil } | ['meta']
+ end
+
+ with_them do
+ let(:changes_by_category) { categories }
+ let(:mr_labels) { labels }
+
+ it "is falsy when labels require no changelog" do
+ is_expected.to be_falsy
+ end
+ end
+
+ where(:categories, :labels) do
+ { frontend: nil, docs: nil } | ['database::review pending', 'feature']
+ { backend: nil } | ['backend', 'technical debt']
+ { engineering_productivity: nil, none: nil } | ['frontend']
+ end
+
+ with_them do
+ let(:changes_by_category) { categories }
+ let(:mr_labels) { labels }
+
+ it "is truthy when categories and labels require a changelog" do
+ is_expected.to be_truthy
+ end
+ end
+ end
+
+ describe '#found' do
+ subject { changelog.found }
+
+ context 'added files contain a changelog' do
+ [
+ 'changelogs/unreleased/entry.md',
+ 'ee/changelogs/unreleased/entry.md',
+ 'changelogs/unreleased-ee/entry.md',
+ 'ee/changelogs/unreleased-ee/entry.md'
+ ].each do |file_path|
+ let(:added_files) { [file_path] }
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ context 'added files do not contain a changelog' do
+ [
+ 'app/models/model.rb',
+ 'app/assets/javascripts/file.js'
+ ].each do |file_path|
+ let(:added_files) { [file_path] }
+ it { is_expected.to eq(nil) }
+ end
+ end
+ end
+
+ describe '#presented_no_changelog_labels' do
+ subject { changelog.presented_no_changelog_labels }
+
+ it 'returns the labels formatted' do
+ is_expected.to eq('~backstage, ~ci-build, ~meta')
+ end
+ end
+
+ describe '#sanitized_mr_title' do
+ subject { changelog.sanitized_mr_title }
+
+ [
+ 'WIP: My MR title',
+ 'My MR title'
+ ].each do |mr_title|
+ let(:mr_json) { { "title" => mr_title } }
+ it { is_expected.to eq("My MR title") }
+ end
+ end
+
+ describe '#ee_changelog?' do
+ context 'is ee changelog' do
+ [
+ 'changelogs/unreleased-ee/entry.md',
+ 'ee/changelogs/unreleased-ee/entry.md'
+ ].each do |file_path|
+ subject { changelog.ee_changelog?(file_path) }
+
+ it { is_expected.to be_truthy }
+ end
+ end
+
+ context 'is not ee changelog' do
+ [
+ 'changelogs/unreleased/entry.md',
+ 'ee/changelogs/unreleased/entry.md'
+ ].each do |file_path|
+ subject { changelog.ee_changelog?(file_path) }
+
+ it { is_expected.to be_falsy }
+ end
+ end
+ end
+
+ describe '#ce_port_changelog?' do
+ where(:helper_ee?, :file_path, :expected) do
+ true | 'changelogs/unreleased-ee/entry.md' | false
+ true | 'ee/changelogs/unreleased-ee/entry.md' | false
+ false | 'changelogs/unreleased-ee/entry.md' | false
+ false | 'ee/changelogs/unreleased-ee/entry.md' | false
+ true | 'changelogs/unreleased/entry.md' | true
+ true | 'ee/changelogs/unreleased/entry.md' | true
+ false | 'changelogs/unreleased/entry.md' | false
+ false | 'ee/changelogs/unreleased/entry.md' | false
+ end
+
+ with_them do
+ let(:ee?) { helper_ee? }
+ subject { changelog.ce_port_changelog?(file_path) }
+
+ it { is_expected.to eq(expected) }
+ end
+ end
+end
diff --git a/spec/lib/gitlab/danger/danger_spec_helper.rb b/spec/lib/gitlab/danger/danger_spec_helper.rb
new file mode 100644
index 00000000000..b1e84b3c13d
--- /dev/null
+++ b/spec/lib/gitlab/danger/danger_spec_helper.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module DangerSpecHelper
+ def new_fake_danger
+ Class.new do
+ attr_reader :git, :gitlab, :helper
+
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ def initialize(git: nil, gitlab: nil, helper: nil)
+ @git = git
+ @gitlab = gitlab
+ @helper = helper
+ end
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
+ end
+ end
+end
diff --git a/spec/lib/gitlab/danger/helper_spec.rb b/spec/lib/gitlab/danger/helper_spec.rb
index 8056418e697..d7e67444fca 100644
--- a/spec/lib/gitlab/danger/helper_spec.rb
+++ b/spec/lib/gitlab/danger/helper_spec.rb
@@ -2,29 +2,22 @@
require 'fast_spec_helper'
require 'rspec-parameterized'
+require_relative 'danger_spec_helper'
require 'gitlab/danger/helper'
describe Gitlab::Danger::Helper do
using RSpec::Parameterized::TableSyntax
-
- class FakeDanger
- include Gitlab::Danger::Helper
-
- attr_reader :git, :gitlab
-
- def initialize(git:, gitlab:)
- @git = git
- @gitlab = gitlab
- end
- end
+ include DangerSpecHelper
let(:fake_git) { double('fake-git') }
let(:mr_author) { nil }
let(:fake_gitlab) { double('fake-gitlab', mr_author: mr_author) }
- subject(:helper) { FakeDanger.new(git: fake_git, gitlab: fake_gitlab) }
+ let(:fake_danger) { new_fake_danger.include(described_class) }
+
+ subject(:helper) { fake_danger.new(git: fake_git, gitlab: fake_gitlab) }
describe '#gitlab_helper' do
context 'when gitlab helper is not available' do
diff --git a/spec/lib/sentry/client/projects_spec.rb b/spec/lib/sentry/client/projects_spec.rb
new file mode 100644
index 00000000000..462f74eaac9
--- /dev/null
+++ b/spec/lib/sentry/client/projects_spec.rb
@@ -0,0 +1,119 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Sentry::Client::Projects do
+ include SentryClientHelpers
+
+ let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' }
+ let(:token) { 'test-token' }
+ let(:client) { Sentry::Client.new(sentry_url, token) }
+ let(:projects_sample_response) do
+ Gitlab::Utils.deep_indifferent_access(
+ JSON.parse(fixture_file('sentry/list_projects_sample_response.json'))
+ )
+ end
+
+ shared_examples 'has correct return type' do |klass|
+ it "returns objects of type #{klass}" do
+ expect(subject).to all( be_a(klass) )
+ end
+ end
+
+ shared_examples 'has correct length' do |length|
+ it { expect(subject.length).to eq(length) }
+ end
+
+ describe '#projects' do
+ let(:sentry_list_projects_url) { 'https://sentrytest.gitlab.com/api/0/projects/' }
+ let(:sentry_api_response) { projects_sample_response }
+ let!(:sentry_api_request) { stub_sentry_request(sentry_list_projects_url, body: sentry_api_response) }
+
+ subject { client.projects }
+
+ it_behaves_like 'calls sentry api'
+
+ it_behaves_like 'has correct return type', Gitlab::ErrorTracking::Project
+ it_behaves_like 'has correct length', 2
+
+ context 'essential keys missing in API response' do
+ let(:sentry_api_response) do
+ projects_sample_response[0...1].map do |project|
+ project.except(:slug)
+ end
+ end
+
+ it 'raises exception' do
+ expect { subject }.to raise_error(Sentry::Client::MissingKeysError, 'Sentry API response is missing keys. key not found: "slug"')
+ end
+ end
+
+ context 'optional keys missing in sentry response' do
+ let(:sentry_api_response) do
+ projects_sample_response[0...1].map do |project|
+ project[:organization].delete(:id)
+ project.delete(:id)
+ project.except(:status)
+ end
+ end
+
+ it_behaves_like 'calls sentry api'
+
+ it_behaves_like 'has correct return type', Gitlab::ErrorTracking::Project
+ it_behaves_like 'has correct length', 1
+ end
+
+ context 'error object created from sentry response' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:sentry_project_object, :sentry_response) do
+ :id | :id
+ :name | :name
+ :status | :status
+ :slug | :slug
+ :organization_name | [:organization, :name]
+ :organization_id | [:organization, :id]
+ :organization_slug | [:organization, :slug]
+ end
+
+ with_them do
+ it do
+ expect(subject[0].public_send(sentry_project_object)).to(
+ eq(sentry_api_response[0].dig(*sentry_response))
+ )
+ end
+ end
+ end
+
+ context 'redirects' do
+ let(:sentry_api_url) { sentry_list_projects_url }
+
+ it_behaves_like 'no Sentry redirects'
+ end
+
+ # Sentry API returns 404 if there are extra slashes in the URL!
+ context 'extra slashes in URL' do
+ let(:sentry_url) { 'https://sentrytest.gitlab.com/api//0/projects//' }
+ let!(:valid_req_stub) do
+ stub_sentry_request(sentry_list_projects_url)
+ end
+
+ it 'removes extra slashes in api url' do
+ expect(Gitlab::HTTP).to receive(:get).with(
+ URI(sentry_list_projects_url),
+ anything
+ ).and_call_original
+
+ subject
+
+ expect(valid_req_stub).to have_been_requested
+ end
+ end
+
+ context 'when exception is raised' do
+ let(:sentry_request_url) { sentry_list_projects_url }
+
+ it_behaves_like 'maps Sentry exceptions'
+ end
+ end
+end
diff --git a/spec/lib/sentry/client_spec.rb b/spec/lib/sentry/client_spec.rb
index 388a6418929..cff06bf4a5f 100644
--- a/spec/lib/sentry/client_spec.rb
+++ b/spec/lib/sentry/client_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
describe Sentry::Client do
+ include SentryClientHelpers
+
let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' }
let(:token) { 'test-token' }
let(:default_httparty_options) do
@@ -18,89 +20,18 @@ describe Sentry::Client do
)
end
- let(:projects_sample_response) do
- Gitlab::Utils.deep_indifferent_access(
- JSON.parse(fixture_file('sentry/list_projects_sample_response.json'))
- )
- end
-
subject(:client) { described_class.new(sentry_url, token) }
- # Requires sentry_api_url and subject to be defined
- shared_examples 'no redirects' do
- let(:redirect_to) { 'https://redirected.example.com' }
- let(:other_url) { 'https://other.example.org' }
-
- let!(:redirected_req_stub) { stub_sentry_request(other_url) }
-
- let!(:redirect_req_stub) do
- stub_sentry_request(
- sentry_api_url,
- status: 302,
- headers: { location: redirect_to }
- )
- end
-
- it 'does not follow redirects' do
- expect { subject }.to raise_exception(Sentry::Client::Error, 'Sentry response status code: 302')
- expect(redirect_req_stub).to have_been_requested
- expect(redirected_req_stub).not_to have_been_requested
- end
- end
-
- shared_examples 'has correct return type' do |klass|
- it "returns objects of type #{klass}" do
- expect(subject).to all( be_a(klass) )
- end
- end
-
shared_examples 'issues has correct return type' do |klass|
it "returns objects of type #{klass}" do
expect(subject[:issues]).to all( be_a(klass) )
end
end
- shared_examples 'has correct length' do |length|
- it { expect(subject.length).to eq(length) }
- end
-
shared_examples 'issues has correct length' do |length|
it { expect(subject[:issues].length).to eq(length) }
end
- # Requires sentry_api_request and subject to be defined
- shared_examples 'calls sentry api' do
- it 'calls sentry api' do
- subject
-
- expect(sentry_api_request).to have_been_requested
- end
- end
-
- shared_examples 'maps exceptions' do
- exceptions = {
- Gitlab::HTTP::Error => 'Error when connecting to Sentry',
- Net::OpenTimeout => 'Connection to Sentry timed out',
- SocketError => 'Received SocketError when trying to connect to Sentry',
- OpenSSL::SSL::SSLError => 'Sentry returned invalid SSL data',
- Errno::ECONNREFUSED => 'Connection refused',
- StandardError => 'Sentry request failed due to StandardError'
- }
-
- exceptions.each do |exception, message|
- context "#{exception}" do
- before do
- stub_request(:get, sentry_request_url).to_raise(exception)
- end
-
- it do
- expect { subject }
- .to raise_exception(Sentry::Client::Error, message)
- end
- end
- end
- end
-
describe '#list_issues' do
let(:issue_status) { 'unresolved' }
let(:limit) { 20 }
@@ -174,7 +105,7 @@ describe Sentry::Client do
context 'redirects' do
let(:sentry_api_url) { sentry_url + '/issues/?limit=20&query=is:unresolved' }
- it_behaves_like 'no redirects'
+ it_behaves_like 'no Sentry redirects'
end
# Sentry API returns 404 if there are extra slashes in the URL!
@@ -265,7 +196,7 @@ describe Sentry::Client do
end
end
- it_behaves_like 'maps exceptions'
+ it_behaves_like 'maps Sentry exceptions'
context 'when search term is present' do
let(:search_term) { 'NoMethodError' }
@@ -287,112 +218,4 @@ describe Sentry::Client do
it_behaves_like 'issues has correct length', 1
end
end
-
- describe '#list_projects' do
- let(:sentry_list_projects_url) { 'https://sentrytest.gitlab.com/api/0/projects/' }
-
- let(:sentry_api_response) { projects_sample_response }
-
- let!(:sentry_api_request) { stub_sentry_request(sentry_list_projects_url, body: sentry_api_response) }
-
- subject { client.list_projects }
-
- it_behaves_like 'calls sentry api'
-
- it_behaves_like 'has correct return type', Gitlab::ErrorTracking::Project
- it_behaves_like 'has correct length', 2
-
- context 'essential keys missing in API response' do
- let(:sentry_api_response) do
- projects_sample_response[0...1].map do |project|
- project.except(:slug)
- end
- end
-
- it 'raises exception' do
- expect { subject }.to raise_error(Sentry::Client::MissingKeysError, 'Sentry API response is missing keys. key not found: "slug"')
- end
- end
-
- context 'optional keys missing in sentry response' do
- let(:sentry_api_response) do
- projects_sample_response[0...1].map do |project|
- project[:organization].delete(:id)
- project.delete(:id)
- project.except(:status)
- end
- end
-
- it_behaves_like 'calls sentry api'
-
- it_behaves_like 'has correct return type', Gitlab::ErrorTracking::Project
- it_behaves_like 'has correct length', 1
- end
-
- context 'error object created from sentry response' do
- using RSpec::Parameterized::TableSyntax
-
- where(:sentry_project_object, :sentry_response) do
- :id | :id
- :name | :name
- :status | :status
- :slug | :slug
- :organization_name | [:organization, :name]
- :organization_id | [:organization, :id]
- :organization_slug | [:organization, :slug]
- end
-
- with_them do
- it do
- expect(subject[0].public_send(sentry_project_object)).to(
- eq(sentry_api_response[0].dig(*sentry_response))
- )
- end
- end
- end
-
- context 'redirects' do
- let(:sentry_api_url) { sentry_list_projects_url }
-
- it_behaves_like 'no redirects'
- end
-
- # Sentry API returns 404 if there are extra slashes in the URL!
- context 'extra slashes in URL' do
- let(:sentry_url) { 'https://sentrytest.gitlab.com/api//0/projects//' }
- let(:client) { described_class.new(sentry_url, token) }
-
- let!(:valid_req_stub) do
- stub_sentry_request(sentry_list_projects_url)
- end
-
- it 'removes extra slashes in api url' do
- expect(Gitlab::HTTP).to receive(:get).with(
- URI(sentry_list_projects_url),
- anything
- ).and_call_original
-
- subject
-
- expect(valid_req_stub).to have_been_requested
- end
- end
-
- context 'when exception is raised' do
- let(:sentry_request_url) { sentry_list_projects_url }
-
- it_behaves_like 'maps exceptions'
- end
- end
-
- private
-
- def stub_sentry_request(url, body: {}, status: 200, headers: {})
- stub_request(:get, url)
- .to_return(
- status: status,
- headers: { 'Content-Type' => 'application/json' }.merge(headers),
- body: body.to_json
- )
- end
end
diff --git a/spec/models/error_tracking/project_error_tracking_setting_spec.rb b/spec/models/error_tracking/project_error_tracking_setting_spec.rb
index 6bb09205a7b..ef426661066 100644
--- a/spec/models/error_tracking/project_error_tracking_setting_spec.rb
+++ b/spec/models/error_tracking/project_error_tracking_setting_spec.rb
@@ -193,7 +193,7 @@ describe ErrorTracking::ProjectErrorTrackingSetting do
it 'calls sentry client' do
expect(subject).to receive(:sentry_client).and_return(sentry_client)
- expect(sentry_client).to receive(:list_projects).and_return(projects)
+ expect(sentry_client).to receive(:projects).and_return(projects)
result = subject.list_sentry_projects
diff --git a/spec/support/helpers/sentry_client_helpers.rb b/spec/support/helpers/sentry_client_helpers.rb
new file mode 100644
index 00000000000..7476b5fb249
--- /dev/null
+++ b/spec/support/helpers/sentry_client_helpers.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+module SentryClientHelpers
+ private
+
+ def stub_sentry_request(url, body: {}, status: 200, headers: {})
+ stub_request(:get, url)
+ .to_return(
+ status: status,
+ headers: { 'Content-Type' => 'application/json' }.merge(headers),
+ body: body.to_json
+ )
+ end
+end
diff --git a/spec/support/shared_examples/lib/sentry/client_shared_examples.rb b/spec/support/shared_examples/lib/sentry/client_shared_examples.rb
new file mode 100644
index 00000000000..76b71ebd3c5
--- /dev/null
+++ b/spec/support/shared_examples/lib/sentry/client_shared_examples.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+# Requires sentry_api_request and subject to be defined
+RSpec.shared_examples 'calls sentry api' do
+ it 'calls sentry api' do
+ subject
+
+ expect(sentry_api_request).to have_been_requested
+ end
+end
+
+# Requires sentry_api_url and subject to be defined
+RSpec.shared_examples 'no Sentry redirects' do
+ let(:redirect_to) { 'https://redirected.example.com' }
+ let(:other_url) { 'https://other.example.org' }
+
+ let!(:redirected_req_stub) { stub_sentry_request(other_url) }
+
+ let!(:redirect_req_stub) do
+ stub_sentry_request(
+ sentry_api_url,
+ status: 302,
+ headers: { location: redirect_to }
+ )
+ end
+
+ it 'does not follow redirects' do
+ expect { subject }.to raise_exception(Sentry::Client::Error, 'Sentry response status code: 302')
+ expect(redirect_req_stub).to have_been_requested
+ expect(redirected_req_stub).not_to have_been_requested
+ end
+end
+
+RSpec.shared_examples 'maps Sentry exceptions' do
+ exceptions = {
+ Gitlab::HTTP::Error => 'Error when connecting to Sentry',
+ Net::OpenTimeout => 'Connection to Sentry timed out',
+ SocketError => 'Received SocketError when trying to connect to Sentry',
+ OpenSSL::SSL::SSLError => 'Sentry returned invalid SSL data',
+ Errno::ECONNREFUSED => 'Connection refused',
+ StandardError => 'Sentry request failed due to StandardError'
+ }
+
+ exceptions.each do |exception, message|
+ context "#{exception}" do
+ before do
+ stub_request(:get, sentry_request_url).to_raise(exception)
+ end
+
+ it do
+ expect { subject }
+ .to raise_exception(Sentry::Client::Error, message)
+ end
+ end
+ end
+end
diff --git a/vendor/gitignore/C++.gitignore b/vendor/gitignore/C++.gitignore
index 259148fa18f..259148fa18f 100755..100644
--- a/vendor/gitignore/C++.gitignore
+++ b/vendor/gitignore/C++.gitignore
diff --git a/vendor/gitignore/Java.gitignore b/vendor/gitignore/Java.gitignore
index a1c2a238a96..a1c2a238a96 100755..100644
--- a/vendor/gitignore/Java.gitignore
+++ b/vendor/gitignore/Java.gitignore