Merge remote-tracking branch 'origin/master' into zj-mattermost-slash-config
This commit is contained in:
commit
0d224376cf
22
CHANGELOG.md
22
CHANGELOG.md
|
@ -2,6 +2,21 @@
|
|||
documentation](doc/development/changelog.md) for instructions on adding your own
|
||||
entry.
|
||||
|
||||
## 8.14.5 (2016-12-14)
|
||||
|
||||
- Moved Leave Project and Leave Group buttons to access_request_buttons from the settings dropdown. !7600
|
||||
- fix display hook error message. !7775 (basyura)
|
||||
- Remove wrong '.builds-feature' class from the MR settings fieldset. !7930
|
||||
- Avoid escaping relative links in Markdown twice. !7940 (winniehell)
|
||||
- API: Memoize the current_user so that sudo can work properly. !8017
|
||||
- Displays milestone remaining days only when it's present.
|
||||
- Allow branch names with dots on API endpoint.
|
||||
- Issue#visible_to_user moved to IssuesFinder to prevent accidental use.
|
||||
- Shows group members in project members list.
|
||||
- Encode input when migrating ProcessCommitWorker jobs to prevent migration errors.
|
||||
- Fixed timeago re-rendering every timeago.
|
||||
- Fix missing Note access checks by moving Note#search to updated NoteFinder.
|
||||
|
||||
## 8.14.4 (2016-12-08)
|
||||
|
||||
- Fix diff view permalink highlighting. !7090
|
||||
|
@ -264,6 +279,13 @@ entry.
|
|||
- Fix "Without projects" filter. !6611 (Ben Bodenmiller)
|
||||
- Fix 404 when visit /projects page
|
||||
|
||||
## 8.13.10 (2016-12-14)
|
||||
|
||||
- API: Memoize the current_user so that sudo can work properly. !8017
|
||||
- Filter `authentication_token`, `incoming_email_token` and `runners_token` parameters.
|
||||
- Issue#visible_to_user moved to IssuesFinder to prevent accidental use.
|
||||
- Fix missing Note access checks by moving Note#search to updated NoteFinder.
|
||||
|
||||
## 8.13.9 (2016-12-08)
|
||||
|
||||
- Reenables /user API request to return private-token if user is admin and request is made with sudo. !7615
|
||||
|
|
|
@ -1 +1 @@
|
|||
4.1.0
|
||||
4.1.1
|
||||
|
|
2
Gemfile
2
Gemfile
|
@ -169,7 +169,7 @@ gem 'gitlab-flowdock-git-hook', '~> 1.0.1'
|
|||
gem 'gemnasium-gitlab-service', '~> 0.2'
|
||||
|
||||
# Slack integration
|
||||
gem 'slack-notifier', '~> 1.2.0'
|
||||
gem 'slack-notifier', '~> 1.5.1'
|
||||
|
||||
# Asana integration
|
||||
gem 'asana', '~> 0.4.0'
|
||||
|
|
|
@ -683,7 +683,7 @@ GEM
|
|||
json (>= 1.8, < 3)
|
||||
simplecov-html (~> 0.10.0)
|
||||
simplecov-html (0.10.0)
|
||||
slack-notifier (1.2.1)
|
||||
slack-notifier (1.5.1)
|
||||
slop (3.6.0)
|
||||
spinach (0.8.10)
|
||||
colorize
|
||||
|
@ -952,7 +952,7 @@ DEPENDENCIES
|
|||
sidekiq-cron (~> 0.4.4)
|
||||
sidekiq-limit_fetch (~> 3.4)
|
||||
simplecov (= 0.12.0)
|
||||
slack-notifier (~> 1.2.0)
|
||||
slack-notifier (~> 1.5.1)
|
||||
spinach-rails (~> 0.2.1)
|
||||
spinach-rerun-reporter (~> 0.0.2)
|
||||
spring (~> 1.7.0)
|
||||
|
|
|
@ -343,16 +343,18 @@
|
|||
selector = ".dropdown-page-one .dropdown-content a";
|
||||
}
|
||||
this.dropdown.on("click", selector, function(e) {
|
||||
var $el, selected;
|
||||
var $el, selected, selectedObj, isMarking;
|
||||
$el = $(this);
|
||||
selected = self.rowClicked($el);
|
||||
selectedObj = selected ? selected[0] : null;
|
||||
isMarking = selected ? selected[1] : null;
|
||||
if (self.options.clicked) {
|
||||
self.options.clicked(selected[0], $el, e, selected[1]);
|
||||
self.options.clicked(selectedObj, $el, e, isMarking);
|
||||
}
|
||||
|
||||
// Update label right after all modifications in dropdown has been done
|
||||
if (self.options.toggleLabel) {
|
||||
self.updateLabel(selected[0], $el, self);
|
||||
self.updateLabel(selectedObj, $el, self);
|
||||
}
|
||||
|
||||
$el.trigger('blur');
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
});
|
||||
$(document).off('ajax:success', '.notification-form').on('ajax:success', '.notification-form', function(e, data) {
|
||||
if (data.saved) {
|
||||
return $(e.currentTarget).closest('.notification-dropdown').replaceWith(data.html);
|
||||
return $(e.currentTarget).closest('.js-notification-dropdown').replaceWith(data.html);
|
||||
} else {
|
||||
return new Flash('Failed to save new settings', 'alert');
|
||||
}
|
||||
|
|
|
@ -96,6 +96,10 @@ label {
|
|||
code {
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
img {
|
||||
margin-right: $gl-padding;
|
||||
}
|
||||
}
|
||||
|
||||
@media(max-width: $screen-xs-max) {
|
||||
|
|
|
@ -49,3 +49,11 @@
|
|||
fill: $gray-darkest;
|
||||
}
|
||||
}
|
||||
|
||||
.ci-status-icon-manual {
|
||||
color: $gl-text-color;
|
||||
|
||||
svg {
|
||||
fill: $gl-text-color;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
}
|
||||
|
||||
// Display Star and Fork buttons without counters on mobile.
|
||||
.project-action-buttons {
|
||||
.project-repo-buttons {
|
||||
display: block;
|
||||
|
||||
.count-buttons .btn {
|
||||
|
|
|
@ -57,7 +57,6 @@
|
|||
}
|
||||
|
||||
.ci-status-link {
|
||||
|
||||
svg {
|
||||
position: relative;
|
||||
top: 2px;
|
||||
|
|
|
@ -18,6 +18,20 @@
|
|||
margin-top: -2px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
&.split {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.left {
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.right {
|
||||
flex: 0 0 auto;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.panel-body {
|
||||
|
|
|
@ -24,6 +24,7 @@ $gray-lightest: #fdfdfd;
|
|||
$gray-light: #fafafa;
|
||||
$gray-lighter: #f9f9f9;
|
||||
$gray-normal: #f5f5f5;
|
||||
$gray-dark: darken($gray-light, $darken-dark-factor);
|
||||
$gray-darker: #eee;
|
||||
$gray-darkest: #c4c4c4;
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
padding: $gl-padding-top 0;
|
||||
border-bottom: 1px solid $border-color;
|
||||
color: $gl-text-color-dark;
|
||||
font-size: 16px;
|
||||
line-height: 34px;
|
||||
|
||||
.author {
|
||||
|
|
|
@ -27,12 +27,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.group-buttons {
|
||||
.notification-dropdown {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.groups-header {
|
||||
@media (min-width: $screen-sm-min) {
|
||||
.nav-links {
|
||||
|
|
|
@ -428,7 +428,7 @@
|
|||
width: 21px;
|
||||
height: 25px;
|
||||
position: absolute;
|
||||
top: -32px;
|
||||
top: -31px;
|
||||
border-top: 2px solid $border-color;
|
||||
}
|
||||
|
||||
|
@ -456,32 +456,31 @@
|
|||
}
|
||||
|
||||
.build {
|
||||
border: 1px solid $border-color;
|
||||
border-radius: 30px;
|
||||
background-color: $white-light;
|
||||
position: relative;
|
||||
padding: 8px 4px 9px 10px;
|
||||
width: 186px;
|
||||
margin-bottom: 10px;
|
||||
white-space: normal;
|
||||
color: $gl-text-color-light;
|
||||
|
||||
&:hover {
|
||||
background-color: $stage-hover-bg;
|
||||
border: 1px solid $stage-hover-border;
|
||||
> .build-content {
|
||||
display: inline-block;
|
||||
padding: 8px 10px 9px;
|
||||
width: 100%;
|
||||
border: 1px solid $border-color;
|
||||
border-radius: 30px;
|
||||
background-color: $white-light;
|
||||
|
||||
a,
|
||||
.dropdown-counter-badge,
|
||||
.dropdown-menu-toggle {
|
||||
&:hover {
|
||||
background-color: $stage-hover-bg;
|
||||
border: 1px solid $stage-hover-border;
|
||||
color: $gl-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
.grouped-pipeline-dropdown a {
|
||||
color: $gl-text-color-light;
|
||||
|
||||
&:hover {
|
||||
color: $gl-text-color;
|
||||
}
|
||||
}
|
||||
> .ci-action-icon-container {
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
top: 5px;
|
||||
}
|
||||
|
||||
.ci-status-icon {
|
||||
|
@ -621,8 +620,8 @@
|
|||
padding: 0;
|
||||
width: 191px;
|
||||
left: auto;
|
||||
right: -206px;
|
||||
top: -11px;
|
||||
right: -195px;
|
||||
top: -4px;
|
||||
box-shadow: 0 1px 5px $black-transparent;
|
||||
|
||||
a {
|
||||
|
@ -650,17 +649,25 @@
|
|||
.dropdown-build {
|
||||
color: $gl-text-color-light;
|
||||
|
||||
a.ci-action-icon-container {
|
||||
padding: 0;
|
||||
.build-content {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ci-action-icon-container {
|
||||
font-size: 11px;
|
||||
float: right;
|
||||
margin-top: 4px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
|
||||
i {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
font-size: 11px;
|
||||
margin-top: 0;
|
||||
|
||||
&::before {
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -670,18 +677,6 @@
|
|||
color: $gl-text-color;
|
||||
}
|
||||
|
||||
.ci-action-icon-container {
|
||||
i {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
|
||||
&::before {
|
||||
top: 1px;
|
||||
left: 1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.stage {
|
||||
max-width: 100px;
|
||||
width: 100px;
|
||||
|
@ -704,9 +699,6 @@
|
|||
|
||||
// Action Icons
|
||||
.ci-action-icon-container .ci-action-icon-wrapper {
|
||||
float: right;
|
||||
margin-top: -4px;
|
||||
|
||||
i {
|
||||
color: $border-color;
|
||||
border-radius: 100%;
|
||||
|
|
|
@ -145,8 +145,6 @@
|
|||
|
||||
.project-repo-buttons,
|
||||
.group-buttons {
|
||||
margin-top: 15px;
|
||||
|
||||
.btn {
|
||||
@include btn-gray;
|
||||
padding: 3px 10px;
|
||||
|
@ -175,11 +173,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
.download-button,
|
||||
.dropdown-toggle,
|
||||
.notification-dropdown,
|
||||
.project-dropdown {
|
||||
margin-left: 10px;
|
||||
.project-action-button {
|
||||
margin: 15px 5px 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.notification-dropdown .dropdown-menu {
|
||||
|
@ -195,13 +191,15 @@
|
|||
.count-buttons {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.project-clone-holder {
|
||||
display: inline-block;
|
||||
margin: 15px 5px 0 0;
|
||||
|
||||
input {
|
||||
height: 29px;
|
||||
height: 28px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,7 +253,7 @@
|
|||
line-height: 13px;
|
||||
padding: $gl-vert-padding $gl-padding;
|
||||
letter-spacing: .4px;
|
||||
padding: 7px 14px;
|
||||
padding: 6px 14px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
touch-action: manipulation;
|
||||
|
@ -492,6 +490,7 @@ a.deploy-project-label {
|
|||
|
||||
.project-stats {
|
||||
font-size: 0;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid $border-color;
|
||||
|
||||
.nav {
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
height: 13px;
|
||||
width: 13px;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
margin-right: 3px;
|
||||
top: 2px;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
|
@ -25,7 +24,7 @@
|
|||
border-color: $gl-danger;
|
||||
|
||||
&:not(span):hover {
|
||||
background-color: rgba( $gl-danger, .07);
|
||||
background-color: rgba($gl-danger, .07);
|
||||
}
|
||||
|
||||
svg {
|
||||
|
@ -39,7 +38,7 @@
|
|||
border-color: $gl-success;
|
||||
|
||||
&:not(span):hover {
|
||||
background-color: rgba( $gl-success, .07);
|
||||
background-color: rgba($gl-success, .07);
|
||||
}
|
||||
|
||||
svg {
|
||||
|
@ -52,7 +51,7 @@
|
|||
border-color: $gl-info;
|
||||
|
||||
&:not(span):hover {
|
||||
background-color: rgba( $gl-info, .07);
|
||||
background-color: rgba($gl-info, .07);
|
||||
}
|
||||
|
||||
svg {
|
||||
|
@ -66,7 +65,7 @@
|
|||
border-color: $gl-gray;
|
||||
|
||||
&:not(span):hover {
|
||||
background-color: rgba( $gl-gray, .07);
|
||||
background-color: rgba($gl-gray, .07);
|
||||
}
|
||||
|
||||
svg {
|
||||
|
@ -79,7 +78,7 @@
|
|||
border-color: $gl-warning;
|
||||
|
||||
&:not(span):hover {
|
||||
background-color: rgba( $gl-warning, .07);
|
||||
background-color: rgba($gl-warning, .07);
|
||||
}
|
||||
|
||||
svg {
|
||||
|
@ -92,7 +91,7 @@
|
|||
border-color: $blue-normal;
|
||||
|
||||
&:not(span):hover {
|
||||
background-color: rgba( $blue-normal, .07);
|
||||
background-color: rgba($blue-normal, .07);
|
||||
}
|
||||
|
||||
svg {
|
||||
|
@ -106,13 +105,26 @@
|
|||
border-color: $gl-gray-light;
|
||||
|
||||
&:not(span):hover {
|
||||
background-color: rgba( $gl-gray-light, .07);
|
||||
background-color: rgba($gl-gray-light, .07);
|
||||
}
|
||||
|
||||
svg {
|
||||
fill: $gl-gray-light;
|
||||
}
|
||||
}
|
||||
|
||||
&.ci-manual {
|
||||
color: $gl-text-color;
|
||||
border-color: $gl-text-color;
|
||||
|
||||
&:not(span):hover {
|
||||
background-color: rgba($gl-text-color, .07);
|
||||
}
|
||||
|
||||
svg {
|
||||
fill: $gl-text-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
.add-to-tree {
|
||||
vertical-align: top;
|
||||
padding: 6px 10px;
|
||||
}
|
||||
|
||||
.tree-table {
|
||||
|
@ -172,7 +173,7 @@
|
|||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
.download-button {
|
||||
.project-action-button {
|
||||
margin-left: $btn-side-margin;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,9 @@ class Projects::BlameController < Projects::ApplicationController
|
|||
|
||||
def show
|
||||
@blob = @repository.blob_at(@commit.id, @path)
|
||||
|
||||
return render_404 unless @blob
|
||||
|
||||
@blame_groups = Gitlab::Blame.new(@blob, @commit).groups
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,7 +18,7 @@ module Ci
|
|||
end
|
||||
|
||||
serialize :options
|
||||
serialize :yaml_variables
|
||||
serialize :yaml_variables, Gitlab::Serialize::Ci::Variables
|
||||
|
||||
validates :coverage, numericality: true, allow_blank: true
|
||||
validates_presence_of :ref
|
||||
|
|
|
@ -97,7 +97,7 @@ class MergeRequest < ActiveRecord::Base
|
|||
validates :source_branch, presence: true
|
||||
validates :target_project, presence: true
|
||||
validates :target_branch, presence: true
|
||||
validates :merge_user, presence: true, if: :merge_when_build_succeeds?
|
||||
validates :merge_user, presence: true, if: :merge_when_build_succeeds?, unless: :importing?
|
||||
validate :validate_branches, unless: [:allow_broken, :importing?, :closed_without_fork?]
|
||||
validate :validate_fork, unless: :closed_without_fork?
|
||||
|
||||
|
|
|
@ -79,7 +79,6 @@ class Project < ActiveRecord::Base
|
|||
|
||||
has_one :last_event, -> {order 'events.created_at DESC'}, class_name: 'Event'
|
||||
has_many :boards, before_add: :validate_board_limit, dependent: :destroy
|
||||
has_many :chat_services
|
||||
|
||||
# Project services
|
||||
has_one :campfire_service, dependent: :destroy
|
||||
|
@ -96,6 +95,7 @@ class Project < ActiveRecord::Base
|
|||
has_one :gemnasium_service, dependent: :destroy
|
||||
has_one :mattermost_slash_commands_service, dependent: :destroy
|
||||
has_one :mattermost_notification_service, dependent: :destroy
|
||||
has_one :slack_slash_commands_service, dependent: :destroy
|
||||
has_one :slack_notification_service, dependent: :destroy
|
||||
has_one :buildkite_service, dependent: :destroy
|
||||
has_one :bamboo_service, dependent: :destroy
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
# Base class for Chat services
|
||||
# This class is not meant to be used directly, but only to inherit from.
|
||||
class ChatService < Service
|
||||
default_value_for :category, 'chat'
|
||||
|
||||
has_many :chat_names, foreign_key: :service_id
|
||||
|
||||
def valid_token?(token)
|
||||
self.respond_to?(:token) &&
|
||||
self.token.present? &&
|
||||
ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.token)
|
||||
end
|
||||
|
||||
def supported_events
|
||||
[]
|
||||
end
|
||||
|
||||
def trigger(params)
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
|
@ -0,0 +1,56 @@
|
|||
# Base class for Chat services
|
||||
# This class is not meant to be used directly, but only to inherrit from.
|
||||
class ChatSlashCommandsService < Service
|
||||
default_value_for :category, 'chat'
|
||||
|
||||
prop_accessor :token
|
||||
|
||||
has_many :chat_names, foreign_key: :service_id, dependent: :destroy
|
||||
|
||||
def valid_token?(token)
|
||||
self.respond_to?(:token) &&
|
||||
self.token.present? &&
|
||||
ActiveSupport::SecurityUtils.variable_size_secure_compare(token, self.token)
|
||||
end
|
||||
|
||||
def supported_events
|
||||
[]
|
||||
end
|
||||
|
||||
def can_test?
|
||||
false
|
||||
end
|
||||
|
||||
def fields
|
||||
[
|
||||
{ type: 'text', name: 'token', placeholder: '' }
|
||||
]
|
||||
end
|
||||
|
||||
def trigger(params)
|
||||
return unless valid_token?(params[:token])
|
||||
|
||||
user = find_chat_user(params)
|
||||
unless user
|
||||
url = authorize_chat_name_url(params)
|
||||
return presenter.authorize_chat_name(url)
|
||||
end
|
||||
|
||||
Gitlab::ChatCommands::Command.new(project, user,
|
||||
params).execute
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_chat_user(params)
|
||||
ChatNames::FindUserService.new(self, params).execute
|
||||
end
|
||||
|
||||
def authorize_chat_name_url(params)
|
||||
ChatNames::AuthorizeUserService.new(self, params).execute
|
||||
end
|
||||
|
||||
def presenter
|
||||
Gitlab::ChatCommands::Presenter.new
|
||||
end
|
||||
end
|
|
@ -1,4 +1,4 @@
|
|||
class MattermostSlashCommandsService < ChatService
|
||||
class MattermostSlashCommandsService < ChatSlashCommandsService
|
||||
include TriggersHelper
|
||||
|
||||
prop_accessor :token
|
||||
|
@ -19,12 +19,6 @@ class MattermostSlashCommandsService < ChatService
|
|||
'mattermost_slash_commands'
|
||||
end
|
||||
|
||||
def fields
|
||||
[
|
||||
{ type: 'text', name: 'token', placeholder: '' }
|
||||
]
|
||||
end
|
||||
|
||||
def configure!(user, params)
|
||||
token = Mattermost::Command.new(user).
|
||||
create(command(params))
|
||||
|
@ -36,18 +30,6 @@ class MattermostSlashCommandsService < ChatService
|
|||
Mattermost::Team.new(user).all
|
||||
end
|
||||
|
||||
def trigger(params)
|
||||
return nil unless valid_token?(params[:token])
|
||||
|
||||
user = find_chat_user(params)
|
||||
unless user
|
||||
url = authorize_chat_name_url(params)
|
||||
return Mattermost::Presenter.authorize_chat_name(url)
|
||||
end
|
||||
|
||||
Gitlab::ChatCommands::Command.new(project, user, params).execute
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def command(params)
|
||||
|
@ -62,12 +44,4 @@ class MattermostSlashCommandsService < ChatService
|
|||
method: 'P',
|
||||
user_name: 'GitLab')
|
||||
end
|
||||
|
||||
def find_chat_user(params)
|
||||
ChatNames::FindUserService.new(self, params).execute
|
||||
end
|
||||
|
||||
def authorize_chat_name_url(params)
|
||||
ChatNames::AuthorizeUserService.new(self, params).execute
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
class SlackSlashCommandsService < ChatSlashCommandsService
|
||||
include TriggersHelper
|
||||
|
||||
def title
|
||||
'Slack Command'
|
||||
end
|
||||
|
||||
def description
|
||||
"Perform common operations on GitLab in Slack"
|
||||
end
|
||||
|
||||
def to_param
|
||||
'slack_slash_commands'
|
||||
end
|
||||
|
||||
def trigger(params)
|
||||
# Format messages to be Slack-compatible
|
||||
super.tap do |result|
|
||||
result[:text] = format(result[:text])
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def format(text)
|
||||
Slack::Notifier::LinkFormatter.format(text) if text
|
||||
end
|
||||
end
|
|
@ -13,7 +13,7 @@ class Route < ActiveRecord::Base
|
|||
def rename_children
|
||||
# We update each row separately because MySQL does not have regexp_replace.
|
||||
# rubocop:disable Rails/FindEach
|
||||
Route.where('path LIKE ?', "#{path_was}%").each do |route|
|
||||
Route.where('path LIKE ?', "#{path_was}/%").each do |route|
|
||||
# Note that update column skips validation and callbacks.
|
||||
# We need this to avoid recursive call of rename_children method
|
||||
route.update_column(:path, route.path.sub(path_was, path))
|
||||
|
|
|
@ -216,11 +216,12 @@ class Service < ActiveRecord::Base
|
|||
jira
|
||||
kubernetes
|
||||
mattermost_slash_commands
|
||||
mattermost_notification
|
||||
pipelines_email
|
||||
pivotaltracker
|
||||
pushover
|
||||
redmine
|
||||
mattermost_notification
|
||||
slack_slash_commands
|
||||
slack_notification
|
||||
teamcity
|
||||
]
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
- status = local_assigns.fetch(:status)
|
||||
- css_classes = "ci-status ci-#{status.group}"
|
||||
|
||||
- if status.has_details?
|
||||
= link_to status.details_path, class: "ci-status ci-#{status}" do
|
||||
= link_to status.details_path, class: css_classes do
|
||||
= custom_icon(status.icon)
|
||||
= status.text
|
||||
- else
|
||||
%span{ class: "ci-status ci-#{status}" }
|
||||
%span{ class: css_classes }
|
||||
= custom_icon(status.icon)
|
||||
= status.text
|
||||
|
|
|
@ -2,15 +2,16 @@
|
|||
|
||||
- subject = local_assigns.fetch(:subject)
|
||||
- status = subject.detailed_status(current_user)
|
||||
- klass = "ci-status-icon ci-status-icon-#{status}"
|
||||
- klass = "ci-status-icon ci-status-icon-#{status.group}"
|
||||
|
||||
- if status.has_details?
|
||||
= link_to status.details_path, data: { toggle: 'tooltip', title: "#{subject.name} - #{status.label}" } do
|
||||
= link_to status.details_path, class: 'build-content' do
|
||||
%span{ class: klass }= custom_icon(status.icon)
|
||||
.ci-status-text= subject.name
|
||||
.ci-status-text{ 'data-toggle' => 'tooltip', 'data-title' => "#{subject.name} - #{status.label}" }= subject.name
|
||||
- else
|
||||
%span{ class: klass }= custom_icon(status.icon)
|
||||
.ci-status-text= subject.name
|
||||
.build-content
|
||||
%span{ class: klass }= custom_icon(status.icon)
|
||||
.ci-status-text{ 'data-toggle' => 'tooltip', 'data-title' => "#{subject.name} - #{status.label}" }= subject.name
|
||||
|
||||
- if status.has_action?
|
||||
= link_to status.action_path, method: status.action_method,
|
||||
|
|
|
@ -18,11 +18,19 @@
|
|||
= link_to project_path(forked_from_project) do
|
||||
= forked_from_project.namespace.try(:name)
|
||||
|
||||
.project-repo-buttons.project-action-buttons
|
||||
.project-repo-buttons
|
||||
.count-buttons
|
||||
= render 'projects/buttons/star'
|
||||
= render 'projects/buttons/fork'
|
||||
|
||||
- if @project.feature_available?(:repository, current_user)
|
||||
.project-clone-holder
|
||||
= render "shared/clone_panel"
|
||||
%span.hidden-xs
|
||||
- if @project.feature_available?(:repository, current_user)
|
||||
.project-clone-holder
|
||||
= render "shared/clone_panel"
|
||||
|
||||
- if current_user && can?(current_user, :download_code, @project)
|
||||
= render 'projects/buttons/download', project: @project, ref: @ref
|
||||
= render 'projects/buttons/dropdown'
|
||||
= render 'shared/notifications/button', notification_setting: @notification_setting
|
||||
= render 'projects/buttons/koding'
|
||||
= render 'shared/members/access_request_buttons', source: @project
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
- if !project.empty_repo? && can?(current_user, :download_code, project)
|
||||
.dropdown.inline.download-button
|
||||
.project-action-button.dropdown.inline
|
||||
%button.btn{ 'data-toggle' => 'dropdown' }
|
||||
= icon('download')
|
||||
= icon("caret-down")
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
- if current_user
|
||||
.dropdown.inline
|
||||
.project-action-button.dropdown.inline
|
||||
%a.btn.dropdown-toggle{href: '#', "data-toggle" => "dropdown"}
|
||||
= icon('plus')
|
||||
= icon("caret-down")
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
- if koding_enabled? && current_user && can_push_branch?(@project, @project.default_branch)
|
||||
- if @repository.koding_yml
|
||||
= link_to koding_project_url(@project), class: 'btn', target: '_blank' do
|
||||
Run in IDE (Koding)
|
||||
- else
|
||||
= link_to add_koding_stack_path(@project), class: 'btn' do
|
||||
Set Up Koding
|
||||
- if koding_enabled? && current_user && @repository.koding_yml && can_push_branch?(@project, @project.default_branch)
|
||||
= link_to koding_project_url(@project), class: 'btn project-action-button inline', target: '_blank' do
|
||||
Run in IDE (Koding)
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
- run_actions_text = "Perform common operations on this project: #{@project.name_with_namespace}"
|
||||
|
||||
.well
|
||||
This service allows GitLab users to perform common operations on this
|
||||
project by entering slash commands in Slack.
|
||||
%br
|
||||
See list of available commands in Slack after setting up this service,
|
||||
by entering
|
||||
%code /<command> help
|
||||
%br
|
||||
%br
|
||||
To setup this service:
|
||||
%ul.list-unstyled
|
||||
%li
|
||||
1.
|
||||
= link_to 'Add a slash command', 'https://my.slack.com/services/new/slash-commands'
|
||||
in your Slack team with these options:
|
||||
|
||||
%hr
|
||||
|
||||
.help-form
|
||||
.form-group
|
||||
= label_tag nil, 'Command', class: 'col-sm-2 col-xs-12 control-label'
|
||||
.col-sm-10.col-xs-12.text-block
|
||||
%p Fill in the word that works best for your team.
|
||||
%p
|
||||
Suggestions:
|
||||
%code= 'gitlab'
|
||||
%code= @project.path # Path contains no spaces, but dashes
|
||||
%code= @project.path_with_namespace
|
||||
|
||||
.form-group
|
||||
= label_tag :url, 'URL', class: 'col-sm-2 col-xs-12 control-label'
|
||||
.col-sm-10.col-xs-12.input-group
|
||||
= text_field_tag :url, service_trigger_url(subject), class: 'form-control input-sm', readonly: 'readonly'
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#url')
|
||||
|
||||
.form-group
|
||||
= label_tag nil, 'Method', class: 'col-sm-2 col-xs-12 control-label'
|
||||
.col-sm-10.col-xs-12.text-block POST
|
||||
|
||||
.form-group
|
||||
= label_tag :customize_name, 'Customize name', class: 'col-sm-2 col-xs-12 control-label'
|
||||
.col-sm-10.col-xs-12.input-group
|
||||
= text_field_tag :customize_name, 'GitLab', class: 'form-control input-sm', readonly: 'readonly'
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#customize_name')
|
||||
|
||||
.form-group
|
||||
= label_tag nil, 'Customize icon', class: 'col-sm-2 col-xs-12 control-label'
|
||||
.col-sm-10.col-xs-12.text-block
|
||||
= image_tag(asset_url('gitlab_logo.png'), width: 36, height: 36)
|
||||
= link_to('Download image', asset_url('gitlab_logo.png'), class: 'btn btn-sm', target: '_blank')
|
||||
|
||||
.form-group
|
||||
= label_tag nil, 'Autocomplete', class: 'col-sm-2 col-xs-12 control-label'
|
||||
.col-sm-10.col-xs-12.text-block Show this command in the autocomplete list
|
||||
|
||||
.form-group
|
||||
= label_tag :autocomplete_description, 'Autocomplete description', class: 'col-sm-2 col-xs-12 control-label'
|
||||
.col-sm-10.col-xs-12.input-group
|
||||
= text_field_tag :autocomplete_description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly'
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#autocomplete_description')
|
||||
|
||||
.form-group
|
||||
= label_tag :autocomplete_usage_hint, 'Autocomplete usage hint', class: 'col-sm-2 col-xs-12 control-label'
|
||||
.col-sm-10.col-xs-12.input-group
|
||||
= text_field_tag :autocomplete_usage_hint, '[help]', class: 'form-control input-sm', readonly: 'readonly'
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#autocomplete_usage_hint')
|
||||
|
||||
.form-group
|
||||
= label_tag :descriptive_label, 'Descriptive label', class: 'col-sm-2 col-xs-12 control-label'
|
||||
.col-sm-10.col-xs-12.input-group
|
||||
= text_field_tag :descriptive_label, 'Perform common operations on GitLab project', class: 'form-control input-sm', readonly: 'readonly'
|
||||
.input-group-btn
|
||||
= clipboard_button(clipboard_target: '#descriptive_label')
|
||||
|
||||
%hr
|
||||
|
||||
%ul.list-unstyled
|
||||
%li
|
||||
2. Paste the
|
||||
%strong Token
|
||||
into the field below
|
||||
%li
|
||||
3. Select the
|
||||
%strong Active
|
||||
checkbox, press
|
||||
%strong Save changes
|
||||
and start using GitLab inside Slack!
|
|
@ -64,20 +64,11 @@
|
|||
- unless @repository.gitlab_ci_yml
|
||||
%li.missing
|
||||
= link_to add_special_file_path(@project, file_name: '.gitlab-ci.yml') do
|
||||
Set Up CI
|
||||
Set up CI
|
||||
- if koding_enabled? && @repository.koding_yml.blank?
|
||||
%li.missing
|
||||
= link_to 'Set up Koding', add_koding_stack_path(@project)
|
||||
|
||||
%li.project-repo-buttons.right
|
||||
.project-right-buttons
|
||||
- if current_user
|
||||
= render 'shared/members/access_request_buttons', source: @project
|
||||
= render "projects/buttons/koding"
|
||||
|
||||
.btn-group.project-repo-btn-group
|
||||
= render 'projects/buttons/download', project: @project, ref: @ref
|
||||
= render 'projects/buttons/dropdown'
|
||||
|
||||
.pull-right
|
||||
= render 'shared/notifications/button', notification_setting: @notification_setting
|
||||
- if @repository.commit
|
||||
.project-last-commit{ class: container_class }
|
||||
= render 'projects/last_commit', commit: @repository.commit, ref: current_ref, project: @project
|
||||
|
|
|
@ -10,12 +10,11 @@
|
|||
- status_groups.each do |group_name, grouped_statuses|
|
||||
- if grouped_statuses.one?
|
||||
- status = grouped_statuses.first
|
||||
%li.build
|
||||
%li.build{ 'id' => "ci-badge-#{group_name}" }
|
||||
.curve
|
||||
.build-content
|
||||
= render 'ci/status/graph_badge', subject: status
|
||||
= render 'ci/status/graph_badge', subject: status
|
||||
- else
|
||||
%li.build
|
||||
%li.build{ 'id' => "ci-badge-#{group_name}" }
|
||||
.curve
|
||||
.dropdown.inline.build-content
|
||||
= render 'projects/stage/in_stage_group', name: group_name, subject: grouped_statuses
|
||||
= render 'projects/stage/in_stage_group', name: group_name, subject: grouped_statuses
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
- group_status = CommitStatus.where(id: subject).status
|
||||
%button.dropdown-menu-toggle.has-tooltip{ type: 'button', data: { toggle: 'dropdown', title: "#{name} - #{group_status}" } }
|
||||
%button.dropdown-menu-toggle.build-content.has-tooltip{ type: 'button', data: { toggle: 'dropdown'} }
|
||||
%span{class: "ci-status-icon ci-status-icon-#{group_status}"}
|
||||
= ci_icon_for_status(group_status)
|
||||
%span.ci-status-text
|
||||
%span.ci-status-text{ 'data-toggle' => 'tooltip', 'data-title' => "#{name} - #{group_status}" }
|
||||
= name
|
||||
%span.dropdown-counter-badge= subject.size
|
||||
.dropdown-menu.grouped-pipeline-dropdown
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
- model_name = source.model_name.to_s.downcase
|
||||
|
||||
- if can?(current_user, :"destroy_#{model_name}_member", source.members.find_by(user_id: current_user.id))
|
||||
= link_to "Leave #{model_name}", polymorphic_path([:leave, source, :members]),
|
||||
method: :delete,
|
||||
data: { confirm: leave_confirmation_message(source) },
|
||||
class: 'btn'
|
||||
- elsif requester = source.requesters.find_by(user_id: current_user.id)
|
||||
= link_to 'Withdraw Access Request', polymorphic_path([:leave, source, :members]),
|
||||
method: :delete,
|
||||
data: { confirm: remove_member_message(requester) },
|
||||
class: 'btn'
|
||||
- elsif source.request_access_enabled && can?(current_user, :request_access, source)
|
||||
= link_to 'Request Access', polymorphic_path([:request_access, source, :members]),
|
||||
method: :post,
|
||||
class: 'btn'
|
||||
.project-action-button.inline
|
||||
- if can?(current_user, :"destroy_#{model_name}_member", source.members.find_by(user_id: current_user.id))
|
||||
= link_to "Leave #{model_name}", polymorphic_path([:leave, source, :members]),
|
||||
method: :delete,
|
||||
data: { confirm: leave_confirmation_message(source) },
|
||||
class: 'btn'
|
||||
- elsif requester = source.requesters.find_by(user_id: current_user.id)
|
||||
= link_to 'Withdraw Access Request', polymorphic_path([:leave, source, :members]),
|
||||
method: :delete,
|
||||
data: { confirm: remove_member_message(requester) },
|
||||
class: 'btn'
|
||||
- elsif source.request_access_enabled && can?(current_user, :request_access, source)
|
||||
= link_to 'Request Access', polymorphic_path([:request_access, source, :members]),
|
||||
method: :post,
|
||||
class: 'btn'
|
||||
|
|
|
@ -3,10 +3,12 @@
|
|||
- panel_class = primary ? 'panel-primary' : 'panel-default'
|
||||
|
||||
.panel{ class: panel_class }
|
||||
.panel-heading
|
||||
= title
|
||||
.panel-heading.split
|
||||
.left
|
||||
= title
|
||||
- if show_counter
|
||||
.pull-right= issuables.size
|
||||
.right
|
||||
= issuables.size
|
||||
|
||||
- class_prefix = dom_class(issuables).pluralize
|
||||
%ul{ class: "well-list #{class_prefix}-sortable-list", id: "#{class_prefix}-list-#{id}", "data-state" => id }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
- if notification_setting
|
||||
.dropdown.notification-dropdown
|
||||
.js-notification-dropdown.notification-dropdown.project-action-button.dropdown.inline
|
||||
= form_for notification_setting, remote: true, html: { class: "inline notification-form" } do |f|
|
||||
= hidden_setting_source_input(notification_setting)
|
||||
= f.hidden_field :level, class: "notification_setting_level"
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
---
|
||||
title: Moved Leave Project and Leave Group buttons to access_request_buttons from
|
||||
the settings dropdown
|
||||
merge_request: 7600
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Remove wrong '.builds-feature' class from the MR settings fieldset
|
||||
merge_request: 7930
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Made the padding on the plus button in the breadcrumb menu even
|
||||
merge_request:
|
||||
author: Ryan Harris
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Fix Route#rename_children behavior
|
||||
merge_request:
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Fix blame 500 error on invalid path.
|
||||
merge_request: 25761
|
||||
author: Jeff Stubler
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Fix Import/Export duplicated builds error
|
||||
merge_request:
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Fix missing service error importing from EE to CE
|
||||
merge_request: 8144
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Fix Import/Export merge requests error while importing
|
||||
merge_request:
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Displays milestone remaining days only when it's present
|
||||
merge_request:
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Convert CI YAML variables keys into strings
|
||||
merge_request: 8088
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Shows group members in project members list
|
||||
merge_request:
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: "fix display hook error message"
|
||||
merge_request: 7775
|
||||
author: basyura
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Allow branch names with dots on API endpoint
|
||||
merge_request:
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Add LDAP Rake task to rename a provider
|
||||
merge_request: 2181
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Move all action buttons to project header
|
||||
merge_request:
|
||||
author:
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Make CI badge hitboxes match parent
|
||||
merge_request:
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Fixed timeago re-rendering every timeago
|
||||
merge_request:
|
||||
author:
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: Avoid escaping relative links in Markdown twice
|
||||
merge_request: 7940
|
||||
author: winniehell
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: Refactor presenters ChatCommands
|
||||
merge_request: 7846
|
||||
author:
|
|
@ -1,26 +1,50 @@
|
|||
class Gitlab::Seeder::Pipelines
|
||||
STAGES = %w[build test deploy notify]
|
||||
BUILDS = [
|
||||
{ name: 'build:linux', stage: 'build', status: :success },
|
||||
{ name: 'build:osx', stage: 'build', status: :success },
|
||||
{ name: 'rspec:linux 0 3', stage: 'test', status: :success },
|
||||
{ name: 'rspec:linux 1 3', stage: 'test', status: :success },
|
||||
{ name: 'rspec:linux 2 3', stage: 'test', status: :success },
|
||||
{ name: 'rspec:windows 0 3', stage: 'test', status: :success },
|
||||
{ name: 'rspec:windows 1 3', stage: 'test', status: :success },
|
||||
{ name: 'rspec:windows 2 3', stage: 'test', status: :success },
|
||||
{ name: 'rspec:windows 2 3', stage: 'test', status: :success },
|
||||
{ name: 'rspec:osx', stage: 'test', status_event: :success },
|
||||
{ name: 'spinach:linux', stage: 'test', status: :success },
|
||||
{ name: 'spinach:osx', stage: 'test', status: :failed, allow_failure: true},
|
||||
{ name: 'env:alpha', stage: 'deploy', environment: 'alpha', status: :pending },
|
||||
{ name: 'env:beta', stage: 'deploy', environment: 'beta', status: :running },
|
||||
{ name: 'env:gamma', stage: 'deploy', environment: 'gamma', status: :canceled },
|
||||
{ name: 'staging', stage: 'deploy', environment: 'staging', status_event: :success, options: { environment: { on_stop: 'stop staging' } } },
|
||||
{ name: 'stop staging', stage: 'deploy', environment: 'staging', when: 'manual', status: :skipped },
|
||||
{ name: 'production', stage: 'deploy', environment: 'production', when: 'manual', status: :skipped },
|
||||
# build stage
|
||||
{ name: 'build:linux', stage: 'build', status: :success,
|
||||
queued_at: 10.hour.ago, started_at: 9.hour.ago, finished_at: 8.hour.ago },
|
||||
{ name: 'build:osx', stage: 'build', status: :success,
|
||||
queued_at: 10.hour.ago, started_at: 10.hour.ago, finished_at: 9.hour.ago },
|
||||
|
||||
# test stage
|
||||
{ name: 'rspec:linux 0 3', stage: 'test', status: :success,
|
||||
queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
|
||||
{ name: 'rspec:linux 1 3', stage: 'test', status: :success,
|
||||
queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
|
||||
{ name: 'rspec:linux 2 3', stage: 'test', status: :success,
|
||||
queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
|
||||
{ name: 'rspec:windows 0 3', stage: 'test', status: :success,
|
||||
queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
|
||||
{ name: 'rspec:windows 1 3', stage: 'test', status: :success,
|
||||
queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
|
||||
{ name: 'rspec:windows 2 3', stage: 'test', status: :success,
|
||||
queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
|
||||
{ name: 'rspec:windows 2 3', stage: 'test', status: :success,
|
||||
queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
|
||||
{ name: 'rspec:osx', stage: 'test', status_event: :success,
|
||||
queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
|
||||
{ name: 'spinach:linux', stage: 'test', status: :success,
|
||||
queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
|
||||
{ name: 'spinach:osx', stage: 'test', status: :failed, allow_failure: true,
|
||||
queued_at: 8.hour.ago, started_at: 8.hour.ago, finished_at: 7.hour.ago },
|
||||
|
||||
# deploy stage
|
||||
{ name: 'staging', stage: 'deploy', environment: 'staging', status_event: :success,
|
||||
options: { environment: { action: 'start', on_stop: 'stop staging' } },
|
||||
queued_at: 7.hour.ago, started_at: 6.hour.ago, finished_at: 4.hour.ago },
|
||||
{ name: 'stop staging', stage: 'deploy', environment: 'staging',
|
||||
when: 'manual', status: :skipped },
|
||||
{ name: 'production', stage: 'deploy', environment: 'production',
|
||||
when: 'manual', status: :skipped },
|
||||
|
||||
# notify stage
|
||||
{ name: 'slack', stage: 'notify', when: 'manual', status: :created },
|
||||
]
|
||||
EXTERNAL_JOBS = [
|
||||
{ name: 'jenkins', stage: 'test', status: :success,
|
||||
queued_at: 7.hour.ago, started_at: 6.hour.ago, finished_at: 4.hour.ago },
|
||||
]
|
||||
|
||||
def initialize(project)
|
||||
@project = project
|
||||
|
@ -30,11 +54,12 @@ class Gitlab::Seeder::Pipelines
|
|||
pipelines.each do |pipeline|
|
||||
begin
|
||||
BUILDS.each { |opts| build_create!(pipeline, opts) }
|
||||
commit_status_create!(pipeline, name: 'jenkins', stage: 'test', status: :success)
|
||||
EXTERNAL_JOBS.each { |opts| commit_status_create!(pipeline, opts) }
|
||||
print '.'
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
print 'F'
|
||||
ensure
|
||||
pipeline.update_duration
|
||||
pipeline.update_status
|
||||
end
|
||||
end
|
||||
|
|
|
@ -74,24 +74,5 @@ Example output:
|
|||
|
||||
The LDAP check Rake task will test the bind_dn and password credentials
|
||||
(if configured) and will list a sample of LDAP users. This task is also
|
||||
executed as part of the `gitlab:check` task, but can run independently
|
||||
using the command below.
|
||||
|
||||
**Omnibus Installation**
|
||||
|
||||
```
|
||||
sudo gitlab-rake gitlab:ldap:check
|
||||
```
|
||||
|
||||
**Source Installation**
|
||||
|
||||
```bash
|
||||
sudo -u git -H bundle exec rake gitlab:ldap:check RAILS_ENV=production
|
||||
```
|
||||
|
||||
By default, the task will return a sample of 100 LDAP users. Change this
|
||||
limit by passing a number to the check task:
|
||||
|
||||
```bash
|
||||
rake gitlab:ldap:check[50]
|
||||
```
|
||||
executed as part of the `gitlab:check` task, but can run independently.
|
||||
See [LDAP Rake Tasks - LDAP Check](ldap.md#check) for details.
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
# LDAP Rake Tasks
|
||||
|
||||
## Check
|
||||
|
||||
The LDAP check Rake task will test the `bind_dn` and `password` credentials
|
||||
(if configured) and will list a sample of LDAP users. This task is also
|
||||
executed as part of the `gitlab:check` task, but can run independently
|
||||
using the command below.
|
||||
|
||||
**Omnibus Installation**
|
||||
|
||||
```
|
||||
sudo gitlab-rake gitlab:ldap:check
|
||||
```
|
||||
|
||||
**Source Installation**
|
||||
|
||||
```bash
|
||||
sudo -u git -H bundle exec rake gitlab:ldap:check RAILS_ENV=production
|
||||
```
|
||||
|
||||
------
|
||||
|
||||
By default, the task will return a sample of 100 LDAP users. Change this
|
||||
limit by passing a number to the check task:
|
||||
|
||||
```bash
|
||||
rake gitlab:ldap:check[50]
|
||||
```
|
||||
|
||||
## Rename a provider
|
||||
|
||||
If you change the LDAP server ID in `gitlab.yml` or `gitlab.rb` you will need
|
||||
to update all user identities or users will be unable to sign in. Input the
|
||||
old and new provider and this task will update all matching identities in the
|
||||
database.
|
||||
|
||||
`old_provider` and `new_provider` are derived from the prefix `ldap` plus the
|
||||
LDAP server ID from the configuration file. For example, in `gitlab.yml` or
|
||||
`gitlab.rb` you may see LDAP configuration like this:
|
||||
|
||||
```yaml
|
||||
main:
|
||||
label: 'LDAP'
|
||||
host: '_your_ldap_server'
|
||||
port: 389
|
||||
uid: 'sAMAccountName'
|
||||
...
|
||||
```
|
||||
|
||||
`main` is the LDAP server ID. Together, the unique provider is `ldapmain`.
|
||||
|
||||
> **Warning**: If you input an incorrect new provider users will be unable
|
||||
to sign in. If this happens, run the task again with the incorrect provider
|
||||
as the `old_provider` and the correct provider as the `new_provider`.
|
||||
|
||||
**Omnibus Installation**
|
||||
|
||||
```bash
|
||||
sudo gitlab-rake gitlab:ldap:rename_provider[old_provider,new_provider]
|
||||
```
|
||||
|
||||
**Source Installation**
|
||||
|
||||
```bash
|
||||
bundle exec rake gitlab:ldap:rename_provider[old_provider,new_provider] RAILS_ENV=production
|
||||
```
|
||||
|
||||
### Example
|
||||
|
||||
Consider beginning with the default server ID `main` (full provider `ldapmain`).
|
||||
If we change `main` to `mycompany`, the `new_provider` is `ldapmycompany`.
|
||||
To rename all user identities run the following command:
|
||||
|
||||
```bash
|
||||
sudo gitlab-rake gitlab:ldap:rename_provider[ldapmain,ldapmycompany]
|
||||
```
|
||||
|
||||
Example output:
|
||||
|
||||
```
|
||||
100 users with provider 'ldapmain' will be updated to 'ldapmycompany'.
|
||||
If the new provider is incorrect, users will be unable to sign in.
|
||||
Do you want to continue (yes/no)? yes
|
||||
|
||||
User identities were successfully updated
|
||||
```
|
||||
|
||||
### Other options
|
||||
|
||||
If you do not specify an `old_provider` and `new_provider` you will be prompted
|
||||
for them:
|
||||
|
||||
**Omnibus Installation**
|
||||
|
||||
```bash
|
||||
sudo gitlab-rake gitlab:ldap:rename_provider
|
||||
```
|
||||
|
||||
**Source Installation**
|
||||
|
||||
```bash
|
||||
bundle exec rake gitlab:ldap:rename_provider RAILS_ENV=production
|
||||
```
|
||||
|
||||
**Example output:**
|
||||
|
||||
```
|
||||
What is the old provider? Ex. 'ldapmain': ldapmain
|
||||
What is the new provider? Ex. 'ldapcustom': ldapmycompany
|
||||
```
|
||||
|
||||
------
|
||||
|
||||
This tasks also accepts the `force` environment variable which will skip the
|
||||
confirmation dialog:
|
||||
|
||||
```bash
|
||||
sudo gitlab-rake gitlab:ldap:rename_provider[old_provider,new_provider] force=yes
|
||||
```
|
|
@ -1056,7 +1056,7 @@ variables:
|
|||
GET_SOURCES_ATTEMPTS: "3"
|
||||
```
|
||||
|
||||
You can set the them in the global [`variables`](#variables) section or the [`variables`](#job-variables)
|
||||
You can set them in the global [`variables`](#variables) section or the [`variables`](#job-variables)
|
||||
section for individual jobs.
|
||||
|
||||
## Shallow cloning
|
||||
|
|
|
@ -37,7 +37,7 @@ graphs/dashboards.
|
|||
GitLab provides built-in tools to aid the process of improving performance:
|
||||
|
||||
* [Sherlock](profiling.md#sherlock)
|
||||
* [GitLab Performance Monitoring](../administration/monitoring/performance/monitoring.md)
|
||||
* [GitLab Performance Monitoring](../administration/monitoring/performance/introduction.md)
|
||||
* [Request Profiling](../administration/monitoring/performance/request_profiling.md)
|
||||
|
||||
GitLab employees can use GitLab.com's performance monitoring systems located at
|
||||
|
|
|
@ -5,7 +5,7 @@ Bitbucket.org account.
|
|||
|
||||
## Overview
|
||||
|
||||
You can set up Bitbucket.org as an OAuth provider so that you can use your
|
||||
You can set up Bitbucket.org as an OAuth2 provider so that you can use your
|
||||
credentials to authenticate into GitLab or import your projects from
|
||||
Bitbucket.org.
|
||||
|
||||
|
@ -50,6 +50,7 @@ you to use.
|
|||
Repositories: Read
|
||||
Pull Requests: Read
|
||||
Issues: Read
|
||||
Wiki: Read and Write
|
||||
```
|
||||
|
||||
![Bitbucket OAuth settings page](img/bitbucket_oauth_settings_page.png)
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 28 KiB |
|
@ -4,7 +4,8 @@
|
|||
- [Check](check.md)
|
||||
- [Cleanup](cleanup.md)
|
||||
- [Features](features.md)
|
||||
- [Maintenance](maintenance.md) and self-checks
|
||||
- [LDAP Maintenance](../administration/raketasks/ldap.md)
|
||||
- [General Maintenance](maintenance.md) and self-checks
|
||||
- [User management](user_management.md)
|
||||
- [Webhooks](web_hooks.md)
|
||||
- [Import](import.md) of git repositories in bulk
|
||||
|
|
|
@ -72,7 +72,7 @@ sudo -u git -H git checkout 8-15-stable-ee
|
|||
```bash
|
||||
cd /home/git/gitlab-shell
|
||||
sudo -u git -H git fetch --all --tags
|
||||
sudo -u git -H git checkout v4.1.0
|
||||
sudo -u git -H git checkout v4.1.1
|
||||
```
|
||||
|
||||
### 6. Update gitlab-workhorse
|
||||
|
|
|
@ -17,6 +17,7 @@ to enable this if not already.
|
|||
- the pull requests (GitLab 8.4+)
|
||||
- the pull request comments (GitLab 8.15+)
|
||||
- the milestones (GitLab 8.15+)
|
||||
- the wiki (GitLab 8.15+)
|
||||
- References to pull requests and issues are preserved (GitLab 8.7+)
|
||||
- Repository public access is retained. If a repository is private in Bitbucket
|
||||
it will be created as private in GitLab as well.
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
Feature: Admin Appearance
|
||||
Scenario: Create new appearance
|
||||
Given I sign in as an admin
|
||||
And I visit admin appearance page
|
||||
When submit form with new appearance
|
||||
Then I should be redirected to admin appearance page
|
||||
And I should see newly created appearance
|
||||
|
||||
Scenario: Preview appearance
|
||||
Given application has custom appearance
|
||||
And I sign in as an admin
|
||||
When I visit admin appearance page
|
||||
And I click preview button
|
||||
Then I should see a customized appearance
|
||||
|
||||
Scenario: Custom sign-in page
|
||||
Given application has custom appearance
|
||||
When I visit login page
|
||||
Then I should see a customized appearance
|
||||
|
||||
Scenario: Appearance logo
|
||||
Given application has custom appearance
|
||||
And I sign in as an admin
|
||||
And I visit admin appearance page
|
||||
When I attach a logo
|
||||
Then I should see a logo
|
||||
And I remove the logo
|
||||
Then I should see logo removed
|
||||
|
||||
Scenario: Header logos
|
||||
Given application has custom appearance
|
||||
And I sign in as an admin
|
||||
And I visit admin appearance page
|
||||
When I attach header logos
|
||||
Then I should see header logos
|
||||
And I remove the header logos
|
||||
Then I should see header logos removed
|
|
@ -1,33 +0,0 @@
|
|||
@admin
|
||||
Feature: Admin Broadcast Messages
|
||||
Background:
|
||||
Given I sign in as an admin
|
||||
And application already has a broadcast message
|
||||
And I visit admin messages page
|
||||
|
||||
Scenario: See broadcast messages list
|
||||
Then I should see all broadcast messages
|
||||
|
||||
Scenario: Create a customized broadcast message
|
||||
When submit form with new customized broadcast message
|
||||
Then I should be redirected to admin messages page
|
||||
And I should see newly created broadcast message
|
||||
Then I visit dashboard page
|
||||
And I should see a customized broadcast message
|
||||
|
||||
Scenario: Edit an existing broadcast message
|
||||
When I edit an existing broadcast message
|
||||
And I change the broadcast message text
|
||||
Then I should be redirected to admin messages page
|
||||
And I should see the updated broadcast message
|
||||
|
||||
Scenario: Remove an existing broadcast message
|
||||
When I remove an existing broadcast message
|
||||
Then I should be redirected to admin messages page
|
||||
And I should not see the removed broadcast message
|
||||
|
||||
@javascript
|
||||
Scenario: Live preview a customized broadcast message
|
||||
When I visit admin messages page
|
||||
And I enter a broadcast message with Markdown
|
||||
Then I should see a live preview of the rendered broadcast message
|
|
@ -1,38 +0,0 @@
|
|||
Feature: Admin Issues Labels
|
||||
Background:
|
||||
Given I sign in as an admin
|
||||
And I have labels: "bug", "feature", "enhancement"
|
||||
Given I visit admin labels page
|
||||
|
||||
Scenario: I should see labels list
|
||||
Then I should see label 'bug'
|
||||
And I should see label 'feature'
|
||||
|
||||
Scenario: I create new label
|
||||
Given I submit new label 'support'
|
||||
Then I should see label 'support'
|
||||
|
||||
Scenario: I edit label
|
||||
Given I visit 'bug' label edit page
|
||||
When I change label 'bug' to 'fix'
|
||||
Then I should not see label 'bug'
|
||||
Then I should see label 'fix'
|
||||
|
||||
Scenario: I remove label
|
||||
When I remove label 'bug'
|
||||
Then I should not see label 'bug'
|
||||
|
||||
@javascript
|
||||
Scenario: I delete all labels
|
||||
When I delete all labels
|
||||
Then I should see labels help message
|
||||
|
||||
Scenario: I create a label with invalid color
|
||||
Given I visit admin new label page
|
||||
When I submit new label with invalid color
|
||||
Then I should see label color error message
|
||||
|
||||
Scenario: I create a label that already exists
|
||||
Given I visit admin new label page
|
||||
When I submit new label 'bug'
|
||||
Then I should see label exist error message
|
|
@ -37,11 +37,11 @@ Feature: Project Services
|
|||
And I fill Assembla settings
|
||||
Then I should see Assembla service settings saved
|
||||
|
||||
Scenario: Activate Slack service
|
||||
Scenario: Activate Slack notifications service
|
||||
When I visit project "Shop" services page
|
||||
And I click Slack service link
|
||||
And I fill Slack settings
|
||||
Then I should see Slack service settings saved
|
||||
And I click Slack notifications service link
|
||||
And I fill Slack notifications settings
|
||||
Then I should see Slack Notifications service settings saved
|
||||
|
||||
Scenario: Activate Pushover service
|
||||
When I visit project "Shop" services page
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
class Spinach::Features::AdminAppearance < Spinach::FeatureSteps
|
||||
include SharedAuthentication
|
||||
include SharedPaths
|
||||
|
||||
step 'submit form with new appearance' do
|
||||
fill_in 'appearance_title', with: 'MyCompany'
|
||||
fill_in 'appearance_description', with: 'dev server'
|
||||
click_button 'Save'
|
||||
end
|
||||
|
||||
step 'I should be redirected to admin appearance page' do
|
||||
expect(current_path).to eq admin_appearances_path
|
||||
expect(page).to have_content 'Appearance settings'
|
||||
end
|
||||
|
||||
step 'I should see newly created appearance' do
|
||||
expect(page).to have_field('appearance_title', with: 'MyCompany')
|
||||
expect(page).to have_field('appearance_description', with: 'dev server')
|
||||
expect(page).to have_content 'Last edit'
|
||||
end
|
||||
|
||||
step 'I click preview button' do
|
||||
click_link "Preview"
|
||||
end
|
||||
|
||||
step 'application has custom appearance' do
|
||||
create(:appearance)
|
||||
end
|
||||
|
||||
step 'I should see a customized appearance' do
|
||||
expect(page).to have_content appearance.title
|
||||
expect(page).to have_content appearance.description
|
||||
end
|
||||
|
||||
step 'I attach a logo' do
|
||||
attach_file(:appearance_logo, Rails.root.join('spec', 'fixtures', 'dk.png'))
|
||||
click_button 'Save'
|
||||
end
|
||||
|
||||
step 'I attach header logos' do
|
||||
attach_file(:appearance_header_logo, Rails.root.join('spec', 'fixtures', 'dk.png'))
|
||||
click_button 'Save'
|
||||
end
|
||||
|
||||
step 'I should see a logo' do
|
||||
expect(page).to have_xpath('//img[@src="/uploads/appearance/logo/1/dk.png"]')
|
||||
end
|
||||
|
||||
step 'I should see header logos' do
|
||||
expect(page).to have_xpath('//img[@src="/uploads/appearance/header_logo/1/dk.png"]')
|
||||
end
|
||||
|
||||
step 'I remove the logo' do
|
||||
click_link 'Remove logo'
|
||||
end
|
||||
|
||||
step 'I remove the header logos' do
|
||||
click_link 'Remove header logo'
|
||||
end
|
||||
|
||||
step 'I should see logo removed' do
|
||||
expect(page).not_to have_xpath('//img[@src="/uploads/appearance/logo/1/gitlab_logo.png"]')
|
||||
end
|
||||
|
||||
step 'I should see header logos removed' do
|
||||
expect(page).not_to have_xpath('//img[@src="/uploads/appearance/header_logo/1/header_logo_light.png"]')
|
||||
end
|
||||
|
||||
def appearance
|
||||
Appearance.last
|
||||
end
|
||||
end
|
|
@ -1,66 +0,0 @@
|
|||
class Spinach::Features::AdminBroadcastMessages < Spinach::FeatureSteps
|
||||
include SharedAuthentication
|
||||
include SharedPaths
|
||||
|
||||
step 'application already has a broadcast message' do
|
||||
FactoryGirl.create(:broadcast_message, :expired, message: "Migration to new server")
|
||||
end
|
||||
|
||||
step 'I should see all broadcast messages' do
|
||||
expect(page).to have_content "Migration to new server"
|
||||
end
|
||||
|
||||
step 'I should be redirected to admin messages page' do
|
||||
expect(current_path).to eq admin_broadcast_messages_path
|
||||
end
|
||||
|
||||
step 'I should see newly created broadcast message' do
|
||||
expect(page).to have_content 'Application update from 4:00 CST to 5:00 CST'
|
||||
end
|
||||
|
||||
step 'submit form with new customized broadcast message' do
|
||||
fill_in 'broadcast_message_message', with: 'Application update from **4:00 CST to 5:00 CST**'
|
||||
fill_in 'broadcast_message_color', with: '#f2dede'
|
||||
fill_in 'broadcast_message_font', with: '#b94a48'
|
||||
select Date.today.next_year.year, from: "broadcast_message_ends_at_1i"
|
||||
click_button "Add broadcast message"
|
||||
end
|
||||
|
||||
step 'I should see a customized broadcast message' do
|
||||
expect(page).to have_content 'Application update from 4:00 CST to 5:00 CST'
|
||||
expect(page).to have_selector 'strong', text: '4:00 CST to 5:00 CST'
|
||||
expect(page).to have_selector %(div[style="background-color: #f2dede; color: #b94a48"])
|
||||
end
|
||||
|
||||
step 'I edit an existing broadcast message' do
|
||||
click_link 'Edit'
|
||||
end
|
||||
|
||||
step 'I change the broadcast message text' do
|
||||
fill_in 'broadcast_message_message', with: 'Application update RIGHT NOW'
|
||||
click_button 'Update broadcast message'
|
||||
end
|
||||
|
||||
step 'I should see the updated broadcast message' do
|
||||
expect(page).to have_content "Application update RIGHT NOW"
|
||||
end
|
||||
|
||||
step 'I remove an existing broadcast message' do
|
||||
click_link 'Remove'
|
||||
end
|
||||
|
||||
step 'I should not see the removed broadcast message' do
|
||||
expect(page).not_to have_content 'Migration to new server'
|
||||
end
|
||||
|
||||
step 'I enter a broadcast message with Markdown' do
|
||||
fill_in 'broadcast_message_message', with: "Live **Markdown** previews. :tada:"
|
||||
end
|
||||
|
||||
step 'I should see a live preview of the rendered broadcast message' do
|
||||
page.within('.broadcast-message-preview') do
|
||||
expect(page).to have_selector('strong', text: 'Markdown')
|
||||
expect(page).to have_selector('img.emoji')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,117 +0,0 @@
|
|||
class Spinach::Features::AdminIssuesLabels < Spinach::FeatureSteps
|
||||
include SharedAuthentication
|
||||
include SharedProject
|
||||
include SharedPaths
|
||||
|
||||
step 'I visit \'bug\' label edit page' do
|
||||
visit edit_admin_label_path(bug_label)
|
||||
end
|
||||
|
||||
step 'I visit admin new label page' do
|
||||
visit new_admin_label_path
|
||||
end
|
||||
|
||||
step 'I visit admin labels page' do
|
||||
visit admin_labels_path
|
||||
end
|
||||
|
||||
step 'I remove label \'bug\'' do
|
||||
page.within "#label_#{bug_label.id}" do
|
||||
click_link 'Delete'
|
||||
end
|
||||
end
|
||||
|
||||
step 'I have labels: "bug", "feature", "enhancement"' do
|
||||
["bug", "feature", "enhancement"].each do |title|
|
||||
Label.create(title: title, template: true)
|
||||
end
|
||||
end
|
||||
|
||||
step 'I delete all labels' do
|
||||
page.within '.labels' do
|
||||
page.all('.btn-remove').each do |remove|
|
||||
remove.click
|
||||
sleep 0.05
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
step 'I should see labels help message' do
|
||||
page.within '.labels' do
|
||||
expect(page).to have_content 'There are no labels yet'
|
||||
end
|
||||
end
|
||||
|
||||
step 'I submit new label \'support\'' do
|
||||
visit new_admin_label_path
|
||||
fill_in 'Title', with: 'support'
|
||||
fill_in 'Background color', with: '#F95610'
|
||||
click_button 'Save'
|
||||
end
|
||||
|
||||
step 'I submit new label \'bug\'' do
|
||||
visit new_admin_label_path
|
||||
fill_in 'Title', with: 'bug'
|
||||
fill_in 'Background color', with: '#F95610'
|
||||
click_button 'Save'
|
||||
end
|
||||
|
||||
step 'I submit new label with invalid color' do
|
||||
visit new_admin_label_path
|
||||
fill_in 'Title', with: 'support'
|
||||
fill_in 'Background color', with: '#12'
|
||||
click_button 'Save'
|
||||
end
|
||||
|
||||
step 'I should see label exist error message' do
|
||||
page.within '.label-form' do
|
||||
expect(page).to have_content 'Title has already been taken'
|
||||
end
|
||||
end
|
||||
|
||||
step 'I should see label color error message' do
|
||||
page.within '.label-form' do
|
||||
expect(page).to have_content 'Color must be a valid color code'
|
||||
end
|
||||
end
|
||||
|
||||
step 'I should see label \'feature\'' do
|
||||
page.within '.manage-labels-list' do
|
||||
expect(page).to have_content 'feature'
|
||||
end
|
||||
end
|
||||
|
||||
step 'I should see label \'bug\'' do
|
||||
page.within '.manage-labels-list' do
|
||||
expect(page).to have_content 'bug'
|
||||
end
|
||||
end
|
||||
|
||||
step 'I should not see label \'bug\'' do
|
||||
page.within '.manage-labels-list' do
|
||||
expect(page).not_to have_content 'bug'
|
||||
end
|
||||
end
|
||||
|
||||
step 'I should see label \'support\'' do
|
||||
page.within '.manage-labels-list' do
|
||||
expect(page).to have_content 'support'
|
||||
end
|
||||
end
|
||||
|
||||
step 'I change label \'bug\' to \'fix\'' do
|
||||
fill_in 'Title', with: 'fix'
|
||||
fill_in 'Background color', with: '#F15610'
|
||||
click_button 'Save'
|
||||
end
|
||||
|
||||
step 'I should see label \'fix\'' do
|
||||
page.within '.manage-labels-list' do
|
||||
expect(page).to have_content 'fix'
|
||||
end
|
||||
end
|
||||
|
||||
def bug_label
|
||||
Label.templates.find_or_create_by(title: 'bug')
|
||||
end
|
||||
end
|
|
@ -137,17 +137,17 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps
|
|||
expect(find_field('Colorize messages').value).to eq '1'
|
||||
end
|
||||
|
||||
step 'I click Slack service link' do
|
||||
click_link 'Slack'
|
||||
step 'I click Slack notifications service link' do
|
||||
click_link 'Slack notifications'
|
||||
end
|
||||
|
||||
step 'I fill Slack settings' do
|
||||
step 'I fill Slack notifications settings' do
|
||||
check 'Active'
|
||||
fill_in 'Webhook', with: 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685'
|
||||
click_button 'Save'
|
||||
end
|
||||
|
||||
step 'I should see Slack service settings saved' do
|
||||
step 'I should see Slack Notifications service settings saved' do
|
||||
expect(find_field('Webhook').value).to eq 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685'
|
||||
end
|
||||
|
||||
|
|
|
@ -195,10 +195,6 @@ module SharedPaths
|
|||
visit admin_groups_path
|
||||
end
|
||||
|
||||
step 'I visit admin appearance page' do
|
||||
visit admin_appearances_path
|
||||
end
|
||||
|
||||
step 'I visit admin teams page' do
|
||||
visit admin_teams_path
|
||||
end
|
||||
|
|
|
@ -378,7 +378,6 @@ module API
|
|||
desc: 'A custom certificate authority bundle to verify the Kubernetes cluster with (PEM format)'
|
||||
},
|
||||
],
|
||||
|
||||
'mattermost-slash-commands' => [
|
||||
{
|
||||
required: true,
|
||||
|
@ -387,6 +386,14 @@ module API
|
|||
desc: 'The Mattermost token'
|
||||
}
|
||||
],
|
||||
'slack-slash-commands' => [
|
||||
{
|
||||
required: true,
|
||||
name: :token,
|
||||
type: String,
|
||||
desc: 'The Slack token'
|
||||
}
|
||||
],
|
||||
'pipelines-email' => [
|
||||
{
|
||||
required: true,
|
||||
|
|
|
@ -51,6 +51,10 @@ module Bitbucket
|
|||
raw['scm'] == 'git'
|
||||
end
|
||||
|
||||
def has_wiki?
|
||||
raw['has_wiki']
|
||||
end
|
||||
|
||||
def visibility_level
|
||||
if raw['is_private']
|
||||
Gitlab::VisibilityLevel::PRIVATE
|
||||
|
|
|
@ -41,7 +41,7 @@ module Ci
|
|||
put ":id" do
|
||||
authenticate_runner!
|
||||
build = Ci::Build.where(runner_id: current_runner.id).running.find(params[:id])
|
||||
forbidden!('Build has been erased!') if build.erased?
|
||||
validate_build!(build)
|
||||
|
||||
update_runner_info
|
||||
|
||||
|
@ -71,9 +71,7 @@ module Ci
|
|||
# PATCH /builds/:id/trace.txt
|
||||
patch ":id/trace.txt" do
|
||||
build = Ci::Build.find_by_id(params[:id])
|
||||
not_found! unless build
|
||||
authenticate_build_token!(build)
|
||||
forbidden!('Build has been erased!') if build.erased?
|
||||
authenticate_build!(build)
|
||||
|
||||
error!('400 Missing header Content-Range', 400) unless request.headers.has_key?('Content-Range')
|
||||
content_range = request.headers['Content-Range']
|
||||
|
@ -104,8 +102,7 @@ module Ci
|
|||
Gitlab::Workhorse.verify_api_request!(headers)
|
||||
not_allowed! unless Gitlab.config.artifacts.enabled
|
||||
build = Ci::Build.find_by_id(params[:id])
|
||||
not_found! unless build
|
||||
authenticate_build_token!(build)
|
||||
authenticate_build!(build)
|
||||
forbidden!('build is not running') unless build.running?
|
||||
|
||||
if params[:filesize]
|
||||
|
@ -142,10 +139,8 @@ module Ci
|
|||
require_gitlab_workhorse!
|
||||
not_allowed! unless Gitlab.config.artifacts.enabled
|
||||
build = Ci::Build.find_by_id(params[:id])
|
||||
not_found! unless build
|
||||
authenticate_build_token!(build)
|
||||
authenticate_build!(build)
|
||||
forbidden!('Build is not running!') unless build.running?
|
||||
forbidden!('Build has been erased!') if build.erased?
|
||||
|
||||
artifacts_upload_path = ArtifactUploader.artifacts_upload_path
|
||||
artifacts = uploaded_file(:file, artifacts_upload_path)
|
||||
|
@ -176,8 +171,7 @@ module Ci
|
|||
# GET /builds/:id/artifacts
|
||||
get ":id/artifacts" do
|
||||
build = Ci::Build.find_by_id(params[:id])
|
||||
not_found! unless build
|
||||
authenticate_build_token!(build)
|
||||
authenticate_build!(build)
|
||||
artifacts_file = build.artifacts_file
|
||||
|
||||
unless artifacts_file.file_storage?
|
||||
|
@ -202,8 +196,7 @@ module Ci
|
|||
# DELETE /builds/:id/artifacts
|
||||
delete ":id/artifacts" do
|
||||
build = Ci::Build.find_by_id(params[:id])
|
||||
not_found! unless build
|
||||
authenticate_build_token!(build)
|
||||
authenticate_build!(build)
|
||||
|
||||
build.erase_artifacts!
|
||||
end
|
||||
|
|
|
@ -13,8 +13,19 @@ module Ci
|
|||
forbidden! unless current_runner
|
||||
end
|
||||
|
||||
def authenticate_build_token!(build)
|
||||
forbidden! unless build_token_valid?(build)
|
||||
def authenticate_build!(build)
|
||||
validate_build!(build) do
|
||||
forbidden! unless build_token_valid?(build)
|
||||
end
|
||||
end
|
||||
|
||||
def validate_build!(build)
|
||||
not_found! unless build
|
||||
|
||||
yield if block_given?
|
||||
|
||||
forbidden!('Project has been deleted!') unless build.project
|
||||
forbidden!('Build has been erased!') if build.erased?
|
||||
end
|
||||
|
||||
def runner_registration_token_valid?
|
||||
|
|
|
@ -118,7 +118,7 @@ module Ci
|
|||
.merge(job_variables(name))
|
||||
|
||||
variables.map do |key, value|
|
||||
{ key: key, value: value, public: true }
|
||||
{ key: key.to_s, value: value, public: true }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
module Gitlab
|
||||
module BitbucketImport
|
||||
class Importer
|
||||
include Gitlab::ShellAdapter
|
||||
|
||||
LABELS = [{ title: 'bug', color: '#FF0000' },
|
||||
{ title: 'enhancement', color: '#428BCA' },
|
||||
{ title: 'proposal', color: '#69D100' },
|
||||
|
@ -18,6 +20,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def execute
|
||||
import_wiki
|
||||
import_issues
|
||||
import_pull_requests
|
||||
handle_errors
|
||||
|
@ -55,6 +58,16 @@ module Gitlab
|
|||
@repo ||= client.repo(project.import_source)
|
||||
end
|
||||
|
||||
def import_wiki
|
||||
return if project.wiki.repository_exists?
|
||||
|
||||
path_with_namespace = "#{project.path_with_namespace}.wiki"
|
||||
import_url = project.import_url.sub(/\.git\z/, ".git/wiki")
|
||||
gitlab_shell.import_repository(project.repository_storage_path, path_with_namespace, import_url)
|
||||
rescue StandardError => e
|
||||
errors << { type: :wiki, errors: e.message }
|
||||
end
|
||||
|
||||
def import_issues
|
||||
return unless repo.issues_enabled?
|
||||
|
||||
|
|
|
@ -22,9 +22,16 @@ module Gitlab
|
|||
import_type: 'bitbucket',
|
||||
import_source: repo.full_name,
|
||||
import_url: repo.clone_url(session_data[:token]),
|
||||
import_data: { credentials: session_data }
|
||||
import_data: { credentials: session_data },
|
||||
skip_wiki: skip_wiki
|
||||
).execute
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def skip_wiki
|
||||
repo.has_wiki?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -42,6 +42,10 @@ module Gitlab
|
|||
def find_by_iid(iid)
|
||||
collection.find_by(iid: iid)
|
||||
end
|
||||
|
||||
def presenter
|
||||
Gitlab::ChatCommands::Presenter.new
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,8 +22,6 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def match_command
|
||||
match = nil
|
||||
service = available_commands.find do |klass|
|
||||
|
@ -33,6 +31,8 @@ module Gitlab
|
|||
[service, match]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def help_messages
|
||||
available_commands.map(&:help_message)
|
||||
end
|
||||
|
@ -48,15 +48,15 @@ module Gitlab
|
|||
end
|
||||
|
||||
def help(messages)
|
||||
Mattermost::Presenter.help(messages, params[:command])
|
||||
presenter.help(messages, params[:command])
|
||||
end
|
||||
|
||||
def access_denied
|
||||
Mattermost::Presenter.access_denied
|
||||
presenter.access_denied
|
||||
end
|
||||
|
||||
def present(resource)
|
||||
Mattermost::Presenter.present(resource)
|
||||
presenter.present(resource)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,7 @@ module Gitlab
|
|||
include Gitlab::Routing.url_helpers
|
||||
|
||||
def self.match(text)
|
||||
/\Adeploy\s+(?<from>.*)\s+to+\s+(?<to>.*)\z/.match(text)
|
||||
/\Adeploy\s+(?<from>\S+.*)\s+to+\s+(?<to>\S+.*)\z/.match(text)
|
||||
end
|
||||
|
||||
def self.help_message
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module Mattermost
|
||||
class Presenter
|
||||
class << self
|
||||
include Gitlab::Routing.url_helpers
|
||||
module Gitlab
|
||||
module ChatCommands
|
||||
class Presenter
|
||||
include Gitlab::Routing
|
||||
|
||||
def authorize_chat_name(url)
|
||||
message = if url
|
||||
|
@ -64,7 +64,7 @@ module Mattermost
|
|||
def single_resource(resource)
|
||||
return error(resource) if resource.errors.any? || !resource.persisted?
|
||||
|
||||
message = "### #{title(resource)}"
|
||||
message = "#{title(resource)}:"
|
||||
message << "\n\n#{resource.description}" if resource.try(:description)
|
||||
|
||||
in_channel_response(message)
|
|
@ -17,6 +17,10 @@ module Gitlab
|
|||
'icon_status_manual'
|
||||
end
|
||||
|
||||
def group
|
||||
'manual'
|
||||
end
|
||||
|
||||
def has_action?
|
||||
can?(user, :update_build, subject)
|
||||
end
|
||||
|
|
|
@ -17,6 +17,10 @@ module Gitlab
|
|||
'icon_status_manual'
|
||||
end
|
||||
|
||||
def group
|
||||
'manual'
|
||||
end
|
||||
|
||||
def has_action?
|
||||
can?(user, :update_build, subject)
|
||||
end
|
||||
|
|
|
@ -22,15 +22,8 @@ module Gitlab
|
|||
raise NotImplementedError
|
||||
end
|
||||
|
||||
# Deprecation warning: this method is here because we need to maintain
|
||||
# backwards compatibility with legacy statuses. We often do something
|
||||
# like "ci-status ci-status-#{status}" to set CSS class.
|
||||
#
|
||||
# `to_s` method should be renamed to `group` at some point, after
|
||||
# phasing legacy satuses out.
|
||||
#
|
||||
def to_s
|
||||
self.class.name.demodulize.downcase.underscore
|
||||
def group
|
||||
self.class.name.demodulize.underscore
|
||||
end
|
||||
|
||||
def has_details?
|
||||
|
|
|
@ -17,7 +17,7 @@ module Gitlab
|
|||
'icon_status_warning'
|
||||
end
|
||||
|
||||
def to_s
|
||||
def group
|
||||
'success_with_warnings'
|
||||
end
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ module Gitlab
|
|||
|
||||
def valid?
|
||||
environment_variables.all? do |(name, value)|
|
||||
value.start_with?(project.repository.path_to_repo)
|
||||
value.to_s.start_with?(project.repository.path_to_repo)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -35,7 +35,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def environment_variables
|
||||
@environment_variables ||= env.slice(*ALLOWED_VARIABLES)
|
||||
@environment_variables ||= env.slice(*ALLOWED_VARIABLES).compact
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -120,7 +120,7 @@ module Gitlab
|
|||
members_mapper: members_mapper,
|
||||
user: @user,
|
||||
project_id: restored_project.id)
|
||||
end
|
||||
end.compact
|
||||
|
||||
relation_hash_list.is_a?(Array) ? relation_array : relation_array.first
|
||||
end
|
||||
|
|
|
@ -14,7 +14,7 @@ module Gitlab
|
|||
priorities: :label_priorities,
|
||||
label: :project_label }.freeze
|
||||
|
||||
USER_REFERENCES = %w[author_id assignee_id updated_by_id user_id created_by_id].freeze
|
||||
USER_REFERENCES = %w[author_id assignee_id updated_by_id user_id created_by_id merge_user_id].freeze
|
||||
|
||||
PROJECT_REFERENCES = %w[project_id source_project_id gl_project_id target_project_id].freeze
|
||||
|
||||
|
@ -40,6 +40,8 @@ module Gitlab
|
|||
# the relation_hash, updating references with new object IDs, mapping users using
|
||||
# the "members_mapper" object, also updating notes if required.
|
||||
def create
|
||||
return nil if unknown_service?
|
||||
|
||||
setup_models
|
||||
|
||||
generate_imported_object
|
||||
|
@ -99,6 +101,8 @@ module Gitlab
|
|||
def generate_imported_object
|
||||
if BUILD_MODELS.include?(@relation_name) # call #trace= method after assigning the other attributes
|
||||
trace = @relation_hash.delete('trace')
|
||||
@relation_hash.delete('token')
|
||||
|
||||
imported_object do |object|
|
||||
object.trace = trace
|
||||
object.commit_id = nil
|
||||
|
@ -215,6 +219,11 @@ module Gitlab
|
|||
existing_object
|
||||
end
|
||||
end
|
||||
|
||||
def unknown_service?
|
||||
@relation_name == :services && parsed_relation_hash['type'] &&
|
||||
!Object.const_defined?(parsed_relation_hash['type'])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
module Gitlab
|
||||
module Serialize
|
||||
module Ci
|
||||
# This serializer could make sure our YAML variables' keys and values
|
||||
# are always strings. This is more for legacy build data because
|
||||
# from now on we convert them into strings before saving to database.
|
||||
module Variables
|
||||
extend self
|
||||
|
||||
def load(string)
|
||||
return unless string
|
||||
|
||||
object = YAML.safe_load(string, [Symbol])
|
||||
|
||||
object.map do |variable|
|
||||
variable[:key] = variable[:key].to_s
|
||||
variable
|
||||
end
|
||||
end
|
||||
|
||||
def dump(object)
|
||||
YAML.dump(object)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,40 @@
|
|||
namespace :gitlab do
|
||||
namespace :ldap do
|
||||
desc 'GitLab | LDAP | Rename provider'
|
||||
task :rename_provider, [:old_provider, :new_provider] => :environment do |_, args|
|
||||
old_provider = args[:old_provider] ||
|
||||
prompt('What is the old provider? Ex. \'ldapmain\': '.color(:blue))
|
||||
new_provider = args[:new_provider] ||
|
||||
prompt('What is the new provider ID? Ex. \'ldapcustom\': '.color(:blue))
|
||||
puts '' # Add some separation in the output
|
||||
|
||||
identities = Identity.where(provider: old_provider)
|
||||
identity_count = identities.count
|
||||
|
||||
if identities.empty?
|
||||
puts "Found no user identities with '#{old_provider}' provider."
|
||||
puts 'Please check the provider name and try again.'
|
||||
exit 1
|
||||
end
|
||||
|
||||
plural_id_count = ActionController::Base.helpers.pluralize(identity_count, 'user')
|
||||
|
||||
unless ENV['force'] == 'yes'
|
||||
puts "#{plural_id_count} with provider '#{old_provider}' will be updated to '#{new_provider}'"
|
||||
puts 'If the new provider is incorrect, users will be unable to sign in'
|
||||
ask_to_continue
|
||||
puts ''
|
||||
end
|
||||
|
||||
updated_count = identities.update_all(provider: new_provider)
|
||||
|
||||
if updated_count == identity_count
|
||||
puts 'User identities were successfully updated'.color(:green)
|
||||
else
|
||||
plural_updated_count = ActionController::Base.helpers.pluralize(updated_count, 'user')
|
||||
puts 'Some user identities could not be updated'.color(:red)
|
||||
puts "Successfully updated #{plural_updated_count} out of #{plural_id_count} total"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -25,5 +25,10 @@ describe Projects::BlameController do
|
|||
let(:id) { 'master/files/ruby/popen.rb' }
|
||||
it { is_expected.to respond_with(:success) }
|
||||
end
|
||||
|
||||
context "invalid file" do
|
||||
let(:id) { 'master/files/ruby/missing_file.rb'}
|
||||
it { expect(response).to have_http_status(404) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue