Commit 74a89b12 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent b0abae12
Please view this file on the master branch, on stable branches it's out of date.
## 12.6.4
- No changes.
## 12.6.2
### Security (2 changes)
......@@ -228,6 +232,10 @@ Please view this file on the master branch, on stable branches it's out of date.
- Remove IIFEs from jira_connect.js file. !19248 (nuwe1)
## 12.4.8
- No changes.
## 12.4.5
- No changes.
......
......@@ -124,9 +124,7 @@ export default {
},
},
mounted() {
if (!this.allValuesEmpty) {
this.draw();
}
},
methods: {
draw() {
......@@ -153,7 +151,14 @@ export default {
this.yScale = d3.scaleLinear().rangeRound([this.vbHeight, 0]);
this.xScale.domain(this.graphData.map(d => d.name));
this.yScale.domain([0, d3.max(this.graphData.map(d => d.value))]);
/*
If we have all-zero graph we want graph to center 0 on axis and not to draw
any kind of ticks on Y axis. Infinity allows us to do that.
See https://gitlab.com/gitlab-org/gitlab/merge_requests/20627#note_251484582
for detailed explanation
*/
this.yScale.domain([0, d3.max(this.graphData.map(d => d.value)) || Infinity]);
// Zoom/Panning Function
this.zoom = d3
......
......@@ -39,6 +39,7 @@ class MergeRequestsFinder < IssuableFinder
def filter_items(_items)
items = by_commit(super)
items = by_deployment(items)
items = by_source_branch(items)
items = by_wip(items)
items = by_target_branch(items)
......@@ -101,6 +102,17 @@ class MergeRequestsFinder < IssuableFinder
.or(table[:title].matches('WIP %'))
.or(table[:title].matches('[WIP]%'))
end
def by_deployment(items)
return items unless deployment_id
items.includes(:deployment_merge_requests)
.where(deployment_merge_requests: { deployment_id: deployment_id })
end
def deployment_id
@deployment_id ||= params[:deployment_id].presence
end
end
MergeRequestsFinder.prepend_if_ee('EE::MergeRequestsFinder')
......@@ -11,6 +11,7 @@ class ApplicationSetting < ApplicationRecord
add_authentication_token_field :static_objects_external_storage_auth_token
belongs_to :instance_administration_project, class_name: "Project"
belongs_to :instance_administrators_group, class_name: "Group"
# Include here so it can override methods from
# `add_authentication_token_field`
......
---
title: Add API support for retrieving merge requests deployed in a deployment
merge_request: 21837
author:
type: added
---
title: Save Instance Administrators group ID in DB
merge_request: 22600
author:
type: changed
---
title: Add structured logging for application logs
merge_request: 22379
author:
type: other
---
title: Add API for getting sentry error tracking settings of a project
merge_request: 21788
author: raju249
type: added
---
title: Update d3 to 5.12
merge_request: 20627
author: Praveen Arimbrathodiyil
type: other
---
title: Fix private objects exposure when using Project Import functionality
merge_request:
author:
type: security
# frozen_string_literal: true
# See http://doc.gitlab.com/ce/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddColumnForInstanceAdministratorsGroup < ActiveRecord::Migration[5.2]
DOWNTIME = false
def change
add_column :application_settings, :instance_administrators_group_id, :integer
end
end
# frozen_string_literal: true
class AddFkForInstanceAdministratorsGroup < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_foreign_key(
:application_settings,
:namespaces,
column: :instance_administrators_group_id,
on_delete: :nullify
)
end
def down
remove_foreign_key :application_settings, column: :instance_administrators_group_id
end
end
# frozen_string_literal: true
class AddIndexForInstanceAdministratorsGroup < ActiveRecord::Migration[5.2]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def up
add_concurrent_index :application_settings, :instance_administrators_group_id
end
def down
remove_concurrent_index :application_settings, :instance_administrators_group_id
end
end
......@@ -365,9 +365,11 @@ ActiveRecord::Schema.define(version: 2020_01_08_233040) do
t.text "encrypted_slack_app_verification_token"
t.string "encrypted_slack_app_verification_token_iv", limit: 255
t.boolean "updating_name_disabled_for_users", default: false, null: false
t.integer "instance_administrators_group_id"
t.index ["custom_project_templates_group_id"], name: "index_application_settings_on_custom_project_templates_group_id"
t.index ["file_template_project_id"], name: "index_application_settings_on_file_template_project_id"
t.index ["instance_administration_project_id"], name: "index_applicationsettings_on_instance_administration_project_id"
t.index ["instance_administrators_group_id"], name: "index_application_settings_on_instance_administrators_group_id"
t.index ["usage_stats_set_by_user_id"], name: "index_application_settings_on_usage_stats_set_by_user_id"
end
......@@ -4414,6 +4416,7 @@ ActiveRecord::Schema.define(version: 2020_01_08_233040) do
add_foreign_key "analytics_repository_file_edits", "projects", on_delete: :cascade
add_foreign_key "analytics_repository_files", "projects", on_delete: :cascade
add_foreign_key "application_settings", "namespaces", column: "custom_project_templates_group_id", on_delete: :nullify
add_foreign_key "application_settings", "namespaces", column: "instance_administrators_group_id", name: "fk_e8a145f3a7", on_delete: :nullify
add_foreign_key "application_settings", "projects", column: "file_template_project_id", name: "fk_ec757bd087", on_delete: :nullify
add_foreign_key "application_settings", "projects", column: "instance_administration_project_id", on_delete: :nullify
add_foreign_key "application_settings", "users", column: "usage_stats_set_by_user_id", name: "fk_964370041d", on_delete: :nullify
......
......@@ -29,6 +29,7 @@ The following API resources are available in the project context:
| [Deployments](deployments.md) | `/projects/:id/deployments` |
| [Discussions](discussions.md) (threaded comments) | `/projects/:id/issues/.../discussions`, `/projects/:id/snippets/.../discussions`, `/projects/:id/merge_requests/.../discussions`, `/projects/:id/commits/.../discussions` (also available for groups) |
| [Environments](environments.md) | `/projects/:id/environments` |
| [Error Tracking](error_tracking.md) | `/projects/:id/error_tracking/settings` |
| [Events](events.md) | `/projects/:id/events` (also available for users and standalone) |
| [Issues](issues.md) | `/projects/:id/issues` (also available for groups and standalone) |
| [Issues Statistics](issues_statistics.md) | `/projects/:id/issues_statistics` (also available for groups and standalone) |
......
......@@ -349,3 +349,19 @@ Example of a response:
"deployable": null
}
```
## List of merge requests associated with a deployment
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/35739) in GitLab 12.7.
This API retrieves the list of merge requests shipped with a given deployment:
```
GET /projects/:id/deployments/:deployment_id/merge_requests
```
It supports the same parameters as the [Merge Requests API](./merge_requests.md#list-merge-requests) and will return a response using the same format:
```bash
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments/42"
```
# Error Tracking settings API
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/34940) in GitLab 12.7.
## Error Tracking project settings
The project settings API allows you to retrieve the Error Tracking settings for a project. Only for project maintainers.
### Get Error Tracking settings
```
GET /projects/:id/error_tracking/settings
```
| Attribute | Type | Required | Description |
| --------- | ------- | -------- | --------------------- |
| `id` | integer | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
```bash
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/error_tracking/settings
```
Example response:
```json
{
"project_name": "sample sentry project",
"sentry_external_url": "https://sentry.io/myawesomeproject/project",
"api_url": "https://sentry.io/api/0/projects/myawesomeproject/project"
}
```
......@@ -550,7 +550,7 @@ Parameters:
},
"user" : {
"can_merge" : false
}
},
"assignee": {
"id": 1,
"name": "Administrator",
......
......@@ -127,6 +127,88 @@ importer progresses. Here's what to do:
logger.info(message: "Import error", error_code: 1, error: "I/O failure")
```
## Multi-destination Logging
GitLab is transitioning from unstructured/plaintext logs to structured/JSON logs. During this transition period some logs will be recorded in multiple formats through multi-destination logging.
### How to use multi-destination logging
Create a new logger class, inheriting from `MultiDestinationLogger` and add an array of loggers to a `LOGGERS` constant. The loggers should be classes that descend from `Gitlab::Logger`. e.g. the user defined loggers in the following examples, could be inheriting from `Gitlab::Logger` and `Gitlab::JsonLogger`, respectively.
You must specify one of the loggers as the `primary_logger`. The `primary_logger` will be used when information about this multi-destination logger is displayed in the app, e.g. using the `Gitlab::Logger.read_latest` method.
The following example sets one of the defined `LOGGERS` as a `primary_logger`.
```ruby
module Gitlab
class FancyMultiLogger < Gitlab::MultiDestinationLogger
LOGGERS = [UnstructuredLogger, StructuredLogger].freeze
def self.loggers
LOGGERS
end
def primary_logger
UnstructuredLogger
end
end
end
```
You can now call the usual logging methods on this multi-logger, e.g.
```ruby
FancyMultiLogger.info(message: "Information")
```
This message will be logged by each logger registered in `FancyMultiLogger.loggers`.
### Passing a string or hash for logging
When passing a string or hash to a `MultiDestinationLogger`, the log lines could be formatted differently, depending on the kinds of `LOGGERS` set.
e.g. let's partially define the loggers from the previous example:
```ruby
module Gitlab
# Similar to AppTextLogger
class UnstructuredLogger < Gitlab::Logger
...
end
# Similar to AppJsonLogger
class StructuredLogger < Gitlab::JsonLogger
...
end
end
```
Here are some examples of how messages would be handled by both the loggers.
1. When passing a string
```ruby
FancyMultiLogger.info("Information")
# UnstructuredLogger
I, [2020-01-13T12:02:41.566219 #6652] INFO -- : Information
# StructuredLogger
{:severity=>"INFO", :time=>"2020-01-13T11:02:41.559Z", :correlation_id=>"b1701f7ecc4be4bcd4c2d123b214e65a", :message=>"Information"}
```
1. When passing a hash
```ruby
FancyMultiLogger.info({:message=>"This is my message", :project_id=>123})
# UnstructuredLogger
I, [2020-01-13T12:06:09.856766 #8049] INFO -- : {:message=>"This is my message", :project_id=>123}
# StructuredLogger
{:severity=>"INFO", :time=>"2020-01-13T11:06:09.851Z", :correlation_id=>"d7e0886f096db9a8526a4f89da0e45f6", :message=>"This is my message", :project_id=>123}
```
## Exception Handling
It often happens that you catch the exception and want to track it.
......
......@@ -34,8 +34,8 @@ a pipeline in the [`gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/) projec
by triggering the `package-and-qa` manual action in the `test` stage (not
available for forks).
**This runs end-to-end tests against a custom Omnibus package built from your
merge request's changes.**
**This runs end-to-end tests against a custom CE and EE (with an Ultimate license)
Omnibus package built from your merge request's changes.**
Manual action that starts end-to-end tests is also available in merge requests
in [Omnibus GitLab][omnibus-gitlab].
......
......@@ -155,7 +155,7 @@ Identity Provider.
### Requirements
First you need to tell GitLab where to look for group information. For this you
need to make sure that your IdP server sends a specific `AttributeStament` along
need to make sure that your IdP server sends a specific `AttributeStatement` along
with the regular SAML response. Here is an example:
```xml
......
......@@ -117,6 +117,7 @@ module API
mount ::API::DeployKeys
mount ::API::Deployments
mount ::API::Environments
mount ::API::ErrorTracking
mount ::API::Events
mount ::API::Features
mount ::API::Files
......
......@@ -127,6 +127,26 @@ module API
render_validation_error!(deployment)
end
end
helpers Helpers::MergeRequestsHelpers
desc 'Get all merge requests of a deployment' do
detail 'This feature was introduced in GitLab 12.7.'
success Entities::MergeRequestBasic
end
params do
requires :deployment_id, type: Integer, desc: 'The deployment ID'
use :merge_requests_base_params
end
get ':id/deployments/:deployment_id/merge_requests' do
authorize! :read_deployment, user_project
mr_params = declared_params.merge(deployment_id: params[:deployment_id])
merge_requests = MergeRequestsFinder.new(current_user, mr_params).execute
present merge_requests, { with: Entities::MergeRequestBasic, current_user: current_user }
end
end
end
end
# frozen_string_literal: true
module API
module Entities
module ErrorTracking
class ProjectSetting < Grape::Entity
expose :project_name
expose :sentry_external_url
expose :api_url
end
end
end
end
# frozen_string_literal: true
module API
class ErrorTracking < Grape::API
before { authenticate! }
params do
requires :id, type: String, desc: 'The ID of a project'
end
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
desc 'Get error tracking settings for the project' do
detail 'This feature was introduced in GitLab 12.7.'
success Entities::ErrorTracking::ProjectSetting
end
get ':id/error_tracking/settings' do
authorize! :admin_operations, user_project
setting = user_project.error_tracking_setting
not_found!('Error Tracking Setting') unless setting
present setting, with: Entities::ErrorTracking::ProjectSetting
end
end
end
end
# frozen_string_literal: true
module API
module Helpers
module MergeRequestsHelpers
extend Grape::API::Helpers
include ::API::Helpers::CustomValidators
params :merge_requests_base_params do
optional :state,
type: String,
values: %w[opened closed locked merged all],
default: 'all',
desc: 'Return opened, closed, locked, merged, or all merge requests'
optional :order_by,
type: String,
values: %w[created_at updated_at],
default: 'created_at',
desc: 'Return merge requests ordered by `created_at` or `updated_at` fields.'
optional :sort,
type: String,
values: %w[asc desc],
default: 'desc',
desc: 'Return merge requests sorted in `asc` or `desc` order.'
optional :milestone, type: String, desc: 'Return merge requests for a specific milestone'
optional :labels,
type: Array[String],
coerce_with: Validations::Types::LabelsList.coerce,
desc: 'Comma-separated list of label names'
optional :with_labels_details, type: Boolean, desc: 'Return titles of labels and other details', default: false
optional :created_after, type: DateTime, desc: 'Return merge requests created after the specified time'
optional :created_before, type: DateTime, desc: 'Return merge requests created before the specified time'
optional :updated_after, type: DateTime, desc: 'Return merge requests updated after the specified time'
optional :updated_before, type: DateTime, desc: 'Return merge requests updated before the specified time'
optional :view,
type: String,
values: %w[simple],
desc: 'If simple, returns the `iid`, URL, title, description, and basic state of merge request'
optional :author_id, type: Integer, desc: 'Return merge requests which are authored by the user with the given ID'
optional :assignee_id,
types: [Integer, String],
integer_none_any: true,
desc: 'Return merge requests which are assigned to the user with the given ID'
optional :scope,
type: String,
values: %w[created-by-me assigned-to-me created_by_me assigned_to_me all],
desc: 'Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`'
optional :my_reaction_emoji, type: String, desc: 'Return issues reacted by the authenticated user by the given emoji'
optional :source_branch, type: String, desc: 'Return merge requests with the given source branch'
optional :source_project_id, type: Integer, desc: 'Return merge requests with the given source project id'
optional :target_branch, type: String, desc: 'Return merge requests with the given target branch'
optional :search,
type: String,
desc: 'Search merge requests for text present in the title, description, or any combination of these'
optional :in, type: String, desc: '`title`, `description`, or a string joining them with comma'
optional :wip, type: String, values: %w[yes no], desc: 'Search merge requests for WIP in the title'
end
params :optional_scope_param do
optional :scope,
type: String,
values: %w[created-by-me assigned-to-me created_by_me assigned_to_me all],
default: 'created_by_me',
desc: 'Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`'
end
end
end
end
......@@ -7,6 +7,7 @@ module API
before { authenticate_non_get! }
helpers ::Gitlab::IssuableMetadata
helpers Helpers::MergeRequestsHelpers
# EE::API::MergeRequests would override the following helpers
helpers do
......@@ -107,33 +108,7 @@ module API
end
params :merge_requests_params do
optional :state, type: String, values: %w[opened closed locked merged all], default: 'all',
desc: 'Return opened, closed, locked, merged, or all merge requests'
optional :order_by, type: String, values: %w[created_at updated_at], default: 'created_at',
desc: 'Return merge requests ordered by `created_at` or `updated_at` fields.'
optional :sort, type: String, values: %w[asc desc], default: 'desc',
desc: 'Return merge requests sorted in `asc` or `desc` order.'
optional :milestone, type: String, desc: 'Return merge requests for a specific milestone'
optional :labels, type: Array[String], coerce_with: Validations::Types::LabelsList.coerce, desc: 'Comma-separated list of label names'
optional :with_labels_details, type: Boolean, desc: 'Return titles of labels and other details', default: false
optional :created_after, type: DateTime, desc: 'Return merge requests created after the specified time'
optional :created_before, type: DateTime, desc: 'Return merge requests created before the specified time'
optional :updated_after, type: DateTime, desc: 'Return merge requests updated after the specified time'
optional :updated_before, type: DateTime, desc: 'Return merge requests updated before the specified time'
optional :view, type: String, values: %w[simple], desc: 'If simple, returns the `iid`, URL, title, description, and basic state of merge request'
optional :author_id, type: Integer, desc: 'Return merge requests which are authored by the user with the given ID'
optional :assignee_id, types: [Integer, String], integer_none_any: true,
desc: 'Return merge requests which are assigned to the user with the given ID'
optional :scope, type: String, values: %w[created-by-me assigned-to-me created_by_me assigned_to_me all],
desc: 'Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`'
optional :my_reaction_emoji, type: String, desc: 'Return issues reacted by the authenticated user by the given emoji'
optional :source_branch, type: String, desc: 'Return merge requests with the given source branch'
optional :source_project_id, type: Integer, desc: 'Return merge requests with the given source project id'
optional :target_branch, type: String, desc: 'Return merge requests with the given target branch'
optional :search, type: String, desc: 'Search merge requests for text present in the title, description, or any combination of these'
optional :in, type: String, desc: '`title`, `description`, or a string joining them with comma'
optional :wip, type: String, values: %w[yes no], desc: 'Search merge requests for WIP in the title'
use :merge_requests_base_params
use :optional_merge_requests_search_params
use :pagination
end
......@@ -145,8 +120,7 @@ module API
end
params do
use :merge_requests_params
optional :scope, type: String, values: %w[created-by-me assigned-to-me created_by_me assigned_to_me all], default: 'created_by_me',
desc: 'Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`'
use :optional_scope_param
end
get do
authenticate! unless params[:scope] == 'all'
......
# frozen_string_literal: true
module Gitlab
class AppJsonLogger < Gitlab::JsonLogger
def self.file_name_noext
'application_json'
end
end
end
# frozen_string_literal: true
module Gitlab
class AppLogger < Gitlab::Logger
def self.file_name_noext
'application'
class AppLogger < Gitlab::MultiDestinationLogger
LOGGERS = [Gitlab::AppTextLogger, Gitlab::AppJsonLogger].freeze
def self.loggers
LOGGERS
end
def format_message(severity, timestamp, progname, msg)
"#{timestamp.to_s(:long)}: #{msg}\n"
def self.primary_logger
Gitlab::AppTextLogger
end
end
end
# frozen_string_literal: true
module Gitlab
class AppTextLogger < Gitlab::Logger
def self.file_name_noext
'application'
end
def format_message(severity, timestamp, progname, msg)
"#{timestamp.to_s(:long)}: #{msg}\n"
end
end
end
# frozen_string_literal: true
module Gitlab
class MultiDestinationLogger < ::Logger
def close
loggers.each(&:close)
end
def self.debug(message)
loggers.each { |logger| logger.build.debug(message) }
end
def self.error(message)
loggers.each { |logger| logger.build.error(message) }
end
def self.warn(message)
loggers.each { |logger| logger.build.warn(message) }
end
def self.info(message)
loggers.each { |logger| logger.build.info(message) }
end
def self.read_latest
primary_logger.read_latest
end
def self.file_name
primary_logger.file_name
end
def self.full_log_path
primary_logger.full_log_path
end
def self.file_name_noext
primary_logger.file_name_noext
end
def self.loggers
raise NotImplementedError
end
def self.primary_logger
raise NotImplementedError
end
end
end
......@@ -22,8 +22,15 @@ module QA
expect(page).to have_content(/@#{user.username}(\n| )?Given access/)
# Wait for Action Mailer to deliver messages
mailhog_json = Support::Retrier.retry_until(sleep_interval: 1) do
mailhog_items = mailhog_json.dig('items')
expect(mailhog_items).to include(an_object_satisfying { |o| /project was granted/ === o.dig('Content', 'Headers', 'Subject', 0) })
end
private
def mailhog_json
Support::Retrier.retry_until(sleep_interval: 1) do
Runtime::Logger.debug(%Q[retrieving "#{QA::Runtime::MailHog.api_messages_url}"])
mailhog_response = get QA::Runtime::MailHog.api_messages_url
......@@ -33,10 +40,6 @@ module QA
# Expect at least two invitation messages: group and project
mailhog_data if mailhog_data.dig('total') >= 2
end
# Check json result from mailhog
mailhog_items = mailhog_json.dig('items')
expect(mailhog_items).to include(an_object_satisfying { |o| /project was granted/ === o.dig('Content', 'Headers', 'Subject', 0) })
end
end
end
......
......@@ -28,11 +28,9 @@ module QA
end
before do
issue = Resource::Issue.fabricate_via_api! do |issue|
Resource::Issue.fabricate_via_api! do |issue|
issue.title = issue_title
end
issue.visit!
end.visit!
end
it 'user comments on an issue with an attachment' do
......
......@@ -8,11 +8,9 @@ module QA
before do
Flow::Login.sign_in
issue = Resource::Issue.fabricate_via_api! do |issue|
Resource::Issue.fabricate_via_api! do |issue|
issue.title = issue_title
end
issue.visit!
end.visit!
end
it 'user filters comments and activities in an issue' do
......
......@@ -166,6 +166,38 @@ describe MergeRequestsFinder do
expect(scalar_params).to include(:wip, :assignee_id)
end
context 'filter by deployment' do
let_it_be(:project_with_repo) { create(:project, :repository) }
it 'returns the relevant merge requests' do
deployment1 = create(
:deployment,
project: project_with_repo,
sha: project_with_repo.commit.id,
merge_requests: [merge_request1, merge_request2]
)
create(
:deployment,
project: project_with_repo,
sha: project_with_repo.commit.id,
merge_requests: [merge_request3]
)
params = { deployment_id: deployment1.id }
merge_requests = described_class.new(user, params).execute
expect(merge_requests).to contain_exactly(merge_request1, merge_request2)
end
context 'when a deployment does not contain any merge requests' do
it 'returns an empty result' do
params = { deployment_id: create(:deployment, project: project_with_repo, sha: project_with_repo.commit.sha).id }
merge_requests = described_class.new(user, params).execute
expect(merge_requests).to be_empty
end
end
end
end
context 'assignee filtering' do
......
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::AppJsonLogger do
subject { described_class.new('/dev/null') }
let(:hash_message) { { 'message' => 'Message', 'project_id' => '123' } }
let(:string_message) { 'Information' }
it 'logs a hash as a JSON' do
expect(JSON.parse(subject.format_message('INFO', Time.now, nil, hash_message))).to include(hash_message)
end
it 'logs a string as a JSON' do
expect(JSON.parse(subject.format_message('INFO', Time.now, nil, string_message))).to include('message' => string_message)
end
end
......@@ -2,13 +2,21 @@
require 'spec_helper'
describe Gitlab::AppLogger, :request_store do
describe Gitlab::AppLogger do
subject { described_class }
it 'builds a logger once' do
expect(::Logger).to receive(:new).and_call_original
it 'builds a Gitlab::Logger object twice' do
expect(Gitlab::Logger).to receive(:new)
.exactly(described_class.loggers.size)
.and_call_original
subject.info('hello world')
subject.error('hello again')
subject.info('Hello World!')
end
it 'logs info to AppLogger and AppJsonLogger' do
expect_any_instance_of(Gitlab::AppTextLogger).to receive(:info).and_call_original
expect_any_instance_of(Gitlab::AppJsonLogger).to receive(:info).and_call_original
subject.info('Hello World!')
end
end
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::AppTextLogger do
subject { described_class.new('/dev/null') }
let(:hash_message) { { message: 'Message', project_id: 123 } }
let(:string_message) { 'Information' }
it 'logs a hash as string' do
expect(subject.format_message('INFO', Time.now, nil, hash_message )).to include(hash_message.to_s)
end
it 'logs a string unchanged' do
expect(subject.format_message('INFO', Time.now, nil, string_message)).to include(string_message)
end
end
# frozen_string_literal: true
require 'spec_helper'
class FakeLogger
end
class LoggerA < Gitlab::Logger
def self.file_name_noext
'loggerA'
end
end
class LoggerB < Gitlab::JsonLogger
def self.file_name_noext
'loggerB'
end
end
class TestLogger < Gitlab::MultiDestinationLogger
LOGGERS = [LoggerA, LoggerB].freeze
def self.loggers
LOGGERS
end
end
class EmptyLogger < Gitlab::MultiDestinationLogger
def self.loggers
[]
end
end
describe Gitlab::MultiDestinationLogger do
after(:all) do
TestLogger.loggers.each do |logger|
log_file_path = "#{Rails.root}/log/#{logger.file_name}"
File.delete(log_file_path)
end
end
context 'with no primary logger set' do
subject { EmptyLogger }
it 'primary_logger raises an error' do
expect { subject.primary_logger }.to raise_error(NotImplementedError)
end
end
context 'with 2 loggers set' do
subject { TestLogger }
it 'logs info to 2 loggers' do
expect(subject.loggers).to all(receive(:build).and_call_original)
subject.info('Hello World')
end
end
end
......@@ -343,6 +343,48 @@ describe API::Deployments do
end
end
describe 'GET /projects/:id/deployments/:deployment_id/merge_requests' do
let(:project) { create(:project, :repository) }
let!(:deployment) { create(:deployment, :success, project: project) }
subject { get api("/projects/#{project.id}/deployments/#{deployment.id}/merge_requests", user) }
context 'when a user is not a member of the deployment project' do
let(:user) { build(:user) }
it 'returns a 404 status code' do
subject
expect(response).to have_gitlab_http_status(404)
end
end
context 'when a user member of the deployment project' do
let_it_be(:project2) { create(:project) }
let!(:merge_request1) { create(:merge_request, source_project: project, target_project: project) }
let!(:merge_request2) { create(:merge_request, source_project: project, target_project: project, state: 'closed') }
let!(:merge_request3) { create(:merge_request, source_project: project2, target_project: project2) }
it 'returns the relevant merge requests linked to a deployment for a project' do
deployment.merge_requests << [merge_request1, merge_request2]
subject
expect(response).to have_gitlab_http_status(200)
expect(json_response.map { |d| d['id'] }).to contain_exactly(merge_request1.id, merge_request2.id)
end
context 'when a deployment is not associated to any existing merge requests' do
it 'returns an empty array' do
subject
expect(response).to have_gitlab_http_status(200)
expect(json_response).to eq([])
end
end
end
end
context 'prevent N + 1 queries' do
context 'when the endpoint returns multiple records' do
let(:project) { create(:project, :repository) }
......
# frozen_string_literal: true
require 'spec_helper'
describe API::ErrorTracking do
describe "GET /projects/:id/error_tracking/settings" do
let(:user) { create(:user) }
let(:setting) { create(:project_error_tracking_setting) }
let(:project) { setting.project }
def make_request
get api("/projects/#{project.id}/error_tracking/settings", user)
end
context 'when authenticated as maintainer' do
before do
project.add_maintainer(user)
end
it 'returns project settings' do
make_request
expect(response).to have_gitlab_http_status(:ok)
expect(json_response).to eq(
'project_name' => setting.project_name,
'sentry_external_url' => setting.sentry_external_url,
'api_url' => setting.api_url
)
end
end
context 'without a project setting' do
let(:project) { create(:project) }
before do
project.add_maintainer(user)
end
it 'returns 404' do
make_request
expect(response).to have_gitlab_http_status(:not_found)
expect(json_response['message'])
.to eq('404 Error Tracking Setting Not Found')
end
end
context 'when authenticated as reporter' do
before do
project.add_reporter(user)
end
it 'returns 403' do
make_request
expect(response).to have_gitlab_http_status(:forbidden)
end
end
context 'when authenticated as non-member' do
it 'returns 404' do
make_request
expect(response).to have_gitlab_http_status(:not_found)
end
end
context 'when unauthenticated' do
let(:user) { nil }
it 'returns 401' do
make_request
expect(response).to have_gitlab_http_status(:unauthorized)
end
end
end
end
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment