Commit 98d5506a authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-04-23

# Conflicts:
#	app/assets/javascripts/vue_shared/components/ci_icon.vue
#	app/finders/users_finder.rb

[ci skip]
parents 1c7008fb d7f68bcf
......@@ -21,7 +21,10 @@ import Icon from '../../vue_shared/components/icon.vue';
* - Jobs table
* - Jobs show view header
* - Jobs show view sidebar
<<<<<<< HEAD
* - Linked pipelines
=======
>>>>>>> upstream/master
*/
export default {
components: {
......
<script>
import commitIconSvg from 'icons/_icon_commit.svg';
import userAvatarLink from './user_avatar/user_avatar_link.vue';
import tooltip from '../directives/tooltip';
import icon from '../../vue_shared/components/icon.vue';
import UserAvatarLink from './user_avatar/user_avatar_link.vue';
import tooltip from '../directives/tooltip';
import Icon from '../../vue_shared/components/icon.vue';
export default {
directives: {
tooltip,
export default {
directives: {
tooltip,
},
components: {
UserAvatarLink,
Icon,
},
props: {
/**
* Indicates the existance of a tag.
* Used to render the correct icon, if true will render `fa-tag` icon,
* if false will render a svg sprite fork icon
*/
tag: {
type: Boolean,
required: false,
default: false,
},
components: {
userAvatarLink,
icon,
/**
* If provided is used to render the branch name and url.
* Should contain the following properties:
* name
* ref_url
*/
commitRef: {
type: Object,
required: false,
default: () => ({}),
},
/**
* Used to link to the commit sha.
*/
commitUrl: {
type: String,
required: false,
default: '',
},
props: {
/**
* Indicates the existance of a tag.
* Used to render the correct icon, if true will render `fa-tag` icon,
* if false will render a svg sprite fork icon
*/
tag: {
type: Boolean,
required: false,
default: false,
},
/**
* If provided is used to render the branch name and url.
* Should contain the following properties:
* name
* ref_url
*/
commitRef: {
type: Object,
required: false,
default: () => ({}),
},
/**
* Used to link to the commit sha.
*/
commitUrl: {
type: String,
required: false,
default: '',
},
/**
* Used to show the commit short sha that links to the commit url.
*/
shortSha: {
type: String,
required: false,
default: '',
},
/**
* If provided shows the commit tile.
*/
title: {
type: String,
required: false,
default: '',
},
/**
* If provided renders information about the author of the commit.
* When provided should include:
* `avatar_url` to render the avatar icon
* `web_url` to link to user profile
* `username` to render alt and title tags
*/
author: {
type: Object,
required: false,
default: () => ({}),
},
showBranch: {
type: Boolean,
required: false,
default: true,
},
/**
* Used to show the commit short sha that links to the commit url.
*/
shortSha: {
type: String,
required: false,
default: '',
},
/**
* If provided shows the commit tile.
*/
title: {
type: String,
required: false,
default: '',
},
/**
* If provided renders information about the author of the commit.
* When provided should include:
* `avatar_url` to render the avatar icon
* `web_url` to link to user profile
* `username` to render alt and title tags
*/
author: {
type: Object,
required: false,
default: () => ({}),
},
showBranch: {
type: Boolean,
required: false,
default: true,
},
computed: {
/**
* Used to verify if all the properties needed to render the commit
* ref section were provided.
*
* @returns {Boolean}
*/
hasCommitRef() {
return this.commitRef && this.commitRef.name && this.commitRef.ref_url;
},
/**
* Used to verify if all the properties needed to render the commit
* author section were provided.
*
* @returns {Boolean}
*/
hasAuthor() {
return this.author &&
this.author.avatar_url &&
this.author.path &&
this.author.username;
},
/**
* If information about the author is provided will return a string
* to be rendered as the alt attribute of the img tag.
*
* @returns {String}
*/
userImageAltDescription() {
return this.author &&
this.author.username ? `${this.author.username}'s avatar` : null;
},
},
computed: {
/**
* Used to verify if all the properties needed to render the commit
* ref section were provided.
*
* @returns {Boolean}
*/
hasCommitRef() {
return this.commitRef && this.commitRef.name && this.commitRef.ref_url;
},
created() {
this.commitIconSvg = commitIconSvg;
/**
* Used to verify if all the properties needed to render the commit
* author section were provided.
*
* @returns {Boolean}
*/
hasAuthor() {
return this.author && this.author.avatar_url && this.author.path && this.author.username;
},
};
/**
* If information about the author is provided will return a string
* to be rendered as the alt attribute of the img tag.
*
* @returns {String}
*/
userImageAltDescription() {
return this.author && this.author.username ? `${this.author.username}'s avatar` : null;
},
},
};
</script>
<template>
<div class="branch-commit">
......@@ -141,11 +133,10 @@
{{ commitRef.name }}
</a>
</template>
<div
v-html="commitIconSvg"
<icon
name="commit"
class="commit-icon js-commit-icon"
>
</div>
/>
<a
class="commit-sha"
......
<script>
import { __ } from '~/locale';
/**
* Port of detail_behavior expand button.
*
* @example
* <expand-button>
* <template slot="expanded">
* Text goes here.
* </template>
* </expand-button>
*/
export default {
name: 'ExpandButton',
data() {
return {
isCollapsed: true,
};
import { __ } from '~/locale';
/**
* Port of detail_behavior expand button.
*
* @example
* <expand-button>
* <template slot="expanded">
* Text goes here.
* </template>
* </expand-button>
*/
export default {
name: 'ExpandButton',
data() {
return {
isCollapsed: true,
};
},
computed: {
ariaLabel() {
return __('Click to expand text');
},
computed: {
ariaLabel() {
return __('Click to expand text');
},
},
methods: {
onClick() {
this.isCollapsed = !this.isCollapsed;
},
methods: {
onClick() {
this.isCollapsed = !this.isCollapsed;
},
},
};
},
};
</script>
<template>
<span>
......
<script>
import ciIconBadge from './ci_badge_link.vue';
import loadingIcon from './loading_icon.vue';
import timeagoTooltip from './time_ago_tooltip.vue';
import tooltip from '../directives/tooltip';
import userAvatarImage from './user_avatar/user_avatar_image.vue';
import CiIconBadge from './ci_badge_link.vue';
import LoadingIcon from './loading_icon.vue';
import TimeagoTooltip from './time_ago_tooltip.vue';
import tooltip from '../directives/tooltip';
import UserAvatarImage from './user_avatar/user_avatar_image.vue';
/**
* Renders header component for job and pipeline page based on UI mockups
*
* Used in:
* - job show page
* - pipeline show page
*/
export default {
components: {
ciIconBadge,
loadingIcon,
timeagoTooltip,
userAvatarImage,
/**
* Renders header component for job and pipeline page based on UI mockups
*
* Used in:
* - job show page
* - pipeline show page
*/
export default {
components: {
CiIconBadge,
LoadingIcon,
TimeagoTooltip,
UserAvatarImage,
},
directives: {
tooltip,
},
props: {
status: {
type: Object,
required: true,
},
directives: {
tooltip,
itemName: {
type: String,
required: true,
},
props: {
status: {
type: Object,
required: true,
},
itemName: {
type: String,
required: true,
},
itemId: {
type: Number,
required: true,
},
time: {
type: String,
required: true,
},
user: {
type: Object,
required: false,
default: () => ({}),
},
actions: {
type: Array,
required: false,
default: () => [],
},
hasSidebarButton: {
type: Boolean,
required: false,
default: false,
},
shouldRenderTriggeredLabel: {
type: Boolean,
required: false,
default: true,
},
itemId: {
type: Number,
required: true,
},
time: {
type: String,
required: true,
},
user: {
type: Object,
required: false,
default: () => ({}),
},
actions: {
type: Array,
required: false,
default: () => [],
},
hasSidebarButton: {
type: Boolean,
required: false,
default: false,
},
shouldRenderTriggeredLabel: {
type: Boolean,
required: false,
default: true,
},
},
computed: {
userAvatarAltText() {
return `${this.user.name}'s avatar`;
},
computed: {
userAvatarAltText() {
return `${this.user.name}'s avatar`;
},
},
methods: {
onClickAction(action) {
this.$emit('actionClicked', action);
},
methods: {
onClickAction(action) {
this.$emit('actionClicked', action);
},
};
},
};
</script>
<template>
......
<script>
/* This is a re-usable vue component for rendering a svg sprite
icon
/* This is a re-usable vue component for rendering a svg sprite
icon
Sample configuration:
Sample configuration:
<icon
name="retry"
:size="32"
css-classes="top"
/>
<icon
name="retry"
:size="32"
css-classes="top"
/>
*/
// only allow classes in images.scss e.g. s12
const validSizes = [8, 12, 16, 18, 24, 32, 48, 72];
*/
// only allow classes in images.scss e.g. s12
const validSizes = [8, 12, 16, 18, 24, 32, 48, 72];
export default {
props: {
name: {
type: String,
required: true,
},
export default {
props: {
name: {
type: String,
required: true,
},
size: {
type: Number,
required: false,
default: 16,
validator(value) {
return validSizes.includes(value);
},
size: {
type: Number,
required: false,
default: 16,
validator(value) {
return validSizes.includes(value);
},
},
cssClasses: {
type: String,
required: false,
default: '',
},
cssClasses: {
type: String,
required: false,
default: '',
},
width: {
type: Number,
required: false,
default: null,
},
width: {
type: Number,
required: false,
default: null,
},
height: {
type: Number,
required: false,
default: null,
},
height: {
type: Number,
required: false,
default: null,
},
y: {
type: Number,
required: false,
default: null,
},
y: {
type: Number,
required: false,
default: null,
},
x: {
type: Number,
required: false,
default: null,
},
x: {
type: Number,
required: false,
default: null,
},
},
computed: {
spriteHref() {
return `${gon.sprite_icons}#${this.name}`;
},
iconSizeClass() {
return this.size ? `s${this.size}` : '';
},
computed: {
spriteHref() {
return `${gon.sprite_icons}#${this.name}`;
},
iconSizeClass() {
return this.size ? `s${this.size}` : '';
},
};
},
};
</script>
<template>
......@@ -79,7 +78,8 @@
:width="width"
:height="height"
:x="x"
:y="y">
:y="y"
>
<use v-bind="{ 'xlink:href':spriteHref }" />
</svg>
</template>
<script>
import $ from 'jquery';
import { __ } from '~/locale';
import LabelsSelect from '~/labels_select';
import LoadingIcon from '../../loading_icon.vue';
......@@ -98,11 +99,18 @@ export default {
this.labelsDropdown = new LabelsSelect(this.$refs.dropdownButton, {
handleClick: this.handleClick,
});
$(this.$refs.dropdown).on('hidden.gl.dropdown', this.handleDropdownHidden);
},
methods: {
handleClick(label) {
this.$emit('onLabelClick', label);
},
handleCollapsedValueClick() {
this.$emit('toggleCollapse');
},
handleDropdownHidden() {
this.$emit('onDropdownClose');
},
},
};
</script>
......@@ -112,6 +120,7 @@ export default {
<dropdown-value-collapsed
v-if="showCreate"
:labels="context.labels"
@onValueClick="handleCollapsedValueClick"
/>
<dropdown-title
:can-edit="canEdit"
......@@ -133,7 +142,10 @@ export default {
:name="hiddenInputName"
:label="label"
/>
<div class="dropdown">
<div
class="dropdown"
ref="dropdown"
>
<dropdown-button
:ability-name="abilityName"
:field-name="hiddenInputName"
......
......@@ -26,6 +26,11 @@ export default {
return labelsString;
},
},
methods: {
handleClick() {
this.$emit('onValueClick');
},
},
};
</script>
......@@ -36,6 +41,7 @@ export default {
data-placement="left"
data-container="body"
:title="labelsList"
@click="handleClick"
>
<i
aria-hidden="true"
......
......@@ -80,12 +80,15 @@ class UsersFinder
users.external
end
<<<<<<< HEAD
def by_non_ldap(users)
return users unless params[:skip_ldap]
users.non_ldap
end
=======
>>>>>>> upstream/master
def by_2fa(users)
case params[:two_factor]
when 'enabled'
......
require "flowdock-git-hook"
# Flow dock depends on Grit to compute the number of commits between two given
# commits. To make this depend on Gitaly, a monkey patch is applied
module Flowdock
class Git
# pass down a Repository all the way down
def repo
@options[:repo]
end
def config
{}
end
def messages
Git::Builder.new(repo: repo,
ref: @ref,
before: @from,
after: @to,
commit_url: @commit_url,
branch_url: @branch_url,
diff_url: @diff_url,
repo_url: @repo_url,
repo_name: @repo_name,
permanent_refs: @permanent_refs,
tags: tags
).to_hashes
end
class Builder
def commits
@repo.commits_between(@before, @after).map do |commit|
{
url: @opts[:commit_url] ? @opts[:commit_url] % [commit.sha] : nil,
id: commit.sha,
message: commit.message,
author: {
name: commit.author_name,
email: commit.author_email
}
}
end
end
end
end
end
class FlowdockService < Service
prop_accessor :token
validates :token, presence: true, if: :activated?
......@@ -34,7 +80,7 @@ class FlowdockService < Service
data[:before],
data[:after],
token: token,
repo: project.repository.path_to_repo,
repo: project.repository,
repo_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}",
commit_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/commit/%s",
diff_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/compare/%s...%s"
......
......@@ -260,7 +260,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
if current_user && can?(current_user, :admin_pipeline, project) && repository.gitlab_ci_yml.blank? && !show_auto_devops_callout
OpenStruct.new(enabled: auto_devops_enabled?,
label: auto_devops_enabled? ? _('Auto DevOps enabled') : _('Enable Auto DevOps'),
link: project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings'))
link: project_settings_ci_cd_path(project, anchor: 'autodevops-settings'))
elsif auto_devops_enabled?
OpenStruct.new(enabled: true,
label: _('Auto DevOps enabled'),
......
......@@ -22,7 +22,7 @@
%hr
%p
- link_to_auto_devops_settings = link_to(s_('AutoDevOps|enable Auto DevOps (Beta)'), project_settings_ci_cd_path(@project, anchor: 'js-general-pipeline-settings'))
- link_to_auto_devops_settings = link_to(s_('AutoDevOps|enable Auto DevOps (Beta)'), project_settings_ci_cd_path(@project, anchor: 'autodevops-settings'))
- link_to_add_kubernetes_cluster = link_to(s_('AutoDevOps|add a Kubernetes cluster'), new_project_cluster_path(@project))
= s_('AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}.').html_safe % { link_to_auto_devops_settings: link_to_auto_devops_settings, link_to_add_kubernetes_cluster: link_to_add_kubernetes_cluster }
......
.row.prepend-top-default
.col-lg-12
= form_for @project, url: project_settings_ci_cd_path(@project) do |f|
= form_errors(@project)
%fieldset.builds-feature
.form-group
- message = auto_devops_warning_message(@project)
- ci_file_formatted = '<code>.gitlab-ci.yml</code>'.html_safe
- if message
%p.settings-message.text-center
= message.html_safe
= f.fields_for :auto_devops_attributes, @auto_devops do |form|
.radio
= form.label :enabled_true do
= form.radio_button :enabled, 'true'
%strong= s_('CICD|Enable Auto DevOps')
%br
= s_('CICD|The Auto DevOps pipeline configuration will be used when there is no %{ci_file} in the project.').html_safe % { ci_file: ci_file_formatted }
.radio
= form.label :enabled_false do
= form.radio_button :enabled, 'false'
%strong= s_('CICD|Disable Auto DevOps')
%br
= s_('CICD|An explicit %{ci_file} needs to be specified before you can begin using Continuous Integration and Delivery.').html_safe % { ci_file: ci_file_formatted }
.radio
= form.label :enabled_ do
= form.radio_button :enabled, ''
%strong= s_('CICD|Instance default (%{state})') % { state: "#{Gitlab::CurrentSettings.auto_devops_enabled? ? _('enabled') : _('disabled')}" }
%br
= s_('CICD|Follow the instance default to either have Auto DevOps enabled or disabled when there is no project specific %{ci_file}.').html_safe % { ci_file: ci_file_formatted }
= form.label :domain, class:"prepend-top-10" do
= _('Domain')
= form.text_field :domain, class: 'form-control', placeholder: 'domain.com'
.help-block
= s_('CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages.')
= f.submit 'Save changes', class: "btn btn-success prepend-top-15"
......@@ -3,44 +3,6 @@
= form_for @project, url: project_settings_ci_cd_path(@project) do |f|
= form_errors(@project)
%fieldset.builds-feature
.form-group
%h5 Auto DevOps (Beta)
%p
Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration.
= link_to 'Learn more about Auto DevOps', help_page_path('topics/autodevops/index.md')
- message = auto_devops_warning_message(@project)
- if message
%p.settings-message.text-center
= message.html_safe
= f.fields_for :auto_devops_attributes, @auto_devops do |form|
.radio
= form.label :enabled_true do
= form.radio_button :enabled, 'true'
%strong Enable Auto DevOps
%br
%span.descr
The Auto DevOps pipeline configuration will be used when there is no <code>.gitlab-ci.yml</code> in the project.
.radio
= form.label :enabled_false do
= form.radio_button :enabled, 'false'
%strong Disable Auto DevOps
%br
%span.descr
An explicit <code>.gitlab-ci.yml</code> needs to be specified before you can begin using Continuous Integration and Delivery.
.radio
= form.label :enabled_ do
= form.radio_button :enabled, ''
%strong Instance default (#{Gitlab::CurrentSettings.auto_devops_enabled? ? 'enabled' : 'disabled'})
%br
%span.descr
Follow the instance default to either have Auto DevOps enabled or disabled when there is no project specific <code>.gitlab-ci.yml</code>.
%p
You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages.
= form.text_field :domain, class: 'form-control', placeholder: 'domain.com'
%hr
.form-group.append-bottom-default.js-secret-runner-token
= f.label :runners_token, "Runner token", class: 'label-light'
.form-control.js-secret-value-placeholder
......
......@@ -12,10 +12,22 @@
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? 'Collapse' : 'Expand'
%p
Update your CI/CD configuration, like job timeout or Auto DevOps.
Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report.
.settings-content
= render 'form'
%section.settings#autodevops-settings.no-animate{ class: ('expanded' if expanded) }
.settings-header
%h4
= s_('CICD|Auto DevOps (Beta)')
%button.btn.btn-default.js-settings-toggle{ type: 'button' }
= expanded ? _('Collapse') : _('Expand')
%p
= s_('CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration.')
= link_to s_('CICD|Learn more about Auto DevOps'), help_page_path('topics/autodevops/index.md')
.settings-content
= render 'autodevops_form'
%section.settings.no-animate{ class: ('expanded' if expanded) }
.settings-header
%h4
......
......@@ -9,7 +9,7 @@
- link = link_to(s_('AutoDevOps|Auto DevOps documentation'), help_page_path('topics/autodevops/index.md'), target: '_blank', rel: 'noopener noreferrer')
= s_('AutoDevOps|Learn more in the %{link_to_documentation}').html_safe % { link_to_documentation: link }
.banner-buttons
= link_to s_('AutoDevOps|Enable in settings'), project_settings_ci_cd_path(@project, anchor: 'js-general-pipeline-settings'), class: 'btn js-close-callout'
= link_to s_('AutoDevOps|Enable in settings'), project_settings_ci_cd_path(@project, anchor: 'autodevops-settings'), class: 'btn js-close-callout'
%button.btn-transparent.banner-close.close.js-close-callout{ type: 'button',
'aria-label' => 'Dismiss Auto DevOps box' }
......
---
title: Create settings section for autodevops
merge_request: 18321
author:
type: changed
---
title: Fix project creation for user endpoint when jobs_enabled parameter supplied
merge_request:
author:
type: fixed
---
title: Add missing changelog type to docs
merge_request: 18526
author: "@blackst0ne"
type: other
---
title: Add 2FA filter to users API for admins only
merge_request: 18503
author:
type: changed
---
title: Fix missing namespace for some internal users
merge_request: 18357
author:
type: fixed
class CreateMissingNamespaceForInternalUsers < ActiveRecord::Migration
DOWNTIME = false
def up
connection.exec_query(users_query.to_sql).rows.each do |id, username|
create_namespace(id, username)
# When testing locally I've noticed that these internal users are missing
# the notification email, for more details visit the below link:
# https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18357#note_68327560
set_notification_email(id)
end
end
def down
# no-op
end
private
def users
@users ||= Arel::Table.new(:users)
end
def namespaces
@namespaces ||= Arel::Table.new(:namespaces)
end
def users_query
condition = users[:ghost].eq(true)
if column_exists?(:users, :support_bot)
condition = condition.or(users[:support_bot].eq(true))
end
users.join(namespaces, Arel::Nodes::OuterJoin)
.on(namespaces[:type].eq(nil).and(namespaces[:owner_id].eq(users[:id])))
.where(namespaces[:owner_id].eq(nil))
.where(condition)
.project(users[:id], users[:username])
end
def create_namespace(user_id, username)
path = Uniquify.new.string(username) do |str|
query = "SELECT id FROM namespaces WHERE parent_id IS NULL AND path='#{str}' LIMIT 1"
connection.exec_query(query).present?
end
insert_query = "INSERT INTO namespaces(owner_id, path, name) VALUES(#{user_id}, '#{path}', '#{path}')"
namespace_id = connection.insert_sql(insert_query)
create_route(namespace_id)
end
def create_route(namespace_id)
return unless namespace_id
row = connection.exec_query("SELECT id, path FROM namespaces WHERE id=#{namespace_id}").first
id, path = row.values_at('id', 'path')
execute("INSERT INTO routes(source_id, source_type, path, name) VALUES(#{id}, 'Namespace', '#{path}', '#{path}')")
end
def set_notification_email(user_id)
execute "UPDATE users SET notification_email = email WHERE notification_email IS NULL AND id = #{user_id}"
end
end
......@@ -112,13 +112,13 @@ POST /projects/import
| `file` | string | yes | The file to be uploaded |
| `path` | string | yes | Name and path for new project |
| `overwrite` | boolean | no | If there is a project with the same path the import will overwrite it. Default to false |
| `override_params` | Hash | no | Supports all fields defined in the [Project API](projects.md)] |
| `override_params` | Hash | no | Supports all fields defined in the [Project API](projects.md) |
The override params passed will take precendence over all values defined inside the export file.
The override params passed will take precedence over all values defined inside the export file.
To upload a file from your filesystem, use the `--form` argument. This causes
To upload a file from your file system, use the `--form` argument. This causes
cURL to post data using the header `Content-Type: multipart/form-data`.
The `file=` parameter must point to a file on your filesystem and be preceded
The `file=` parameter must point to a file on your file system and be preceded
by `@`. For example:
```console
......
......@@ -22,7 +22,7 @@ The `merge_request` value is a reference to a merge request that adds this
entry, and the `author` key is used to give attribution to community
contributors. **Both are optional**.
The `type` field maps the category of the change,
valid options are: added, fixed, changed, deprecated, removed, security, other. **Type field is mandatory**.
valid options are: added, fixed, changed, deprecated, removed, security, performance, other. **Type field is mandatory**.
Community contributors and core team members are encouraged to add their name to
the `author` field. GitLab team members **should not**.
......
......@@ -74,6 +74,11 @@ module API
present options[:with].prepare_relation(projects, options), options
end
def translate_params_for_compatibility(params)
params[:builds_enabled] = params.delete(:jobs_enabled) if params.key?(:jobs_enabled)
params
end
end
resource :users, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
......@@ -123,7 +128,7 @@ module API
end
post do
attrs = declared_params(include_missing: false)
attrs[:builds_enabled] = attrs.delete(:jobs_enabled) if attrs.key?(:jobs_enabled)
attrs = translate_params_for_compatibility(attrs)
project = ::Projects::CreateService.new(current_user, attrs).execute
if project.saved?
......@@ -155,6 +160,7 @@ module API
not_found!('User') unless user
attrs = declared_params(include_missing: false)
attrs = translate_params_for_compatibility(attrs)
project = ::Projects::CreateService.new(user, attrs).execute
if project.saved?
......@@ -283,7 +289,7 @@ module API
authorize! :rename_project, user_project if attrs[:name].present?
authorize! :change_visibility_level, user_project if attrs[:visibility].present?
attrs[:builds_enabled] = attrs.delete(:jobs_enabled) if attrs.key?(:jobs_enabled)
attrs = translate_params_for_compatibility(attrs)
result = ::Projects::UpdateService.new(user_project, current_user, attrs).execute
......
module Gitlab
module Wiki
module Git
class CommitterWithHooks < Gollum::Committer
attr_reader :gl_wiki
......@@ -9,6 +9,9 @@ module Gitlab
end
def commit
# TODO: Remove after 10.8
return super unless allowed_to_run_hooks?
result = Gitlab::Git::OperationService.new(git_user, gl_wiki.repository).with_branch(
@wiki.ref,
start_branch_name: @wiki.ref
......@@ -24,6 +27,11 @@ module Gitlab
private
# TODO: Remove after 10.8
def allowed_to_run_hooks?
@options[:user_id] != 0 && @options[:username].present?
end
def git_user
@git_user ||= Gitlab::Git::User.new(@options[:username],
@options[:name],
......
......@@ -290,7 +290,7 @@ module Gitlab
end
def committer_with_hooks(commit_details)
Gitlab::Wiki::CommitterWithHooks.new(self, commit_details.to_h)
Gitlab::Git::CommitterWithHooks.new(self, commit_details.to_h)
end
def with_committer_with_hooks(commit_details, &block)
......
......@@ -8,6 +8,7 @@ describe "Projects > Settings > Pipelines settings" do
before do
sign_in(user)
project.add_role(user, role)
create(:project_auto_devops, project: project)
end
context 'for developer' do
......@@ -27,10 +28,17 @@ describe "Projects > Settings > Pipelines settings" do
visit project_settings_ci_cd_path(project)
fill_in('Test coverage parsing', with: 'coverage_regex')
click_on 'Save changes'
page.within '#js-general-pipeline-settings' do
click_on 'Save changes'
end
expect(page.status_code).to eq(200)
expect(page).to have_button('Save changes', disabled: false)
page.within '#js-general-pipeline-settings' do
expect(page).to have_button('Save changes', disabled: false)
end
expect(page).to have_field('Test coverage parsing', with: 'coverage_regex')
end
......@@ -38,10 +46,15 @@ describe "Projects > Settings > Pipelines settings" do
visit project_settings_ci_cd_path(project)
page.check('Auto-cancel redundant, pending pipelines')
click_on 'Save changes'
page.within '#js-general-pipeline-settings' do
click_on 'Save changes'
end
expect(page.status_code).to eq(200)
expect(page).to have_button('Save changes', disabled: false)
page.within '#js-general-pipeline-settings' do
expect(page).to have_button('Save changes', disabled: false)
end
checkbox = find_field('project_auto_cancel_pending_pipelines')
expect(checkbox).to be_checked
......@@ -51,13 +64,16 @@ describe "Projects > Settings > Pipelines settings" do
it 'update auto devops settings' do
visit project_settings_ci_cd_path(project)
fill_in('project_auto_devops_attributes_domain', with: 'test.com')
page.choose('project_auto_devops_attributes_enabled_false')
click_on 'Save changes'
page.within '#autodevops-settings' do
fill_in('project_auto_devops_attributes_domain', with: 'test.com')
page.choose('project_auto_devops_attributes_enabled_false')
click_on 'Save changes'
end
expect(page.status_code).to eq(200)
expect(project.auto_devops).to be_present
expect(project.auto_devops).not_to be_enabled
expect(project.auto_devops.domain).to eq('test.com')
end
end
end
......
......@@ -65,7 +65,7 @@ describe 'Projects > Show > User sees setup shortcut buttons' do
describe 'Auto DevOps button' do
it '"Enable Auto DevOps" button linked to settings page' do
page.within('.project-stats') do
expect(page).to have_link('Enable Auto DevOps', href: project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings'))
expect(page).to have_link('Enable Auto DevOps', href: project_settings_ci_cd_path(project, anchor: 'autodevops-settings'))
end
end
......@@ -75,7 +75,7 @@ describe 'Projects > Show > User sees setup shortcut buttons' do
visit project_path(project)
page.within('.project-stats') do
expect(page).to have_link('Auto DevOps enabled', href: project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings'))
expect(page).to have_link('Auto DevOps enabled', href: project_settings_ci_cd_path(project, anchor: 'autodevops-settings'))
end
end
end
......@@ -212,7 +212,7 @@ describe 'Projects > Show > User sees setup shortcut buttons' do
describe 'Auto DevOps button' do
it '"Enable Auto DevOps" button linked to settings page' do
page.within('.project-stats') do
expect(page).to have_link('Enable Auto DevOps', href: project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings'))
expect(page).to have_link('Enable Auto DevOps', href: project_settings_ci_cd_path(project, anchor: 'autodevops-settings'))
end
end
......@@ -222,7 +222,7 @@ describe 'Projects > Show > User sees setup shortcut buttons' do
visit project_path(project)
page.within('.project-stats') do
expect(page).to have_link('Auto DevOps enabled', href: project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings'))
expect(page).to have_link('Auto DevOps enabled', href: project_settings_ci_cd_path(project, anchor: 'autodevops-settings'))
end
end
......
......@@ -13,9 +13,9 @@ describe('Settings Panels', () => {
});
it('should expand linked hash fragment panel', () => {
location.hash = '#js-general-pipeline-settings';
location.hash = '#autodevops-settings';
const pipelineSettingsPanel = document.querySelector('#js-general-pipeline-settings');
const pipelineSettingsPanel = document.querySelector('#autodevops-settings');
// Our test environment automatically expands everything so we need to clear that out first
pipelineSettingsPanel.classList.remove('expanded');
......
......@@ -55,7 +55,6 @@ describe('Commit component', () => {
path: '/jschatz1',
username: 'jschatz1',
},
commitIconSvg: '<svg></svg>',
};
component = mountComponent(CommitComponent, props);
......@@ -82,8 +81,10 @@ describe('Commit component', () => {
expect(component.$el.querySelector('.commit-sha').textContent).toContain(props.shortSha);
});
it('should render the given commitIconSvg', () => {
expect(component.$el.querySelector('.js-commit-icon').children).toContain('svg');
it('should render icon for commit', () => {
expect(
component.$el.querySelector('.js-commit-icon use').getAttribute('xlink:href'),
).toContain('commit');
});
describe('Given commit title and author props', () => {
......
......@@ -3,10 +3,10 @@ import expandButton from '~/vue_shared/components/expand_button.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
describe('expand button', () => {
const Component = Vue.extend(expandButton);
let vm;
beforeEach(() => {
const Component = Vue.extend(expandButton);
vm = mountComponent(Component, {
slots: {
expanded: '<p>Expanded!</p>',
......@@ -22,7 +22,7 @@ describe('expand button', () => {
expect(vm.$el.textContent.trim()).toEqual('...');
});
it('hides expander on click', (done) => {
it('hides expander on click', done => {
vm.$el.querySelector('button').click();
vm.$nextTick(() => {
expect(vm.$el.querySelector('button').getAttribute('style')).toEqual('display: none;');
......
......@@ -73,6 +73,22 @@ describe('BaseComponent', () => {
expect(vm.$emit).toHaveBeenCalledWith('onLabelClick', mockLabels[0]);
});
});
describe('handleCollapsedValueClick', () => {
it('emits toggleCollapse event on component', () => {
spyOn(vm, '$emit');
vm.handleCollapsedValueClick();
expect(vm.$emit).toHaveBeenCalledWith('toggleCollapse');
});
});
describe('handleDropdownHidden', () => {
it('emits onDropdownClose event on component', () => {
spyOn(vm, '$emit');
vm.handleDropdownHidden();
expect(vm.$emit).toHaveBeenCalledWith('onDropdownClose');
});
});
});
describe('mounted', () => {
......
......@@ -56,6 +56,16 @@ describe('DropdownValueCollapsedComponent', () => {
});
});
describe('methods', () => {
describe('handleClick', () => {
it('emits onValueClick event on component', () => {
spyOn(vm, '$emit');
vm.handleClick();
expect(vm.$emit).toHaveBeenCalledWith('onValueClick');
});
});
});
describe('template', () => {
it('renders component container element with tooltip`', () => {
expect(vm.$el.dataset.placement).toBe('left');
......
require 'spec_helper'
describe Gitlab::Wiki::CommitterWithHooks, seed_helper: true do
describe Gitlab::Git::CommitterWithHooks, seed_helper: true do
shared_examples 'calling wiki hooks' do
let(:project) { create(:project) }
let(:user) { project.owner }
......
require 'spec_helper'
require Rails.root.join('db', 'migrate', '20180413022611_create_missing_namespace_for_internal_users.rb')
describe CreateMissingNamespaceForInternalUsers, :migration do
let(:users) { table(:users) }
let(:namespaces) { table(:namespaces) }
let(:routes) { table(:routes) }
internal_user_types = [:ghost]
internal_user_types << :support_bot if ActiveRecord::Base.connection.column_exists?(:users, :support_bot)
internal_user_types.each do |attr|
context "for #{attr} user" do
let(:internal_user) do
users.create!(email: 'test@example.com', projects_limit: 100, username: 'test', attr => true)
end
it 'creates the missing namespace' do
expect(namespaces.find_by(owner_id: internal_user.id)).to be_nil
migrate!
namespace = Namespace.find_by(type: nil, owner_id: internal_user.id)
route = namespace.route
expect(namespace.path).to eq(route.path)
expect(namespace.name).to eq(route.name)
end
it 'sets notification email' do
users.update(internal_user.id, notification_email: nil)
expect(users.find(internal_user.id).notification_email).to be_nil
migrate!
user = users.find(internal_user.id)
expect(user.notification_email).to eq(user.email)
end
end
end
end
......@@ -321,7 +321,7 @@ describe ProjectPresenter do
expect(presenter.autodevops_anchor_data).to eq(OpenStruct.new(enabled: false,
label: 'Enable Auto DevOps',
link: presenter.project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings')))
link: presenter.project_settings_ci_cd_path(project, anchor: 'autodevops-settings')))
end
end
end
......
......@@ -685,7 +685,8 @@ describe API::Projects do
issues_enabled: false,
merge_requests_enabled: false,
wiki_enabled: false,
request_access_enabled: true
request_access_enabled: true,
jobs_enabled: true
})
post api("/projects/user/#{user.id}", admin), project
......
require 'spec_helper'
describe 'projects/settings/ci_cd/_form' do
describe 'projects/settings/ci_cd/_autodevops_form' do
let(:project) { create(:project, :repository) }
before 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