Commit 2c269bd9 authored by Dmitriy Zaporozhets's avatar Dmitriy Zaporozhets

Merge branch 'master' into 'ce-to-ee'

# Conflicts:
#   config/webpack.config.js
parents 99f05339 0f29e208
/* eslint-disable no-new, import/first */
/* eslint-disable no-new */
/* global Flash */
/**
* Renders a deploy board.
*
......@@ -17,13 +18,13 @@
* Please refer to this [comment](https://gitlab.com/gitlab-org/gitlab-ee/issues/1589#note_23630610)
* for more information
*/
import statusCodes from '~/lib/utils/http_status';
import '~/flash';
import '~/lib/utils/common_utils';
import deployBoardSvg from 'empty_states/icons/_deploy_board.svg';
import instanceComponent from './deploy_board_instance_component';
const instanceComponent = require('./deploy_board_instance_component');
const statusCodes = require('~/lib/utils/http_status');
const Flash = require('~/flash');
require('~/lib/utils/common_utils');
module.exports = {
export default {
components: {
instanceComponent,
......@@ -61,6 +62,7 @@ module.exports = {
isLoading: false,
hasError: false,
backOffRequestCounter: 0,
deployBoardSvg,
};
},
......@@ -110,7 +112,15 @@ module.exports = {
computed: {
canRenderDeployBoard() {
return !this.isLoading && !this.hasError && Object.keys(this.deployBoardData).length;
return !this.isLoading && !this.hasError && this.deployBoardData.valid;
},
canRenderEmptyState() {
return !this.isLoading && !this.hasError && !this.deployBoardData.valid;
},
canRenderErrorState() {
return !this.isLoading && this.hasError;
},
instanceTitle() {
......@@ -124,6 +134,10 @@ module.exports = {
return title;
},
projectName() {
return '<projectname>';
},
},
template: `
......@@ -149,8 +163,7 @@ module.exports = {
<template v-for="instance in deployBoardData.instances">
<instance-component
:status="instance.status"
:tooltipText="instance.tooltip">
</instance-component>
:tooltipText="instance.tooltip"/>
</template>
</div>
</section>
......@@ -174,7 +187,21 @@ module.exports = {
</section>
</div>
<div v-if="!isLoading && hasError" class="deploy-board-error-message">
<div v-if="canRenderEmptyState">
<section class="deploy-board-empty-state-svg">
${deployBoardSvg}
</section>
<section class="deploy-board-empty-state-text">
<span class="title">Kubernetes deployment not found</span>
<span>
To see deployment progress for your environments, make sure your deployments are in Kubernetes namespace
<code>{{projectName}}</code> and labeled with <code>app=$CI_ENVIRONMENT_SLUG</code>.
</span>
</section>
</div>
<div v-if="canRenderErrorState" class="deploy-board-error-message">
We can't fetch the data right now. Please try again later.
</div>
</div>
......
......@@ -4,14 +4,13 @@
*
* Each instance has a state and a tooltip.
* The state needs to be represented in different colors,
* see more information about this in https://gitlab.com/gitlab-org/gitlab-ee/uploads/5fff049fd88336d9ee0c6ef77b1ba7e3/monitoring__deployboard--key.png
* see more information about this in
* https://gitlab.com/gitlab-org/gitlab-ee/uploads/5fff049fd88336d9ee0c6ef77b1ba7e3/monitoring__deployboard--key.png
*
*/
module.exports = {
export default {
props: {
/**
* Represents the status of the pod. Each state is represented with a different
* color.
......
......@@ -6,7 +6,7 @@
*/
const Vue = require('vue');
const EnvironmentItem = require('./environment_item');
const DeployBoard = require('./deploy_board_component');
const DeployBoard = require('./deploy_board_component').default;
module.exports = Vue.component('environment-table-component', {
......
......@@ -25,7 +25,7 @@
this.isAllowedToPushDropdown = false;
this.groups = [];
this.accessLevel = accessLevel;
this.accessLevelsData = accessLevelsData;
this.accessLevelsData = accessLevelsData.roles;
this.$dropdown = $dropdown;
this.$wrap = this.$dropdown.closest(`.${this.accessLevel}-container`);
this.usersPath = '/autocomplete/users.json';
......@@ -275,8 +275,7 @@
let consolidatedData = [];
const map = [];
let roles = [];
const selectedUsers = [];
const unselectedUsers = [];
const users = [];
let groups = [];
const selectedItems = this.getSelectedItems();
......@@ -319,12 +318,12 @@
if (current.type !== LEVEL_TYPES.USER) { continue; }
// Collect selected users
selectedUsers.push({
users.push({
id: current.user_id,
name: current.name,
username: current.username,
avatar_url: current.avatar_url,
type: LEVEL_TYPES.USER
type: LEVEL_TYPES.USER,
});
// Save identifiers for easy-checking more later
......@@ -339,32 +338,24 @@
// Add is it has not been added
if (map.indexOf(LEVEL_TYPES.USER + u.id) === -1) {
u.type = LEVEL_TYPES.USER;
unselectedUsers.push(u);
users.push(u);
}
}
if (groups.length) {
consolidatedData = consolidatedData.concat(groups);
if (roles.length) {
consolidatedData = consolidatedData.concat([{ header: 'Roles', }], roles);
}
if (roles.length) {
if (groups.length) {
if (groups.length) {
if (roles.length) {
consolidatedData = consolidatedData.concat(['divider']);
}
consolidatedData = consolidatedData.concat(roles);
consolidatedData = consolidatedData.concat([{ header: 'Groups', }], groups);
}
if (selectedUsers.length) {
consolidatedData = consolidatedData.concat(['divider'], selectedUsers);
}
if (unselectedUsers.length) {
if (!selectedUsers.length) {
consolidatedData = consolidatedData.concat(['divider']);
}
consolidatedData = consolidatedData.concat(unselectedUsers);
if (users.length) {
consolidatedData = consolidatedData.concat(['divider'], [{ header: 'Users', }], users);
}
return consolidatedData;
......@@ -434,9 +425,8 @@
groupRowHtml(group, isActive) {
const avatarHtml = group.avatar_url ? `<img src='${group.avatar_url}' class='avatar avatar-inline' width='30'>` : '';
const nameHtml = `<strong class='dropdown-menu-group-full-name'>${group.name}</strong>`;
const groupnameHtml = `<span class='dropdown-menu-group-groupname'>${group.name}</span>`;
return `<li><a href='#' class='${isActive ? 'is-active' : ''}'>${avatarHtml} ${nameHtml} ${groupnameHtml}</a></li>`;
return `<li><a href='#' class='${isActive ? 'is-active' : ''}'>${avatarHtml} ${groupnameHtml}</a></li>`;
}
roleRowHtml(role, isActive) {
......
......@@ -200,6 +200,25 @@
&.deploy-board-error-message {
justify-content: center;
}
.deploy-board-empty-state-svg {
order: 1;
width: 90px;
margin: auto 0 auto 20px;
}
.deploy-board-empty-state-text {
order: 2;
flex-wrap: wrap;
margin: auto auto 15px 0;
.title {
order: 1;
display: flex;
font-size: 17px;
line-height: 40px;
}
}
}
.deploy-board-instance {
......
......@@ -69,8 +69,14 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
def access_levels_options
{
push_access_levels: ProtectedBranch::PushAccessLevel.human_access_levels.map { |id, text| { id: id, text: text, before_divider: true } },
merge_access_levels: ProtectedBranch::MergeAccessLevel.human_access_levels.map { |id, text| { id: id, text: text, before_divider: true } }
push_access_levels: {
roles: ProtectedBranch::PushAccessLevel.human_access_levels.map { |id, text| { id: id, text: text, before_divider: true } },
},
merge_access_levels: {
roles: ProtectedBranch::MergeAccessLevel.human_access_levels.map { |id, text| { id: id, text: text, before_divider: true } },
},
selected_merge_access_levels: @protected_branch.merge_access_levels.map { |access_level| access_level.user_id || access_level.access_level },
selected_push_access_levels: @protected_branch.push_access_levels.map { |access_level| access_level.user_id || access_level.access_level }
}
end
......
......@@ -26,7 +26,8 @@ module MergeRequests
run_git_command(
%W(pull --rebase #{target_project.repository.path_to_repo} #{merge_request.target_branch}),
tree_path,
git_env,
git_env.merge('GIT_COMMITTER_NAME' => current_user.name,
'GIT_COMMITTER_EMAIL' => current_user.email),
'rebase branch'
)
......
<svg width="55" height="44" viewBox="0 0 55 44" xmlns="http://www.w3.org/2000/svg"><g fill="none" fill-rule="evenodd"><g transform="translate(1.488 .803)"><rect stroke="#E5E5E5" stroke-width="1.6" fill="#FFF" width="42" height="42" rx="4"/><rect stroke="#E7E7E7" stroke-width="1.6" fill="#FFF" x="6" y="12" width="7.171" height="24" rx="2"/><rect stroke="#B5A7DD" stroke-width="1.6" fill="#FFF" x="6" y="5" width="32.17" height="3.5" rx="1.75"/><rect stroke="#FDE5D8" stroke-width="1.6" fill="#FFF" x="17" y="12" width="21.17" height="24" rx="2"/><rect fill="#E52C5A" x="19.74" y="14.197" width="7.171" height="2.408" rx="1.204"/><rect fill="#E5E5E5" x="28.35" y="18.272" width="7.171" height="2.408" rx="1.204"/><rect fill="#E5E5E5" x="19.74" y="26.697" width="15.943" height="2.408" rx="1.204"/><rect fill="#E5E5E5" x="19.74" y="30.697" width="15.943" height="2.408" rx="1.204"/><rect fill="#E52C5A" x="21.911" y="21.272" width="4.78" height="2.408" rx="1.204"/><rect fill="#FC8A51" x="28.472" y="22.429" width="7.171" height="2.408" rx="1.204"/><rect fill="#FDE5D8" x="26.691" y="8.429" width="2.39" height="2.408" rx="1.195"/><rect fill="#FF8340" x="8.512" y="14.85" width="2.39" height="2.408" rx="1.195"/><rect fill="#E52C5A" x="8.512" y="19.197" width="2.39" height="2.408" rx="1.195"/><rect fill="#FF8340" x="8.512" y="31.197" width="2.39" height="2.408" rx="1.195"/><rect fill="#E7E7E7" x="8.512" y="27.197" width="2.39" height="2.408" rx="1.195"/><rect fill="#B5A7DD" x="8.512" y="23.197" width="2.39" height="2.408" rx="1.195"/></g><g transform="rotate(-45 33.371 -12.99)"><ellipse stroke="#6B4FBB" stroke-width="3.2" fill-opacity=".1" fill="#FFF" cx="11.951" cy="12.041" rx="11.951" ry="12.041"/><path d="M5.536 22.29c5.716 3.3 13.046 1.307 16.37-4.452 3.326-5.759 1.387-13.103-4.329-16.403" stroke="#6B4FBB" stroke-width="3.2" fill-opacity=".3" fill="#FFF"/><rect fill="#6B4FBB" x="9.561" y="23.279" width="4.78" height="13.646" rx="2.39"/></g></g></svg>
---
title: "Update project list API returns with approvals_before_merge attribute"
merge_request: 1245
author: Geoff Webster
\ No newline at end of file
---
title: Parallelise the gitlab:elastic:index_database Rake task
merge_request: 1361
author:
---
title: Rebase - fix commiter email & name
merge_request:
author:
---
title: Added headers to protected branches access dropdowns
merge_request:
author:
---
title: Remove "subscribed" field from API responses returning list of issues or merge
requests
merge_request: 9661
author:
......@@ -135,6 +135,7 @@ var config = {
alias: {
'~': path.join(ROOT_PATH, 'app/assets/javascripts'),
'emoji-aliases$': path.join(ROOT_PATH, 'fixtures/emojis/aliases.json'),
'empty_states': path.join(ROOT_PATH, 'app/views/shared/empty_states'),
'icons': path.join(ROOT_PATH, 'app/views/shared/icons'),
'vendor': path.join(ROOT_PATH, 'vendor/assets/javascripts'),
'vue$': 'vue/dist/vue.common.js',
......@@ -184,4 +185,4 @@ if (WEBPACK_REPORT) {
);
}
module.exports = config;
module.exports = config;
\ No newline at end of file
......@@ -84,7 +84,6 @@ Example response:
"created_at" : "2016-01-04T15:31:51.081Z",
"iid" : 6,
"labels" : [],
"subscribed" : false,
"user_notes_count": 1,
"due_date": "2016-07-22",
"web_url": "http://example.com/example/example/issues/6",
......@@ -168,7 +167,6 @@ Example response:
"title" : "Ut commodi ullam eos dolores perferendis nihil sunt.",
"updated_at" : "2016-01-04T15:31:46.176Z",
"created_at" : "2016-01-04T15:31:46.176Z",
"subscribed" : false,
"user_notes_count": 1,
"due_date": null,
"web_url": "http://example.com/example/example/issues/1",
......@@ -252,7 +250,6 @@ Example response:
"title" : "Ut commodi ullam eos dolores perferendis nihil sunt.",
"updated_at" : "2016-01-04T15:31:46.176Z",
"created_at" : "2016-01-04T15:31:46.176Z",
"subscribed" : false,
"user_notes_count": 1,
"due_date": "2016-07-22",
"web_url": "http://example.com/example/example/issues/1",
......
......@@ -67,7 +67,6 @@ Parameters:
},
"merge_when_pipeline_succeeds": true,
"merge_status": "can_be_merged",
"subscribed" : false,
"sha": "8888888888888888888888888888888888888888",
"merge_commit_sha": null,
"user_notes_count": 1,
......
......@@ -90,7 +90,8 @@ Parameters:
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
"only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false
"request_access_enabled": false,
"approvals_before_merge": 0
},
{
"id": 6,
......@@ -150,7 +151,8 @@ Parameters:
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
"only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false
"request_access_enabled": false,
"approvals_before_merge": 0
}
]
```
......@@ -242,7 +244,8 @@ Parameters:
"repository_storage": "default",
"only_allow_merge_if_pipeline_succeeds": false,
"only_allow_merge_if_all_discussions_are_resolved": false,
"request_access_enabled": false
"request_access_enabled": false,
"approvals_before_merge": 0
}
```
......
......@@ -52,6 +52,10 @@ changes are in V4:
- PUT `projects/:id`
- Renamed `branch_name` to `branch` on DELETE `id/repository/branches/:branch` response [!8936](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8936)
- Remove `public` param from create and edit actions of projects [!8736](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/8736)
- Remove `subscribed` field from responses returning list of issues or merge
requests. Fetch individual issues or merge requests to obtain the value
of `subscribed`
[!9661](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9661)
- Use `visibility` as string parameter everywhere [!9337](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9337)
- Notes do not return deprecated field `upvote` and `downvote` [!9384](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9384)
- Return HTTP status code `400` for all validation errors when creating or updating a member instead of sometimes `422` error. [!9523](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9523)
......@@ -64,4 +68,4 @@ changes are in V4:
- Remove the ProjectGitHook API. Use the ProjectPushRule API instead [!1301](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1301)
- Removed `repository_storage` from `PUT /application/settings` and `GET /application/settings` (use `repository_storages` instead) [!1307](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1307)
- Removed `elasticsearch_host` and `elasticsearch_port` from `PUT /application/settings` (use `elasticsearch_url` instead) [!1305](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1305)
- Removed `elasticsearch_host` and `elasticsearch_port` from `PUT /application/settings` (use `elasticsearch_url` instead) [!1305](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/1305)
......@@ -21,6 +21,7 @@ module API
mount ::API::V3::MergeRequestDiffs
mount ::API::V3::MergeRequests
mount ::API::V3::Notes
mount ::API::V3::Pipelines
mount ::API::V3::ProjectGitHook
mount ::API::V3::ProjectPushRule
mount ::API::V3::Pipelines
......
......@@ -275,14 +275,11 @@ module API
expose :start_date
end
class Issue < ProjectEntity
class IssueBasic < ProjectEntity
expose :label_names, as: :labels
expose :milestone, using: Entities::Milestone
expose :assignee, :author, using: Entities::UserBasic
expose :subscribed do |issue, options|
issue.subscribed?(options[:current_user], options[:project] || issue.project)
end
expose :user_notes_count
expose :upvotes, :downvotes
expose :due_date
......@@ -294,6 +291,12 @@ module API
end
end
class Issue < IssueBasic
expose :subscribed do |issue, options|
issue.subscribed?(options[:current_user], options[:project] || issue.project)
end
end
class IssuableTimeStats < Grape::Entity
expose :time_estimate
expose :total_time_spent
......@@ -306,7 +309,7 @@ module API
expose :id
end
class MergeRequest < ProjectEntity
class MergeRequestBasic < ProjectEntity
expose :target_branch, :source_branch
expose :upvotes, :downvotes
expose :author, :assignee, using: Entities::UserBasic
......@@ -318,11 +321,6 @@ module API
expose :merge_status
expose :diff_head_sha, as: :sha
expose :merge_commit_sha
expose :subscribed do |merge_request, options|
merge_request.subscribed?(options[:current_user], options[:project])
end
expose :user_notes_count
expose :approvals_before_merge
expose :should_remove_source_branch?, as: :should_remove_source_branch
......@@ -334,6 +332,12 @@ module API
end
end
class MergeRequest < MergeRequestBasic
expose :subscribed do |merge_request, options|
merge_request.subscribed?(options[:current_user], options[:project])
end
end
class MergeRequestChanges < MergeRequest
expose :diffs, as: :changes, using: Entities::RepoDiff do |compare, _|
compare.raw_diffs(all_diffs: true).to_a
......
......@@ -399,14 +399,6 @@ module API
header(*Gitlab::Workhorse.send_git_archive(repository, ref: ref, format: format))
end
def issue_entity(project)
if project.has_external_issue_tracker?
Entities::ExternalIssue
else
Entities::Issue
end
end
# The Grape Error Middleware only has access to env but no params. We workaround this by
# defining a method that returns the right value.
def define_params_for_grape_middleware
......
......@@ -43,7 +43,7 @@ module API
resource :issues do
desc "Get currently authenticated user's issues" do
success Entities::Issue
success Entities::IssueBasic
end
params do
optional :state, type: String, values: %w[opened closed all], default: 'all',
......@@ -53,7 +53,7 @@ module API
get do
issues = find_issues(scope: 'authored')
present paginate(issues), with: Entities::Issue, current_user: current_user
present paginate(issues), with: Entities::IssueBasic, current_user: current_user
end
end
......@@ -62,7 +62,7 @@ module API
end
resource :groups do
desc 'Get a list of group issues' do
success Entities::Issue
success Entities::IssueBasic
end
params do
optional :state, type: String, values: %w[opened closed all], default: 'opened',
......@@ -74,7 +74,7 @@ module API
issues = find_issues(group_id: group.id, state: params[:state] || 'opened')
present paginate(issues), with: Entities::Issue, current_user: current_user
present paginate(issues), with: Entities::IssueBasic, current_user: current_user
end
end
......@@ -85,7 +85,7 @@ module API
include TimeTrackingEndpoints
desc 'Get a list of project issues' do
success Entities::Issue
success Entities::IssueBasic
end
params do
optional :state, type: String, values: %w[opened closed all], default: 'all',
......@@ -97,7 +97,7 @@ module API
issues = find_issues(project_id: project.id)
present paginate(issues), with: Entities::Issue, current_user: current_user, project: user_project
present paginate(issues), with: Entities::IssueBasic, current_user: current_user, project: user_project
end
desc 'Get a single project issue' do
......
......@@ -25,6 +25,14 @@ module API
render_api_error!(errors, 400)
end
def issue_entity(project)
if project.has_external_issue_tracker?
Entities::ExternalIssue
else
Entities::IssueBasic
end
end
params :optional_params do
optional :description, type: String, desc: 'The description of the merge request'
optional :assignee_id, type: Integer, desc: 'The ID of a user to assign the merge request'
......@@ -37,7 +45,7 @@ module API
end
desc 'List merge requests' do
success Entities::MergeRequest
success Entities::MergeRequestBasic
end
params do
optional :state, type: String, values: %w[opened closed merged all], default: 'all',
......@@ -64,7 +72,7 @@ module API
end
merge_requests = merge_requests.reorder(params[:order_by] => params[:sort])
present paginate(merge_requests), with: Entities::MergeRequest, current_user: current_user, project: user_project
present paginate(merge_requests), with: Entities::MergeRequestBasic, current_user: current_user, project: user_project
end
desc 'Create a merge request' do
......
......@@ -103,7 +103,7 @@ module API
end
desc 'Get all issues for a single project milestone' do
success Entities::Issue
success Entities::IssueBasic
end
params do
requires :milestone_id, type: Integer, desc: 'The ID of a project milestone'
......@@ -120,12 +120,12 @@ module API
}
issues = IssuesFinder.new(current_user, finder_params).execute
present paginate(issues), with: Entities::Issue, current_user: current_user, project: user_project
present paginate(issues), with: Entities::IssueBasic, current_user: current_user, project: user_project
end
desc 'Get all merge requests for a single project milestone' do
detail 'This feature was introduced in GitLab 9.'
success Entities::MergeRequest
success Entities::MergeRequestBasic
end
params do
requires :milestone_id, type: Integer, desc: 'The ID of a project milestone'
......@@ -142,7 +142,10 @@ module API
}
merge_requests = MergeRequestsFinder.new(current_user, finder_params).execute
present paginate(merge_requests), with: Entities::MergeRequest, current_user: current_user, project: user_project
present paginate(merge_requests),
with: Entities::MergeRequestBasic,
current_user: current_user,
project: user_project
end
end
end
......
......@@ -28,6 +28,14 @@ module API
render_api_error!(errors, 400)
end
def issue_entity(project)
if project.has_external_issue_tracker?
::API::Entities::ExternalIssue
else
::API::Entities::Issue
end
end
params :optional_params do
optional :description, type: String, desc: 'The description of the merge request'
optional :assignee_id, type: Integer, desc: 'The ID of a user to assign the merge request'
......
......@@ -37,6 +37,27 @@ module API
present paginate(milestones), with: ::API::Entities::Milestone
end
desc 'Get all issues for a single project milestone' do
success ::API::Entities::Issue
end
params do
requires :milestone_id, type: Integer, desc: 'The ID of a project milestone'
use :pagination
end
get ':id/milestones/:milestone_id/issues' do
authorize! :read_milestone, user_project
milestone = user_project.milestones.find(params[:milestone_id])
finder_params = {
project_id: user_project.id,
milestone_title: milestone.title
}
issues = IssuesFinder.new(current_user, finder_params).execute
present paginate(issues), with: ::API::Entities::Issue, current_user: current_user, project: user_project
end
end
end
end
......
......@@ -58,12 +58,23 @@ namespace :gitlab do
end
end
desc "GitLab | Elasticsearch | Index all database objects"
task index_database: :environment do
[Project, Issue, MergeRequest, Snippet, Note, Milestone].each do |klass|
print "Indexing #{klass} records... "
case klass.to_s
INDEXABLE_CLASSES = {
"Project" => "index_projects",
"Issue" => "index_issues",
"MergeRequest" => "index_merge_requests",
"Snippet" => "index_snippets",
"Note" => "index_notes",
"Milestone" => "index_milestones",
}.freeze
INDEXABLE_CLASSES.each do |klass_name, task_name|
task task_name => :environment do
logger = Logger.new(STDOUT)
logger.info("Indexing #{klass_name.pluralize}...")
klass = Kernel.const_get(klass_name)
case klass_name
when 'Note'
Note.searchable.import_with_parent
when 'Project', 'Snippet'
......@@ -72,10 +83,13 @@ namespace :gitlab do
klass.import_with_parent
end
puts "done".color(:green)
logger.info("Indexing #{klass_name.pluralize}... " + "done".color(:green))
end
end
desc "GitLab | Elasticsearch | Index all database objects"
multitask index_database: INDEXABLE_CLASSES.values
desc "GitLab | Elasticsearch | Create empty index"
task create_empty_index: :environment do
Gitlab::Elastic::Helper.create_empty_index
......
......@@ -92,6 +92,13 @@ RSpec.shared_examples "protected branches > access control > EE" do
within(".protected-branches-list") do
find(".js-allowed-to-#{git_operation}").click
find(".dropdown-input-field").set(users.last.name) # Find a user that is not loaded
expect(page).to have_selector('.dropdown-header', count: 3)
%w{Roles Groups Users}.each_with_index do |header, index|
expect(all('.dropdown-header')[index]).to have_content(header)
end
wait_for_ajax
click_on users.last.name
find(".js-allowed-to-#{git_operation}").click # close
......
{
"type": "array",
"items": {
"type": "object",
"properties" : {
"id": { "type": "integer" },
"iid": { "type": "integer" },
"project_id": { "type": "integer" },
"title": { "type": "string" },
"description": { "type": ["string", "null"] },
"state": { "type": "string" },
"created_at": { "type": "date" },
"updated_at": { "type": "date" },
"labels": {
"type": "array",
"items": {
"type": "string"
}
},
"milestone": {
"type": "object",
"properties": {
"id": { "type": "integer" },
"iid": { "type": "integer" },
"project_id": { "type": "integer" },
"title": { "type": "string" },
"description": { "type": ["string", "null"] },
"state": { "type": "string" },
"created_at": { "type": "date" },
"updated_at": { "type": "date" },
"due_date": { "type": "date" },
"start_date": { "type": "date" }
},
"additionalProperties": false
},
"assignee": {
"type": ["object", "null"],
"properties": {
"name": { "type": "string" },
"username": { "type": "string" },
"id": { "type": "integer" },
"state": { "type": "string" },
"avatar_url": { "type": "uri" },
"web_url": { "type": "uri" }
},
"additionalProperties": false
},
"author": {
"type": "object",
"properties": {
"name": { "type": "string" },
"username": { "type": "string" },
"id": { "type": "integer" },
"state": { "type": "string" },
"avatar_url": { "type": "uri" },
"web_url": { "type": "uri" }
},
"additionalProperties": false
},
"user_notes_count": { "type": "integer" },
"upvotes": { "type": "integer" },
"downvotes": { "type": "integer" },
"due_date": { "type": ["date", "null"] },
"confidential": { "type": "boolean" },
"web_url": { "type": "uri" },
"subscribed": { "type": ["boolean"] },
"weight": { "type": ["integer", "null"] }
},
"required": [
"id", "iid", "project_id", "title", "description",
"state", "created_at", "updated_at", "labels",
"milestone", "assignee", "author", "user_notes_count",
"upvotes", "downvotes", "due_date", "confidential",
"web_url", "subscribed", "weight"
],
"additionalProperties": false
}
}
{
"type": "array",
"items": {
"type": "object",
"properties" : {
"id": { "type": "integer" },
"iid": { "type": "integer" },
"project_id": { "type": "integer" },
"title": { "type": "string" },
"description": { "type": ["string", "null"] },
"state": { "type": "string" },
"created_at": { "type": "date" },
"updated_at": { "type": "date" },
"target_branch": { "type": "string" },
"source_branch": { "type": "string" },
"upvotes": { "type": "integer" },
"downvotes": { "type": "integer" },
"author": {
"type": "object",
"properties": {
"name": { "type": "string" },
"username": { "type": "string" },
"id": { "type": "integer" },
"state": { "type": "string" },
"avatar_url": { "type": "uri" },
"web_url": { "type": "uri" }
},
"additionalProperties": false
},
"assignee": {
"type": "object",
"properties": {
"name": { "type": "string" },
"username": { "type": "string" },
"id": { "type": "integer" },
"state": { "type": "string" },
"avatar_url": { "type": "uri" },
"web_url": { "type": "uri" }
},
"additionalProperties": false
},
"source_project_id": { "type": "integer" },
"target_project_id": { "type": "integer" },
"labels": {
"type": "array",
"items": {
"type": "string"
}
},
"work_in_progress": { "type": "boolean" },
"milestone": {
"type": ["object", "null"],
"properties": {
"id": { "type": "integer" },
"iid": { "type": "integer" },
"project_id": { "type": "integer" },
"title": { "type": "string" },
"description": { "type": ["string", "null"] },
"state": { "type": "string" },
"created_at": { "type": "date" },
"updated_at": { "type": "date" },
"due_date": { "type": "date" },
"start_date": { "type": "date" }
},
"additionalProperties": false
},
"merge_when_build_succeeds": { "type": "boolean" },
"merge_status": { "type": "string" },
"sha": { "type": "string" },
"merge_commit_sha": { "type": ["string", "null"] },
"user_notes_count": { "type": "integer" },
"should_remove_source_branch": { "type": ["boolean", "null"] },
"force_remove_source_branch": { "type": ["boolean", "null"] },
"web_url": { "type": "uri" },
"subscribed": { "type": ["boolean"] },
"approvals_before_merge": { "type": ["integer", "null"] },
"squash": { "type": "boolean" }
},
"required": [
"id", "iid", "project_id", "title", "description",
"state", "created_at", "updated_at", "target_branch",
"source_branch", "upvotes", "downvotes", "author",
"assignee", "source_project_id", "target_project_id",
"labels", "work_in_progress", "milestone", "merge_when_build_succeeds",
"merge_status", "sha", "merge_commit_sha", "user_notes_count",
"should_remove_source_branch", "force_remove_source_branch",
"web_url", "subscribed", "approvals_before_merge", "squash"
],
"additionalProperties": false
}
}
{
"type": "array",
"items": {
"type": "object",
"properties" : {
"id": { "type": "integer" },
"iid": { "type": "integer" },
"project_id": { "type": "integer" },
"title": { "type": "string" },
"description": { "type": ["string", "null"] },
"state": { "type": "string" },
"created_at": { "type": "date" },
"updated_at": { "type": "date" },
"labels": {
"type": "array",
"items": {
"type": "string"
}
},
"milestone": {
"type": "object",
"properties": {
"id": { "type": "integer" },
"iid": { "type": "integer" },
"project_id": { "type": "integer" },
"title": { "type": "string" },
"description": { "type": ["string", "null"] },
"state": { "type": "string" },
"created_at": { "type": "date" },
"updated_at": { "type": "date" },
"due_date": { "type": "date" },
"start_date": { "type": "date" }
},
"additionalProperties": false
},
"assignee": {
"type": ["object", "null"],
"properties": {
"name": { "type": "string" },
"username": { "type": "string" },
"id": { "type": "integer" },
"state": { "type": "string" },
"avatar_url": { "type": "uri" },
"web_url": { "type": "uri" }
},
"additionalProperties": false
},
"author": {
"type": "object",
"properties": {
"name": { "type": "string" },
"username": { "type": "string" },
"id": { "type": "integer" },
"state": { "type": "string" },
"avatar_url": { "type": "uri" },
"web_url": { "type": "uri" }
},
"additionalProperties": false
},
"user_notes_count": { "type": "integer" },
"upvotes": { "type": "integer" },
"downvotes": { "type": "integer" },
"due_date": { "type": ["date", "null"] },
"confidential": { "type": "boolean" },
"web_url": { "type": "uri" },
"weight": { "type": ["integer", "null"] }
},
"required": [
"id", "iid", "project_id", "title", "description",
"state", "created_at", "updated_at", "labels",
"milestone", "assignee", "author", "user_notes_count",
"upvotes", "downvotes", "due_date", "confidential",
"web_url", "weight"
],
"additionalProperties": false
}
}
{
"type": "array",
"items": {
"type": "object",
"properties" : {
"id": { "type": "integer" },
"iid": { "type": "integer" },
"project_id": { "type": "integer" },
"title": { "type": "string" },
"description": { "type": ["string", "null"] },
"state": { "type": "string" },
"created_at": { "type": "date" },
"updated_at": { "type": "date" },
"target_branch": { "type": "string" },
"source_branch": { "type": "string" },
"upvotes": { "type": "integer" },
"downvotes": { "type": "integer" },
"author": {
"type": "object",
"properties": {
"name": { "type": "string" },
"username": { "type": "string" },
"id": { "type": "integer" },
"state": { "type": "string" },
"avatar_url": { "type": "uri" },
"web_url": { "type": "uri" }
},
"additionalProperties": false
},
"assignee": {
"type": "object",
"properties": {
"name": { "type": "string" },
"username": { "type": "string" },
"id": { "type": "integer" },
"state": { "type": "string" },
"avatar_url": { "type": "uri" },
"web_url": { "type": "uri" }
},
"additionalProperties": false
},
"source_project_id": { "type": "integer" },
"target_project_id": { "type": "integer" },
"labels": {
"type": "array",
"items": {
"type": "string"
}
},
"work_in_progress": { "type": "boolean" },
"milestone": {
"type": ["object", "null"],
"properties": {
"id": { "type": "integer" },
"iid": { "type": "integer" },
"project_id": { "type": "integer" },
"title": { "type": "string" },
"description": { "type": ["string", "null"] },
"state": { "type": "string" },
"created_at": { "type": "date" },
"updated_at": { "type": "date" },
"due_date": { "type": "date" },
"start_date": { "type": "date" }
},
"additionalProperties": false
},
"merge_when_pipeline_succeeds": { "type": "boolean" },
"merge_status": { "type": "string" },
"sha": { "type": "string" },
"merge_commit_sha": { "type": ["string", "null"] },
"user_notes_count": { "type": "integer" },
"should_remove_source_branch": { "type": ["boolean", "null"] },
"force_remove_source_branch": { "type": ["boolean", "null"] },
"web_url": { "type": "uri" },
"approvals_before_merge": { "type": ["integer", "null"] },
"squash": { "type": "boolean" }
},
"required": [
"id", "iid", "project_id", "title", "description",
"state", "created_at", "updated_at", "target_branch",
"source_branch", "upvotes", "downvotes", "author",
"assignee", "source_project_id", "target_project_id",
"labels", "work_in_progress", "milestone", "merge_when_pipeline_succeeds",
"merge_status", "sha", "merge_commit_sha", "user_notes_count",
"should_remove_source_branch", "force_remove_source_branch",
"web_url", "approvals_before_merge", "squash"
],
"additionalProperties": false
}
}
const Vue = require('vue');
const DeployBoard = require('~/environments/components/deploy_board_component');
const Service = require('~/environments/services/environments_service');
const { deployBoardMockData } = require('./mock_data');
import Vue from 'vue';
import DeployBoard from '~/environments/components/deploy_board_component';
import Service from '~/environments/services/environments_service';
const { deployBoardMockData, invalidDeployBoardMockData } = require('./mock_data');
describe('Deploy Board', () => {
let DeployBoardComponent;
......@@ -77,6 +78,46 @@ describe('Deploy Board', () => {
});
});
describe('successfull request without valid data', () => {
const deployBoardInterceptorInvalidData = (request, next) => {
next(request.respondWith(JSON.stringify(invalidDeployBoardMockData), {
status: 200,
}));
};
let component;
beforeEach(() => {
Vue.http.interceptors.push(deployBoardInterceptorInvalidData);
this.service = new Service('environments');
component = new DeployBoardComponent({
propsData: {
store: {},
service: new Service('environments'),
deployBoardData: invalidDeployBoardMockData,
environmentID: 1,
endpoint: 'endpoint',
},
}).$mount();
});
afterEach(() => {
Vue.http.interceptors = _.without(
Vue.http.interceptors, deployBoardInterceptorInvalidData,
);
});
it('should render the empty state', (done) => {
setTimeout(() => {
expect(component.$el.querySelector('.deploy-board-empty-state-svg svg')).toBeDefined();
expect(component.$el.querySelector('.deploy-board-empty-state-text .title').textContent).toContain('Kubernetes deployment not found');
done();
}, 0);
});
});
describe('unsuccessfull request', () => {
const deployBoardErrorInterceptor = (request, next) => {
next(request.respondWith(JSON.stringify({}), {
......@@ -108,7 +149,7 @@ describe('Deploy Board', () => {
it('should render empty state', (done) => {
setTimeout(() => {
expect(component.$el.children.length).toEqual(0);
expect(component.$el.children.length).toEqual(1);
done();
}, 0);
});
......
const Vue = require('vue');
const DeployBoardInstance = require('~/environments/components/deploy_board_instance_component');
import Vue from 'vue';
import DeployBoardInstance from '~/environments/components/deploy_board_instance_component';
describe('Deploy Board Instance', () => {
let DeployBoardInstanceComponent;
......
......@@ -120,7 +120,15 @@ const deployBoardMockData = {
abort_url: 'url',
rollback_url: 'url',
completion: 100,
is_completed: true,
valid: true,
};
const invalidDeployBoardMockData = {
instances: [],
abort_url: 'url',
rollback_url: 'url',
completion: 100,
valid: false,
};
module.exports = {
......@@ -128,4 +136,5 @@ module.exports = {
environment,
serverData,
deployBoardMockData,
invalidDeployBoardMockData,
};
......@@ -270,6 +270,13 @@ describe API::Issues, api: true do
expect(json_response).to be_an Array
expect(response_dates).to eq(response_dates.sort)
end
it 'matches V4 response schema' do
get api('/issues', user)
expect(response).to have_http_status(200)
expect(response).to match_response_schema('public_api/v4/issues')
end
end
end
......
......@@ -94,6 +94,13 @@ describe API::MergeRequests, api: true do
expect(json_response.first['id']).to eq merge_request_closed.id
end
it 'matches V4 response schema' do
get api("/projects/#{project.id}/merge_requests", user)
expect(response).to have_http_status(200)
expect(response).to match_response_schema('public_api/v4/merge_requests')
end
context "with ordering" do
before do
@mr_later = mr_with_later_created_and_updated_at_time
......
......@@ -227,6 +227,13 @@ describe API::Milestones, api: true do
expect(json_response.first['milestone']['title']).to eq(milestone.title)
end
it 'matches V4 response schema for a list of issues' do
get api("/projects/#{project.id}/milestones/#{milestone.id}/issues", user)
expect(response).to have_http_status(200)
expect(response).to match_response_schema('public_api/v4/issues')
end
it 'returns a 401 error if user not authenticated' do
get api("/projects/#{project.id}/milestones/#{milestone.id}/issues")
......
......@@ -740,7 +740,7 @@ describe API::Users, api: true do
get api("/user", user)
expect(response).to have_http_status(200)
expect(response).to match_response_schema('user/public')
expect(response).to match_response_schema('public_api/v4/user/public')
expect(json_response['id']).to eq(user.id)
end
end
......@@ -759,7 +759,7 @@ describe API::Users, api: true do
get api("/user?private_token=#{admin_personal_access_token}")
expect(response).to have_http_status(200)
expect(response).to match_response_schema('user/public')
expect(response).to match_response_schema('public_api/v4/user/public')
expect(json_response['id']).to eq(admin.id)
end
end
......@@ -769,7 +769,7 @@ describe API::Users, api: true do
get api("/user?private_token=#{admin.private_token}&sudo=#{user.id}")
expect(response).to have_http_status(200)
expect(response).to match_response_schema('user/login')
expect(response).to match_response_schema('public_api/v4/user/login')
expect(json_response['id']).to eq(user.id)
end
......@@ -777,7 +777,7 @@ describe API::Users, api: true do
get api("/user?private_token=#{admin.private_token}")
expect(response).to have_http_status(200)
expect(response).to match_response_schema('user/public')
expect(response).to match_response_schema('public_api/v4/user/public')
expect(json_response['id']).to eq(admin.id)
end
end
......
......@@ -232,6 +232,13 @@ describe API::V3::Issues, api: true do
expect(json_response).to be_an Array
expect(response_dates).to eq(response_dates.sort)
end
it 'matches V3 response schema' do
get v3_api('/issues', user)
expect(response).to have_http_status(200)
expect(response).to match_response_schema('public_api/v3/issues')
end
end
end
......
......@@ -74,6 +74,13 @@ describe API::MergeRequests, api: true do
expect(json_response.first['title']).to eq(merge_request_merged.title)
end
it 'matches V3 response schema' do
get v3_api("/projects/#{project.id}/merge_requests", user)
expect(response).to have_http_status(200)
expect(response).to match_response_schema('public_api/v3/merge_requests')
end
context "with ordering" do
before do
@mr_later = mr_with_later_created_and_updated_at_time
......
......@@ -181,6 +181,13 @@ describe API::V3::Milestones, api: true do
expect(json_response.first['milestone']['title']).to eq(milestone.title)
end
it 'matches V3 response schema for a list of issues' do
get v3_api("/projects/#{project.id}/milestones/#{milestone.id}/issues", user)
expect(response).to have_http_status(200)
expect(response).to match_response_schema('public_api/v3/issues')
end
it 'returns a 401 error if user not authenticated' do
get v3_api("/projects/#{project.id}/milestones/#{milestone.id}/issues")
......
......@@ -31,6 +31,15 @@ describe MergeRequests::RebaseService do
head_sha = merge_request.source_project.repository.commit(merge_request.source_branch).sha
expect(merge_request.reload.rebase_commit_sha).to eq(head_sha)
end
it 'logs correct author and commiter' do
head_commit = merge_request.source_project.repository.commit(merge_request.source_branch)
expect(head_commit.author_email).to eq('dmitriy.zaporozhets@gmail.com')
expect(head_commit.author_name).to eq('Dmitriy Zaporozhets')
expect(head_commit.committer_email).to eq(user.email)
expect(head_commit.committer_name).to eq(user.name)
end
end
end
end
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