Commit 80e7e95b authored by Stan Hu's avatar Stan Hu

Merge branch 'ce-to-ee-2018-09-11' into 'master'

CE upstream - 2018-09-11 18:21 UTC

See merge request gitlab-org/gitlab-ee!7333
parents 4105c6b6 a3c158d3
# frozen_string_literal: true
module ProjectServicesLoggable module ProjectServicesLoggable
def log_info(message, params = {}) def log_info(message, params = {})
message = build_message(message, params) message = build_message(message, params)
......
# frozen_string_literal: true
class ActiveHookFilter class ActiveHookFilter
def initialize(hook) def initialize(hook)
@hook = hook @hook = hook
......
# frozen_string_literal: true # frozen_string_literal: true
class StatusEntity < Grape::Entity class DetailedStatusEntity < Grape::Entity
include RequestAwareEntity include RequestAwareEntity
expose :icon, :text, :label, :group expose :icon, :text, :label, :group
...@@ -8,6 +8,14 @@ class StatusEntity < Grape::Entity ...@@ -8,6 +8,14 @@ class StatusEntity < Grape::Entity
expose :has_details?, as: :has_details expose :has_details?, as: :has_details
expose :details_path expose :details_path
expose :illustration do |status|
begin
status.illustration
rescue NotImplementedError
# ignored
end
end
expose :favicon do |status| expose :favicon do |status|
Gitlab::Favicon.status_overlay(status.favicon) Gitlab::Favicon.status_overlay(status.favicon)
end end
......
...@@ -27,7 +27,7 @@ class JobEntity < Grape::Entity ...@@ -27,7 +27,7 @@ class JobEntity < Grape::Entity
expose :playable?, as: :playable expose :playable?, as: :playable
expose :created_at expose :created_at
expose :updated_at expose :updated_at
expose :detailed_status, as: :status, with: StatusEntity expose :detailed_status, as: :status, with: DetailedStatusEntity
expose :callout_message, if: -> (*) { failed? && !build.script_failure? } expose :callout_message, if: -> (*) { failed? && !build.script_failure? }
expose :recoverable, if: -> (*) { failed? } expose :recoverable, if: -> (*) { failed? }
......
...@@ -5,7 +5,7 @@ class JobGroupEntity < Grape::Entity ...@@ -5,7 +5,7 @@ class JobGroupEntity < Grape::Entity
expose :name expose :name
expose :size expose :size
expose :detailed_status, as: :status, with: StatusEntity expose :detailed_status, as: :status, with: DetailedStatusEntity
expose :jobs, with: JobEntity expose :jobs, with: JobEntity
private private
......
...@@ -30,7 +30,7 @@ class PipelineEntity < Grape::Entity ...@@ -30,7 +30,7 @@ class PipelineEntity < Grape::Entity
end end
expose :details do expose :details do
expose :detailed_status, as: :status, with: StatusEntity expose :detailed_status, as: :status, with: DetailedStatusEntity
expose :duration expose :duration
expose :finished_at expose :finished_at
end end
......
...@@ -19,7 +19,7 @@ class StageEntity < Grape::Entity ...@@ -19,7 +19,7 @@ class StageEntity < Grape::Entity
latest_statuses latest_statuses
end end
expose :detailed_status, as: :status, with: StatusEntity expose :detailed_status, as: :status, with: DetailedStatusEntity
expose :path do |stage| expose :path do |stage|
project_pipeline_path( project_pipeline_path(
......
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
module Emails module Emails
class BaseService class BaseService
attr_reader :current_user
def initialize(current_user, params = {}) def initialize(current_user, params = {})
@current_user, @params = current_user, params.dup @current_user, @params = current_user, params.dup
@user = params.delete(:user) @user = params.delete(:user)
......
...@@ -5,7 +5,12 @@ module Emails ...@@ -5,7 +5,12 @@ module Emails
prepend ::EE::Emails::CreateService prepend ::EE::Emails::CreateService
def execute(extra_params = {}) def execute(extra_params = {})
@user.emails.create(@params.merge(extra_params)) skip_confirmation = @params.delete(:skip_confirmation)
email = @user.emails.create(@params.merge(extra_params))
email&.confirm if skip_confirmation && current_user.admin?
email
end end
end end
end end
# frozen_string_literal: true
# BranchFilterValidator # BranchFilterValidator
# #
# Custom validator for branch names. Squishes whitespace and ignores empty # Custom validator for branch names. Squishes whitespace and ignores empty
......
# frozen_string_literal: true
class JsRegexValidator < ActiveModel::EachValidator class JsRegexValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value) def validate_each(record, attribute, value)
return true if value.blank? return true if value.blank?
......
...@@ -11,5 +11,5 @@ ...@@ -11,5 +11,5 @@
= render "events/event/note", event: event = render "events/event/note", event: event
- else - else
= render "events/event/common", event: event = render "events/event/common", event: event
- elsif @user.include_private_contributions? - elsif @user&.include_private_contributions?
= render "events/event/private", event: event = render "events/event/private", event: event
---
title: Add empty state illustration information in job API
merge_request: 21532
author:
type: other
---
title: Enable frozen string in vestigial files
merge_request:
author: gfyoung
type: performance
---
title: Add ability to skip user email confirmation with API
merge_request: 21630
author:
type: added
...@@ -35,8 +35,8 @@ module Importers ...@@ -35,8 +35,8 @@ module Importers
attr_reader :content attr_reader :content
def initialize(file = 'config/prometheus/common_metrics.yml') def initialize(filename = 'common_metrics.yml')
@content = YAML.load_file(file) @content = YAML.load_file(Rails.root.join('config', 'prometheus', filename))
end end
def execute def execute
......
...@@ -977,6 +977,7 @@ Parameters: ...@@ -977,6 +977,7 @@ Parameters:
- `id` (required) - id of specified user - `id` (required) - id of specified user
- `email` (required) - email address - `email` (required) - email address
- `skip_confirmation` (optional) - Skip confirmation and assume e-mail is verified - true or false (default)
## Delete email for current user ## Delete email for current user
......
...@@ -12,7 +12,7 @@ class TriggeredPipelineEntity < Grape::Entity ...@@ -12,7 +12,7 @@ class TriggeredPipelineEntity < Grape::Entity
end end
expose :details do expose :details do
expose :detailed_status, as: :status, with: StatusEntity expose :detailed_status, as: :status, with: DetailedStatusEntity
end end
expose :project, using: ProjectEntity expose :project, using: ProjectEntity
......
...@@ -367,6 +367,7 @@ module API ...@@ -367,6 +367,7 @@ module API
params do params do
requires :id, type: Integer, desc: 'The ID of the user' requires :id, type: Integer, desc: 'The ID of the user'
requires :email, type: String, desc: 'The email of the user' requires :email, type: String, desc: 'The email of the user'
optional :skip_confirmation, type: Boolean, desc: 'Skip confirmation of email and assume it is verified'
end end
post ":id/emails" do post ":id/emails" do
authenticated_as_admin! authenticated_as_admin!
......
...@@ -194,6 +194,18 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do ...@@ -194,6 +194,18 @@ describe Projects::JobsController, :clean_gitlab_redis_shared_state do
expect(json_response['terminal_path']).to match(%r{/terminal}) expect(json_response['terminal_path']).to match(%r{/terminal})
end end
end end
context 'when job passed with no trace' do
let(:job) { create(:ci_build, :success, :artifacts, pipeline: pipeline) }
it 'exposes empty state illustrations' do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('job/job_details')
expect(json_response['status']['illustration']).to have_key('image')
expect(json_response['status']['illustration']).to have_key('size')
expect(json_response['status']['illustration']).to have_key('title')
end
end
end end
def get_show(**extra_params) def get_show(**extra_params)
......
...@@ -47,6 +47,16 @@ describe Importers::CommonMetricsImporter do ...@@ -47,6 +47,16 @@ describe Importers::CommonMetricsImporter do
end end
end end
context "does import common_metrics.yml" do
it "when executed from outside of the Rails.root" do
Dir.chdir(Dir.tmpdir) do
expect { subject.execute }.not_to raise_error
end
expect(PrometheusMetric.common).not_to be_empty
end
end
context 'does import properly all fields' do context 'does import properly all fields' do
let(:query_identifier) { 'response-metric' } let(:query_identifier) { 'response-metric' }
let(:group) do let(:group) do
......
require 'spec_helper'
describe 'Project > Activity > User sees private activity', :js do
let(:project) { create(:project, :public) }
let(:author) { create(:user) }
let(:user) { create(:user) }
let(:issue) { create(:issue, :confidential, project: project, author: author) }
let(:message) { "#{author.name} opened issue #{issue.to_reference}" }
before do
project.add_developer(author)
create(:event, :created, project: project, target: issue, author: author)
end
it 'shows the activity to a logged-in user with permissions' do
sign_in(author)
visit activity_project_path(project)
expect(page).to have_content(message)
end
it 'hides the activity from a logged-in user without permissions' do
sign_in(user)
visit activity_project_path(project)
expect(page).not_to have_content(message)
end
it 'hides the activity from an anonymous user' do
visit activity_project_path(project)
expect(page).not_to have_content(message)
end
end
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
"playable": { "type": "boolean" }, "playable": { "type": "boolean" },
"created_at": { "type": "string" }, "created_at": { "type": "string" },
"updated_at": { "type": "string" }, "updated_at": { "type": "string" },
"status": { "$ref": "../ci_detailed_status.json" } "status": { "$ref": "../status/ci_detailed_status.json" }
}, },
"additionalProperties": true "additionalProperties": true
} }
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
"items": { "$ref": "job/job.json" }, "items": { "$ref": "job/job.json" },
"optional": true "optional": true
}, },
"status": { "$ref": "ci_detailed_status.json" }, "status": { "$ref": "status/ci_detailed_status.json" },
"path": { "type": "string" }, "path": { "type": "string" },
"dropdown_path": { "type": "string" } "dropdown_path": { "type": "string" }
}, },
......
{
"type": "object",
"required": [
"icon",
"title",
"path",
"method"
],
"properties": {
"icon": {
"type": "string",
"enum": [
"retry",
"play",
"cancel"
]
},
"title": { "type": "string" },
"path": { "type": "string" },
"method": { "$ref": "../http_method.json" }
}
}
{ {
"type": "object", "type": "object",
"required" : [ "required": [
"icon", "icon",
"text", "text",
"label", "label",
...@@ -19,28 +19,8 @@ ...@@ -19,28 +19,8 @@
"has_details": { "type": "boolean" }, "has_details": { "type": "boolean" },
"details_path": { "type": "string" }, "details_path": { "type": "string" },
"favicon": { "type": "string" }, "favicon": { "type": "string" },
"action": { "illustration": { "$ref": "illustration.json" },
"type": "object", "action": { "$ref": "action.json" }
"required": [
"icon",
"title",
"path",
"method"
],
"properties": {
"icon": {
"type": "string",
"enum": [
"retry",
"play",
"cancel"
]
},
"title": { "type": "string" },
"path": { "type": "string" },
"method": { "$ref": "http_method.json" }
}
}
}, },
"additionalProperties": false "additionalProperties": false
} }
{
"oneOf": [
{ "type": "null" },
{
"type": "object",
"required": [
"image",
"size",
"title"
],
"properties": {
"image": { "type": "string" },
"size": { "type": "string" },
"title": { "type": "string" },
"content": { "type": "string" }
}
}
]
}
...@@ -1064,11 +1064,14 @@ describe API::Users do ...@@ -1064,11 +1064,14 @@ describe API::Users do
expect(json_response['error']).to eq('email is missing') expect(json_response['error']).to eq('email is missing')
end end
it "creates email" do it "creates unverified email" do
email_attrs = attributes_for :email email_attrs = attributes_for :email
expect do expect do
post api("/users/#{user.id}/emails", admin), email_attrs post api("/users/#{user.id}/emails", admin), email_attrs
end.to change { user.emails.count }.by(1) end.to change { user.emails.count }.by(1)
email = Email.find_by(user_id: user.id, email: email_attrs[:email])
expect(email).not_to be_confirmed
end end
it "returns a 400 for invalid ID" do it "returns a 400 for invalid ID" do
...@@ -1076,6 +1079,18 @@ describe API::Users do ...@@ -1076,6 +1079,18 @@ describe API::Users do
expect(response).to have_gitlab_http_status(400) expect(response).to have_gitlab_http_status(400)
end end
it "creates verified email" do
email_attrs = attributes_for :email
email_attrs[:skip_confirmation] = true
post api("/users/#{user.id}/emails", admin), email_attrs
expect(response).to have_gitlab_http_status(201)
email = Email.find_by(user_id: user.id, email: email_attrs[:email])
expect(email).to be_confirmed
end
end end
describe 'GET /user/:id/emails' do describe 'GET /user/:id/emails' do
......
require 'spec_helper' require 'spec_helper'
describe StatusEntity do describe DetailedStatusEntity do
let(:entity) { described_class.new(status) } let(:entity) { described_class.new(status) }
let(:status) do let(:status) do
......
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