diff options
102 files changed, 958 insertions, 638 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index fb13db4dd1c..786b0128aac 100644 --- a/CHANGELOG.md +++ b/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 diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION index ee74734aa22..627a3f43a64 100644 --- a/GITLAB_SHELL_VERSION +++ b/GITLAB_SHELL_VERSION @@ -1 +1 @@ -4.1.0 +4.1.1 diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index 57dabfe05e4..bb516b3d2df 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -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'); diff --git a/app/assets/javascripts/notifications_dropdown.js b/app/assets/javascripts/notifications_dropdown.js index 324b68a7efc..5d0d594073d 100644 --- a/app/assets/javascripts/notifications_dropdown.js +++ b/app/assets/javascripts/notifications_dropdown.js @@ -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'); } diff --git a/app/assets/stylesheets/framework/icons.scss b/app/assets/stylesheets/framework/icons.scss index 226bd2ead31..8624a25c052 100644 --- a/app/assets/stylesheets/framework/icons.scss +++ b/app/assets/stylesheets/framework/icons.scss @@ -49,3 +49,11 @@ fill: $gray-darkest; } } + +.ci-status-icon-manual { + color: $gl-text-color; + + svg { + fill: $gl-text-color; + } +} diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss index abfdd7a759d..7eb9962ba33 100644 --- a/app/assets/stylesheets/framework/mobile.scss +++ b/app/assets/stylesheets/framework/mobile.scss @@ -54,7 +54,7 @@ } // Display Star and Fork buttons without counters on mobile. - .project-action-buttons { + .project-repo-buttons { display: block; .count-buttons .btn { diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index d0c27d64239..460c5d995be 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -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; diff --git a/app/assets/stylesheets/pages/groups.scss b/app/assets/stylesheets/pages/groups.scss index a9af7af59e2..16bff5f1e03 100644 --- a/app/assets/stylesheets/pages/groups.scss +++ b/app/assets/stylesheets/pages/groups.scss @@ -27,12 +27,6 @@ } } -.group-buttons { - .notification-dropdown { - display: inline-block; - } -} - .groups-header { @media (min-width: $screen-sm-min) { .nav-links { diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss index be22e7bdc79..243c9153ded 100644 --- a/app/assets/stylesheets/pages/pipelines.scss +++ b/app/assets/stylesheets/pages/pipelines.scss @@ -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,30 +649,20 @@ .dropdown-build { color: $gl-text-color-light; - a.ci-action-icon-container { - padding: 0; - font-size: 11px; - float: right; - margin-top: 4px; - display: inline-block; - position: relative; - - i { - font-size: 11px; - margin-top: 0; - } - } - - &:hover { - background-color: $stage-hover-bg; - border-radius: 3px; - color: $gl-text-color; + .build-content { + width: 100%; } .ci-action-icon-container { + font-size: 11px; + position: absolute; + right: 4px; + i { width: 25px; height: 25px; + font-size: 11px; + margin-top: 0; &::before { top: 1px; @@ -682,6 +671,12 @@ } } + &:hover { + background-color: $stage-hover-bg; + border-radius: 3px; + color: $gl-text-color; + } + .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%; diff --git a/app/assets/stylesheets/pages/projects.scss b/app/assets/stylesheets/pages/projects.scss index 3b1b375133d..a443b6a37b3 100644 --- a/app/assets/stylesheets/pages/projects.scss +++ b/app/assets/stylesheets/pages/projects.scss @@ -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 { diff --git a/app/assets/stylesheets/pages/status.scss b/app/assets/stylesheets/pages/status.scss index f3b0608e545..055dacd81f4 100644 --- a/app/assets/stylesheets/pages/status.scss +++ b/app/assets/stylesheets/pages/status.scss @@ -1,5 +1,6 @@ .container-fluid { .ci-status { + display: inline-block; padding: 2px 7px; margin-right: 10px; border: 1px solid $gray-darker; @@ -15,8 +16,7 @@ height: 13px; width: 13px; position: relative; - top: 1px; - margin-right: 3px; + top: 2px; overflow: visible; } @@ -25,7 +25,7 @@ border-color: $gl-danger; &:not(span):hover { - background-color: rgba( $gl-danger, .07); + background-color: rgba($gl-danger, .07); } svg { @@ -39,7 +39,7 @@ border-color: $gl-success; &:not(span):hover { - background-color: rgba( $gl-success, .07); + background-color: rgba($gl-success, .07); } svg { @@ -52,7 +52,7 @@ border-color: $gl-info; &:not(span):hover { - background-color: rgba( $gl-info, .07); + background-color: rgba($gl-info, .07); } svg { @@ -66,7 +66,7 @@ border-color: $gl-gray; &:not(span):hover { - background-color: rgba( $gl-gray, .07); + background-color: rgba($gl-gray, .07); } svg { @@ -79,7 +79,7 @@ border-color: $gl-warning; &:not(span):hover { - background-color: rgba( $gl-warning, .07); + background-color: rgba($gl-warning, .07); } svg { @@ -92,7 +92,7 @@ border-color: $blue-normal; &:not(span):hover { - background-color: rgba( $blue-normal, .07); + background-color: rgba($blue-normal, .07); } svg { @@ -106,13 +106,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; + } + } } } diff --git a/app/assets/stylesheets/pages/tree.scss b/app/assets/stylesheets/pages/tree.scss index c0341db7289..cad4e149845 100644 --- a/app/assets/stylesheets/pages/tree.scss +++ b/app/assets/stylesheets/pages/tree.scss @@ -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; } } diff --git a/app/controllers/projects/blame_controller.rb b/app/controllers/projects/blame_controller.rb index f576d0be1fc..863a766a255 100644 --- a/app/controllers/projects/blame_controller.rb +++ b/app/controllers/projects/blame_controller.rb @@ -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 diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 591aba6bdc9..cb76cdf5981 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -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 diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index b7c775777c7..5ce20cc43d6 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -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? diff --git a/app/models/route.rb b/app/models/route.rb index d40214b9da6..caf596efa79 100644 --- a/app/models/route.rb +++ b/app/models/route.rb @@ -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)) diff --git a/app/views/ci/status/_badge.html.haml b/app/views/ci/status/_badge.html.haml index f2135af2686..601fb7f0f3f 100644 --- a/app/views/ci/status/_badge.html.haml +++ b/app/views/ci/status/_badge.html.haml @@ -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 diff --git a/app/views/ci/status/_graph_badge.html.haml b/app/views/ci/status/_graph_badge.html.haml index c7d04ab61e9..52b4d77d074 100644 --- a/app/views/ci/status/_graph_badge.html.haml +++ b/app/views/ci/status/_graph_badge.html.haml @@ -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, diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml index 5a04c3318cf..0d1f2b70018 100644 --- a/app/views/projects/_home_panel.html.haml +++ b/app/views/projects/_home_panel.html.haml @@ -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 diff --git a/app/views/projects/buttons/_download.html.haml b/app/views/projects/buttons/_download.html.haml index 40bfa01a45a..324a7f8cd3f 100644 --- a/app/views/projects/buttons/_download.html.haml +++ b/app/views/projects/buttons/_download.html.haml @@ -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") diff --git a/app/views/projects/buttons/_dropdown.html.haml b/app/views/projects/buttons/_dropdown.html.haml index d3ccebbe290..f5659be25f0 100644 --- a/app/views/projects/buttons/_dropdown.html.haml +++ b/app/views/projects/buttons/_dropdown.html.haml @@ -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") diff --git a/app/views/projects/buttons/_koding.html.haml b/app/views/projects/buttons/_koding.html.haml index fdc80d44253..5d9a776da89 100644 --- a/app/views/projects/buttons/_koding.html.haml +++ b/app/views/projects/buttons/_koding.html.haml @@ -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) diff --git a/app/views/projects/show.html.haml b/app/views/projects/show.html.haml index c50093cf47c..8a214e1de58 100644 --- a/app/views/projects/show.html.haml +++ b/app/views/projects/show.html.haml @@ -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 - - %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' + Set up CI + - if koding_enabled? && @repository.koding_yml.blank? + %li.missing + = link_to 'Set up Koding', add_koding_stack_path(@project) - .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 diff --git a/app/views/projects/stage/_graph.html.haml b/app/views/projects/stage/_graph.html.haml index b70b574e687..6919b210a00 100644 --- a/app/views/projects/stage/_graph.html.haml +++ b/app/views/projects/stage/_graph.html.haml @@ -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 + diff --git a/app/views/projects/stage/_in_stage_group.html.haml b/app/views/projects/stage/_in_stage_group.html.haml index b03837d1211..b15f7eaeab2 100644 --- a/app/views/projects/stage/_in_stage_group.html.haml +++ b/app/views/projects/stage/_in_stage_group.html.haml @@ -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 diff --git a/app/views/shared/members/_access_request_buttons.html.haml b/app/views/shared/members/_access_request_buttons.html.haml index e166dfab710..fb795ad1c72 100644 --- a/app/views/shared/members/_access_request_buttons.html.haml +++ b/app/views/shared/members/_access_request_buttons.html.haml @@ -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' diff --git a/app/views/shared/notifications/_button.html.haml b/app/views/shared/notifications/_button.html.haml index fbad0d05de3..1d072c16b32 100644 --- a/app/views/shared/notifications/_button.html.haml +++ b/app/views/shared/notifications/_button.html.haml @@ -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" diff --git a/changelogs/unreleased/23305-leave-project-and-leave-group-should-be-buttons.yml b/changelogs/unreleased/23305-leave-project-and-leave-group-should-be-buttons.yml deleted file mode 100644 index 99dbe4a32a0..00000000000 --- a/changelogs/unreleased/23305-leave-project-and-leave-group-should-be-buttons.yml +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Moved Leave Project and Leave Group buttons to access_request_buttons from - the settings dropdown -merge_request: 7600 -author: diff --git a/changelogs/unreleased/25171-fix-mr-features-settings-hidden-when-builds-are-disabled.yml b/changelogs/unreleased/25171-fix-mr-features-settings-hidden-when-builds-are-disabled.yml deleted file mode 100644 index a7576e2cbdb..00000000000 --- a/changelogs/unreleased/25171-fix-mr-features-settings-hidden-when-builds-are-disabled.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: Remove wrong '.builds-feature' class from the MR settings fieldset -merge_request: 7930 -author: diff --git a/changelogs/unreleased/25740-fix-new-branch-button-padding.yml b/changelogs/unreleased/25740-fix-new-branch-button-padding.yml new file mode 100644 index 00000000000..7da8f9357a7 --- /dev/null +++ b/changelogs/unreleased/25740-fix-new-branch-button-padding.yml @@ -0,0 +1,4 @@ +--- +title: Made the padding on the plus button in the breadcrumb menu even +merge_request: +author: Ryan Harris diff --git a/changelogs/unreleased/dz-fix-route-rename.yml b/changelogs/unreleased/dz-fix-route-rename.yml new file mode 100644 index 00000000000..a649fb169a5 --- /dev/null +++ b/changelogs/unreleased/dz-fix-route-rename.yml @@ -0,0 +1,4 @@ +--- +title: Fix Route#rename_children behavior +merge_request: +author: diff --git a/changelogs/unreleased/fix-blame-500.yml b/changelogs/unreleased/fix-blame-500.yml new file mode 100644 index 00000000000..379d81aaa44 --- /dev/null +++ b/changelogs/unreleased/fix-blame-500.yml @@ -0,0 +1,4 @@ +--- +title: Fix blame 500 error on invalid path. +merge_request: 25761 +author: Jeff Stubler diff --git a/changelogs/unreleased/fix-import-export-build-token.yml b/changelogs/unreleased/fix-import-export-build-token.yml new file mode 100644 index 00000000000..622487e6829 --- /dev/null +++ b/changelogs/unreleased/fix-import-export-build-token.yml @@ -0,0 +1,4 @@ +--- +title: Fix Import/Export duplicated builds error +merge_request: +author: diff --git a/changelogs/unreleased/fix-import-export-ee-services.yml b/changelogs/unreleased/fix-import-export-ee-services.yml new file mode 100644 index 00000000000..c0aacbc96f8 --- /dev/null +++ b/changelogs/unreleased/fix-import-export-ee-services.yml @@ -0,0 +1,4 @@ +--- +title: Fix missing service error importing from EE to CE +merge_request: 8144 +author: diff --git a/changelogs/unreleased/fix-import-export-mr-error.yml b/changelogs/unreleased/fix-import-export-mr-error.yml new file mode 100644 index 00000000000..e1137bca131 --- /dev/null +++ b/changelogs/unreleased/fix-import-export-mr-error.yml @@ -0,0 +1,4 @@ +--- +title: Fix Import/Export merge requests error while importing +merge_request: +author: diff --git a/changelogs/unreleased/fix-milestone-summary.yml b/changelogs/unreleased/fix-milestone-summary.yml deleted file mode 100644 index 3045a15054c..00000000000 --- a/changelogs/unreleased/fix-milestone-summary.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: Displays milestone remaining days only when it's present -merge_request: -author: diff --git a/changelogs/unreleased/fix-yaml-variables.yml b/changelogs/unreleased/fix-yaml-variables.yml new file mode 100644 index 00000000000..3abff1e3b08 --- /dev/null +++ b/changelogs/unreleased/fix-yaml-variables.yml @@ -0,0 +1,4 @@ +--- +title: Convert CI YAML variables keys into strings +merge_request: 8088 +author: diff --git a/changelogs/unreleased/group-members-in-project-members-view.yml b/changelogs/unreleased/group-members-in-project-members-view.yml deleted file mode 100644 index 415e2b6b1e2..00000000000 --- a/changelogs/unreleased/group-members-in-project-members-view.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: Shows group members in project members list -merge_request: -author: diff --git a/changelogs/unreleased/issue_24020.yml b/changelogs/unreleased/issue_24020.yml deleted file mode 100644 index 87310b75296..00000000000 --- a/changelogs/unreleased/issue_24020.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: "fix display hook error message" -merge_request: 7775 -author: basyura diff --git a/changelogs/unreleased/issue_25030.yml b/changelogs/unreleased/issue_25030.yml deleted file mode 100644 index e18b8d6a79b..00000000000 --- a/changelogs/unreleased/issue_25030.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: Allow branch names with dots on API endpoint -merge_request: -author: diff --git a/changelogs/unreleased/ldap_maint_task.yml b/changelogs/unreleased/ldap_maint_task.yml new file mode 100644 index 00000000000..8acffba0ce5 --- /dev/null +++ b/changelogs/unreleased/ldap_maint_task.yml @@ -0,0 +1,4 @@ +--- +title: Add LDAP Rake task to rename a provider +merge_request: 2181 +author: diff --git a/changelogs/unreleased/leave-project-btn.yml b/changelogs/unreleased/leave-project-btn.yml new file mode 100644 index 00000000000..2aa553d7b97 --- /dev/null +++ b/changelogs/unreleased/leave-project-btn.yml @@ -0,0 +1,4 @@ +--- +title: Move all action buttons to project header +merge_request: +author: diff --git a/changelogs/unreleased/pipeline-build-hitbox.yml b/changelogs/unreleased/pipeline-build-hitbox.yml new file mode 100644 index 00000000000..051b538a9a3 --- /dev/null +++ b/changelogs/unreleased/pipeline-build-hitbox.yml @@ -0,0 +1,4 @@ +--- +title: Make CI badge hitboxes match parent +merge_request: +author: diff --git a/changelogs/unreleased/timeago-perf-fix.yml b/changelogs/unreleased/timeago-perf-fix.yml deleted file mode 100644 index 265e7db29a9..00000000000 --- a/changelogs/unreleased/timeago-perf-fix.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: Fixed timeago re-rendering every timeago -merge_request: -author: diff --git a/changelogs/unreleased/unescape-relative-path.yml b/changelogs/unreleased/unescape-relative-path.yml deleted file mode 100644 index 755b0379a16..00000000000 --- a/changelogs/unreleased/unescape-relative-path.yml +++ /dev/null @@ -1,4 +0,0 @@ ---- -title: Avoid escaping relative links in Markdown twice -merge_request: 7940 -author: winniehell diff --git a/db/fixtures/development/14_pipelines.rb b/db/fixtures/development/14_pipelines.rb index 19e001854d2..be95d788850 100644 --- a/db/fixtures/development/14_pipelines.rb +++ b/db/fixtures/development/14_pipelines.rb @@ -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 diff --git a/doc/administration/raketasks/check.md b/doc/administration/raketasks/check.md index d1d2fed4861..c8b5434c068 100644 --- a/doc/administration/raketasks/check.md +++ b/doc/administration/raketasks/check.md @@ -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. diff --git a/doc/administration/raketasks/ldap.md b/doc/administration/raketasks/ldap.md new file mode 100644 index 00000000000..91fc0133d56 --- /dev/null +++ b/doc/administration/raketasks/ldap.md @@ -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 +``` diff --git a/doc/development/performance.md b/doc/development/performance.md index 5c43ae7b79a..f936a49a2aa 100644 --- a/doc/development/performance.md +++ b/doc/development/performance.md @@ -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 diff --git a/doc/integration/bitbucket.md b/doc/integration/bitbucket.md index 5df6e103f42..1dfc985eaea 100644 --- a/doc/integration/bitbucket.md +++ b/doc/integration/bitbucket.md @@ -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) diff --git a/doc/integration/img/bitbucket_oauth_settings_page.png b/doc/integration/img/bitbucket_oauth_settings_page.png Binary files differindex 21ce82a6074..3e6dea6cfe9 100644 --- a/doc/integration/img/bitbucket_oauth_settings_page.png +++ b/doc/integration/img/bitbucket_oauth_settings_page.png diff --git a/doc/raketasks/README.md b/doc/raketasks/README.md index a49c43b8ef2..2b81ebc9c59 100644 --- a/doc/raketasks/README.md +++ b/doc/raketasks/README.md @@ -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 diff --git a/doc/update/8.14-to-8.15.md b/doc/update/8.14-to-8.15.md index 4eacab0c890..8d4bfd913bd 100644 --- a/doc/update/8.14-to-8.15.md +++ b/doc/update/8.14-to-8.15.md @@ -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 diff --git a/doc/workflow/importing/import_projects_from_bitbucket.md b/doc/workflow/importing/import_projects_from_bitbucket.md index b6d47e5afa2..97380bce172 100644 --- a/doc/workflow/importing/import_projects_from_bitbucket.md +++ b/doc/workflow/importing/import_projects_from_bitbucket.md @@ -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.
diff --git a/features/admin/appearance.feature b/features/admin/appearance.feature deleted file mode 100644 index 5c1dd7531c1..00000000000 --- a/features/admin/appearance.feature +++ /dev/null @@ -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 diff --git a/features/admin/broadcast_messages.feature b/features/admin/broadcast_messages.feature deleted file mode 100644 index 4f9c651561e..00000000000 --- a/features/admin/broadcast_messages.feature +++ /dev/null @@ -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 diff --git a/features/admin/labels.feature b/features/admin/labels.feature deleted file mode 100644 index 1af0e700bd4..00000000000 --- a/features/admin/labels.feature +++ /dev/null @@ -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 diff --git a/features/steps/admin/appearance.rb b/features/steps/admin/appearance.rb deleted file mode 100644 index 0d1be46d11d..00000000000 --- a/features/steps/admin/appearance.rb +++ /dev/null @@ -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 diff --git a/features/steps/admin/broadcast_messages.rb b/features/steps/admin/broadcast_messages.rb deleted file mode 100644 index af2b4a29313..00000000000 --- a/features/steps/admin/broadcast_messages.rb +++ /dev/null @@ -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 diff --git a/features/steps/admin/labels.rb b/features/steps/admin/labels.rb deleted file mode 100644 index 55ddcc25085..00000000000 --- a/features/steps/admin/labels.rb +++ /dev/null @@ -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 diff --git a/features/steps/shared/paths.rb b/features/steps/shared/paths.rb index a78d0a775ba..15b81fa529b 100644 --- a/features/steps/shared/paths.rb +++ b/features/steps/shared/paths.rb @@ -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 diff --git a/lib/bitbucket/representation/repo.rb b/lib/bitbucket/representation/repo.rb index 8969ecd1c19..423eff8f2a5 100644 --- a/lib/bitbucket/representation/repo.rb +++ b/lib/bitbucket/representation/repo.rb @@ -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 diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index fef652cb975..7463bd719d5 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -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 diff --git a/lib/gitlab/bitbucket_import/importer.rb b/lib/gitlab/bitbucket_import/importer.rb index 7d2f92d577a..44323b47dca 100644 --- a/lib/gitlab/bitbucket_import/importer.rb +++ b/lib/gitlab/bitbucket_import/importer.rb @@ -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? diff --git a/lib/gitlab/bitbucket_import/project_creator.rb b/lib/gitlab/bitbucket_import/project_creator.rb index eb03882ab26..d94f70fd1fb 100644 --- a/lib/gitlab/bitbucket_import/project_creator.rb +++ b/lib/gitlab/bitbucket_import/project_creator.rb @@ -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 diff --git a/lib/gitlab/ci/status/build/play.rb b/lib/gitlab/ci/status/build/play.rb index 5c506e6d59f..1bf949c96dd 100644 --- a/lib/gitlab/ci/status/build/play.rb +++ b/lib/gitlab/ci/status/build/play.rb @@ -17,6 +17,10 @@ module Gitlab 'icon_status_manual' end + def group + 'manual' + end + def has_action? can?(user, :update_build, subject) end diff --git a/lib/gitlab/ci/status/build/stop.rb b/lib/gitlab/ci/status/build/stop.rb index f8ffa95cde4..e1dfdb76d41 100644 --- a/lib/gitlab/ci/status/build/stop.rb +++ b/lib/gitlab/ci/status/build/stop.rb @@ -17,6 +17,10 @@ module Gitlab 'icon_status_manual' end + def group + 'manual' + end + def has_action? can?(user, :update_build, subject) end diff --git a/lib/gitlab/ci/status/core.rb b/lib/gitlab/ci/status/core.rb index 46fef8262c1..73b6ab5a635 100644 --- a/lib/gitlab/ci/status/core.rb +++ b/lib/gitlab/ci/status/core.rb @@ -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? diff --git a/lib/gitlab/ci/status/pipeline/success_with_warnings.rb b/lib/gitlab/ci/status/pipeline/success_with_warnings.rb index a7c98f9e909..24bf8b869e0 100644 --- a/lib/gitlab/ci/status/pipeline/success_with_warnings.rb +++ b/lib/gitlab/ci/status/pipeline/success_with_warnings.rb @@ -17,7 +17,7 @@ module Gitlab 'icon_status_warning' end - def to_s + def group 'success_with_warnings' end diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index c551321c18d..cda6ddf0443 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -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 diff --git a/lib/gitlab/import_export/relation_factory.rb b/lib/gitlab/import_export/relation_factory.rb index a0e80fccad9..65b229ca8ff 100644 --- a/lib/gitlab/import_export/relation_factory.rb +++ b/lib/gitlab/import_export/relation_factory.rb @@ -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 diff --git a/lib/gitlab/serialize/ci/variables.rb b/lib/gitlab/serialize/ci/variables.rb new file mode 100644 index 00000000000..3a9443bfcd9 --- /dev/null +++ b/lib/gitlab/serialize/ci/variables.rb @@ -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 diff --git a/lib/tasks/gitlab/ldap.rake b/lib/tasks/gitlab/ldap.rake new file mode 100644 index 00000000000..c66a2a263dc --- /dev/null +++ b/lib/tasks/gitlab/ldap.rake @@ -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 diff --git a/spec/controllers/projects/blame_controller_spec.rb b/spec/controllers/projects/blame_controller_spec.rb index 25f06299a29..4402ca43c65 100644 --- a/spec/controllers/projects/blame_controller_spec.rb +++ b/spec/controllers/projects/blame_controller_spec.rb @@ -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 diff --git a/spec/factories/ci/builds.rb b/spec/factories/ci/builds.rb index 62466c06194..0397d5d4001 100644 --- a/spec/factories/ci/builds.rb +++ b/spec/factories/ci/builds.rb @@ -22,7 +22,7 @@ FactoryGirl.define do yaml_variables do [ - { key: :DB_NAME, value: 'postgres', public: true } + { key: 'DB_NAME', value: 'postgres', public: true } ] end diff --git a/spec/features/admin/admin_appearance_spec.rb b/spec/features/admin/admin_appearance_spec.rb new file mode 100644 index 00000000000..96d715ef383 --- /dev/null +++ b/spec/features/admin/admin_appearance_spec.rb @@ -0,0 +1,76 @@ +require 'spec_helper' + +feature 'Admin Appearance', feature: true do + let!(:appearance) { create(:appearance) } + + scenario 'Create new appearance' do + login_as :admin + visit admin_appearances_path + + fill_in 'appearance_title', with: 'MyCompany' + fill_in 'appearance_description', with: 'dev server' + click_button 'Save' + + expect(current_path).to eq admin_appearances_path + expect(page).to have_content 'Appearance settings' + + 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 + + scenario 'Preview appearance' do + login_as :admin + + visit admin_appearances_path + click_link "Preview" + + expect_page_has_custom_appearance(appearance) + end + + scenario 'Custom sign-in page' do + visit new_user_session_path + expect_page_has_custom_appearance(appearance) + end + + scenario 'Appearance logo' do + login_as :admin + visit admin_appearances_path + + attach_file(:appearance_logo, logo_fixture) + click_button 'Save' + expect(page).to have_css(logo_selector) + + click_link 'Remove logo' + expect(page).not_to have_css(logo_selector) + end + + scenario 'Header logos' do + login_as :admin + visit admin_appearances_path + + attach_file(:appearance_header_logo, logo_fixture) + click_button 'Save' + expect(page).to have_css(header_logo_selector) + + click_link 'Remove header logo' + expect(page).not_to have_css(header_logo_selector) + end + + def expect_page_has_custom_appearance(appearance) + expect(page).to have_content appearance.title + expect(page).to have_content appearance.description + end + + def logo_selector + '//img[@src^="/uploads/appearance/logo"]' + end + + def header_logo_selector + '//img[@src^="/uploads/appearance/header_logo"]' + end + + def logo_fixture + Rails.root.join('spec', 'fixtures', 'dk.png') + end +end diff --git a/spec/features/admin/admin_broadcast_messages_spec.rb b/spec/features/admin/admin_broadcast_messages_spec.rb new file mode 100644 index 00000000000..bc957ec72e1 --- /dev/null +++ b/spec/features/admin/admin_broadcast_messages_spec.rb @@ -0,0 +1,51 @@ +require 'spec_helper' + +feature 'Admin Broadcast Messages', feature: true do + before do + login_as :admin + create(:broadcast_message, :expired, message: 'Migration to new server') + visit admin_broadcast_messages_path + end + + scenario 'See broadcast messages list' do + expect(page).to have_content 'Migration to new server' + end + + scenario 'Create a 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' + + expect(current_path).to eq admin_broadcast_messages_path + 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 + + scenario 'Edit an existing broadcast message' do + click_link 'Edit' + fill_in 'broadcast_message_message', with: 'Application update RIGHT NOW' + click_button 'Update broadcast message' + + expect(current_path).to eq admin_broadcast_messages_path + expect(page).to have_content 'Application update RIGHT NOW' + end + + scenario 'Remove an existing broadcast message' do + click_link 'Remove' + + expect(current_path).to eq admin_broadcast_messages_path + expect(page).not_to have_content 'Migration to new server' + end + + scenario 'Live preview a customized broadcast message', js: true do + fill_in 'broadcast_message_message', with: "Live **Markdown** previews. :tada:" + + page.within('.broadcast-message-preview') do + expect(page).to have_selector('strong', text: 'Markdown') + expect(page).to have_selector('img.emoji') + end + end +end diff --git a/spec/features/admin/admin_labels_spec.rb b/spec/features/admin/admin_labels_spec.rb new file mode 100644 index 00000000000..eaa42aad0a7 --- /dev/null +++ b/spec/features/admin/admin_labels_spec.rb @@ -0,0 +1,99 @@ +require 'spec_helper' + +RSpec.describe 'admin issues labels' do + include WaitForAjax + + let!(:bug_label) { Label.create(title: 'bug', template: true) } + let!(:feature_label) { Label.create(title: 'feature', template: true) } + + before do + login_as :admin + end + + describe 'list' do + before do + visit admin_labels_path + end + + it 'renders labels list' do + page.within '.manage-labels-list' do + expect(page).to have_content('bug') + expect(page).to have_content('feature') + end + end + + it 'deletes label' do + page.within "#label_#{bug_label.id}" do + click_link 'Delete' + end + + page.within '.manage-labels-list' do + expect(page).not_to have_content('bug') + end + end + + it 'deletes all labels', js: true do + page.within '.labels' do + page.all('.btn-remove').each do |remove| + wait_for_ajax + remove.click + end + end + + page.within '.manage-labels-list' do + expect(page).not_to have_content('bug') + expect(page).not_to have_content('feature_label') + end + end + end + + describe 'create' do + before do + visit new_admin_label_path + end + + it 'creates new label' do + fill_in 'Title', with: 'support' + fill_in 'Background color', with: '#F95610' + click_button 'Save' + + page.within '.manage-labels-list' do + expect(page).to have_content('support') + end + end + + it 'does not creates label with invalid color' do + fill_in 'Title', with: 'support' + fill_in 'Background color', with: '#12' + click_button 'Save' + + page.within '.label-form' do + expect(page).to have_content('Color must be a valid color code') + end + end + + it 'does not creates label if label already exists' do + fill_in 'Title', with: 'bug' + fill_in 'Background color', with: '#F95610' + click_button 'Save' + + page.within '.label-form' do + expect(page).to have_content 'Title has already been taken' + end + end + end + + describe 'edit' do + it 'changes bug label' do + visit edit_admin_label_path(bug_label) + + fill_in 'Title', with: 'fix' + fill_in 'Background color', with: '#F15610' + click_button 'Save' + + page.within '.manage-labels-list' do + expect(page).to have_content('fix') + end + end + end +end diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb index 0a77eaa123c..1210e2745db 100644 --- a/spec/features/projects/pipelines/pipeline_spec.rb +++ b/spec/features/projects/pipelines/pipeline_spec.rb @@ -19,7 +19,7 @@ describe "Pipelines", feature: true, js: true do @success = create(:ci_build, :success, pipeline: pipeline, stage: 'build', name: 'build') @failed = create(:ci_build, :failed, pipeline: pipeline, stage: 'test', name: 'test', commands: 'test') @running = create(:ci_build, :running, pipeline: pipeline, stage: 'deploy', name: 'deploy') - @manual = create(:ci_build, :manual, pipeline: pipeline, stage: 'deploy', name: 'manual build') + @manual = create(:ci_build, :manual, pipeline: pipeline, stage: 'deploy', name: 'manual-build') @external = create(:generic_commit_status, status: 'success', pipeline: pipeline, name: 'jenkins', stage: 'external') end @@ -41,37 +41,34 @@ describe "Pipelines", feature: true, js: true do describe 'pipeline graph' do context 'when pipeline has running builds' do it 'shows a running icon and a cancel action for the running build' do - page.within('a[data-title="deploy - running"]') do + page.within('#ci-badge-deploy') do expect(page).to have_selector('.ci-status-icon-running') - expect(page).to have_content('deploy') - end - - page.within('a[data-title="deploy - running"] + .ci-action-icon-container') do expect(page).to have_selector('.ci-action-icon-container .fa-ban') + expect(page).to have_content('deploy') end end it 'should be possible to cancel the running build' do - find('a[data-title="deploy - running"] + .ci-action-icon-container').trigger('click') + find('#ci-badge-deploy .ci-action-icon-container').trigger('click') expect(page).not_to have_content('Cancel running') end end context 'when pipeline has successful builds' do - it 'shows the success icon and a retry action for the successfull build' do - page.within('a[data-title="build - passed"]') do + it 'shows the success icon and a retry action for the successful build' do + page.within('#ci-badge-build') do expect(page).to have_selector('.ci-status-icon-success') expect(page).to have_content('build') end - page.within('a[data-title="build - passed"] + .ci-action-icon-container') do + page.within('#ci-badge-build .ci-action-icon-container') do expect(page).to have_selector('.ci-action-icon-container .fa-refresh') end end it 'should be possible to retry the success build' do - find('a[data-title="build - passed"] + .ci-action-icon-container').trigger('click') + find('#ci-badge-build .ci-action-icon-container').trigger('click') expect(page).not_to have_content('Retry build') end @@ -79,18 +76,18 @@ describe "Pipelines", feature: true, js: true do context 'when pipeline has failed builds' do it 'shows the failed icon and a retry action for the failed build' do - page.within('a[data-title="test - failed"]') do + page.within('#ci-badge-test') do expect(page).to have_selector('.ci-status-icon-failed') expect(page).to have_content('test') end - page.within('a[data-title="test - failed"] + .ci-action-icon-container') do + page.within('#ci-badge-test .ci-action-icon-container') do expect(page).to have_selector('.ci-action-icon-container .fa-refresh') end end it 'should be possible to retry the failed build' do - find('a[data-title="test - failed"] + .ci-action-icon-container').trigger('click') + find('#ci-badge-test .ci-action-icon-container').trigger('click') expect(page).not_to have_content('Retry build') end @@ -98,18 +95,18 @@ describe "Pipelines", feature: true, js: true do context 'when pipeline has manual builds' do it 'shows the skipped icon and a play action for the manual build' do - page.within('a[data-title="manual build - manual play action"]') do - expect(page).to have_selector('.ci-status-icon-skipped') + page.within('#ci-badge-manual-build') do + expect(page).to have_selector('.ci-status-icon-manual') expect(page).to have_content('manual') end - page.within('a[data-title="manual build - manual play action"] + .ci-action-icon-container') do + page.within('#ci-badge-manual-build .ci-action-icon-container') do expect(page).to have_selector('.ci-action-icon-container .fa-play') end end it 'should be possible to play the manual build' do - find('a[data-title="manual build - manual play action"] + .ci-action-icon-container').trigger('click') + find('#ci-badge-manual-build .ci-action-icon-container').trigger('click') expect(page).not_to have_content('Play build') end @@ -167,7 +164,7 @@ describe "Pipelines", feature: true, js: true do @success = create(:ci_build, :success, pipeline: pipeline, stage: 'build', name: 'build') @failed = create(:ci_build, :failed, pipeline: pipeline, stage: 'test', name: 'test', commands: 'test') @running = create(:ci_build, :running, pipeline: pipeline, stage: 'deploy', name: 'deploy') - @manual = create(:ci_build, :manual, pipeline: pipeline, stage: 'deploy', name: 'manual build') + @manual = create(:ci_build, :manual, pipeline: pipeline, stage: 'deploy', name: 'manual-build') @external = create(:generic_commit_status, status: 'success', pipeline: pipeline, name: 'jenkins', stage: 'external') end diff --git a/spec/javascripts/fixtures/pipeline_graph.html.haml b/spec/javascripts/fixtures/pipeline_graph.html.haml index deca50ceaa7..c0b5ab4411e 100644 --- a/spec/javascripts/fixtures/pipeline_graph.html.haml +++ b/spec/javascripts/fixtures/pipeline_graph.html.haml @@ -8,8 +8,7 @@ %ul %li.build .curve - .build-content - %a - %svg - .ci-status-text - stop_review + %a + %svg + .ci-status-text + stop_review diff --git a/spec/lib/bitbucket/representation/repo_spec.rb b/spec/lib/bitbucket/representation/repo_spec.rb new file mode 100644 index 00000000000..adcd978e1b3 --- /dev/null +++ b/spec/lib/bitbucket/representation/repo_spec.rb @@ -0,0 +1,49 @@ +require 'spec_helper' + +describe Bitbucket::Representation::Repo do + describe '#has_wiki?' do + it { expect(described_class.new({ 'has_wiki' => false }).has_wiki?).to be_falsey } + it { expect(described_class.new({ 'has_wiki' => true }).has_wiki?).to be_truthy } + end + + describe '#name' do + it { expect(described_class.new({ 'name' => 'test' }).name).to eq('test') } + end + + describe '#valid?' do + it { expect(described_class.new({ 'scm' => 'hg' }).valid?).to be_falsey } + it { expect(described_class.new({ 'scm' => 'git' }).valid?).to be_truthy } + end + + describe '#full_name' do + it { expect(described_class.new({ 'full_name' => 'test_full' }).full_name).to eq('test_full') } + end + + describe '#description' do + it { expect(described_class.new({ 'description' => 'desc' }).description).to eq('desc') } + end + + describe '#issues_enabled?' do + it { expect(described_class.new({ 'has_issues' => false }).issues_enabled?).to be_falsey } + it { expect(described_class.new({ 'has_issues' => true }).issues_enabled?).to be_truthy } + end + + describe '#owner_and_slug' do + it { expect(described_class.new({ 'full_name' => 'ben/test' }).owner_and_slug).to eq(['ben', 'test']) } + end + + describe '#owner' do + it { expect(described_class.new({ 'full_name' => 'ben/test' }).owner).to eq('ben') } + end + + describe '#slug' do + it { expect(described_class.new({ 'full_name' => 'ben/test' }).slug).to eq('test') } + end + + describe '#clone_url' do + it 'builds url' do + data = { 'links' => { 'clone' => [ { 'name' => 'https', 'href' => 'https://bibucket.org/test/test.git' }] } } + expect(described_class.new(data).clone_url('abc')).to eq('https://x-token-auth:abc@bibucket.org/test/test.git') + end + end +end diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb index ff5dcc06ab3..62d68721574 100644 --- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb @@ -483,7 +483,7 @@ module Ci context 'when global variables are defined' do let(:variables) do - { VAR1: 'value1', VAR2: 'value2' } + { 'VAR1' => 'value1', 'VAR2' => 'value2' } end let(:config) do { @@ -495,18 +495,18 @@ module Ci it 'returns global variables' do expect(subject).to contain_exactly( - { key: :VAR1, value: 'value1', public: true }, - { key: :VAR2, value: 'value2', public: true } + { key: 'VAR1', value: 'value1', public: true }, + { key: 'VAR2', value: 'value2', public: true } ) end end context 'when job and global variables are defined' do let(:global_variables) do - { VAR1: 'global1', VAR3: 'global3' } + { 'VAR1' => 'global1', 'VAR3' => 'global3' } end let(:job_variables) do - { VAR1: 'value1', VAR2: 'value2' } + { 'VAR1' => 'value1', 'VAR2' => 'value2' } end let(:config) do { @@ -518,9 +518,9 @@ module Ci it 'returns all unique variables' do expect(subject).to contain_exactly( - { key: :VAR3, value: 'global3', public: true }, - { key: :VAR1, value: 'value1', public: true }, - { key: :VAR2, value: 'value2', public: true } + { key: 'VAR3', value: 'global3', public: true }, + { key: 'VAR1', value: 'value1', public: true }, + { key: 'VAR2', value: 'value2', public: true } ) end end @@ -535,13 +535,13 @@ module Ci context 'when syntax is correct' do let(:variables) do - { VAR1: 'value1', VAR2: 'value2' } + { 'VAR1' => 'value1', 'VAR2' => 'value2' } end it 'returns job variables' do expect(subject).to contain_exactly( - { key: :VAR1, value: 'value1', public: true }, - { key: :VAR2, value: 'value2', public: true } + { key: 'VAR1', value: 'value1', public: true }, + { key: 'VAR2', value: 'value2', public: true } ) end end @@ -549,7 +549,7 @@ module Ci context 'when syntax is incorrect' do context 'when variables defined but invalid' do let(:variables) do - [ :VAR1, 'value1', :VAR2, 'value2' ] + [ 'VAR1', 'value1', 'VAR2', 'value2' ] end it 'raises error' do diff --git a/spec/lib/gitlab/bitbucket_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importer_spec.rb index 53f3c73ade4..72b1ba36b58 100644 --- a/spec/lib/gitlab/bitbucket_import/importer_spec.rb +++ b/spec/lib/gitlab/bitbucket_import/importer_spec.rb @@ -69,6 +69,9 @@ describe Gitlab::BitbucketImport::Importer, lib: true do context 'issues statuses' do before do + # HACK: Bitbucket::Representation.const_get('Issue') seems to return ::Issue without this + Bitbucket::Representation::Issue.new({}) + stub_request( :get, "https://api.bitbucket.org/2.0/repositories/#{project_identifier}" @@ -108,13 +111,16 @@ describe Gitlab::BitbucketImport::Importer, lib: true do body: {}.to_json) end - it 'map statuses to open or closed' do - # HACK: Bitbucket::Representation.const_get('Issue') seems to return ::Issue without this - Bitbucket::Representation::Issue.new({}) + it 'maps statuses to open or closed' do importer.execute expect(project.issues.where(state: "closed").size).to eq(5) expect(project.issues.where(state: "opened").size).to eq(2) end + + it 'calls import_wiki' do + expect(importer).to receive(:import_wiki) + importer.execute + end end end diff --git a/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb b/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb index b6d052a4612..773d0d4d288 100644 --- a/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb +++ b/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb @@ -11,7 +11,8 @@ describe Gitlab::BitbucketImport::ProjectCreator, lib: true do owner: "asd", full_name: 'Vim repo', visibility_level: Gitlab::VisibilityLevel::PRIVATE, - clone_url: 'ssh://git@bitbucket.org/asd/vim.git') + clone_url: 'ssh://git@bitbucket.org/asd/vim.git', + has_wiki?: false) end let(:namespace){ create(:group, owner: user) } diff --git a/spec/lib/gitlab/ci/status/build/cancelable_spec.rb b/spec/lib/gitlab/ci/status/build/cancelable_spec.rb index 9376bce17a1..b3c07347de1 100644 --- a/spec/lib/gitlab/ci/status/build/cancelable_spec.rb +++ b/spec/lib/gitlab/ci/status/build/cancelable_spec.rb @@ -32,6 +32,14 @@ describe Gitlab::Ci::Status::Build::Cancelable do end end + describe '#group' do + it 'does not override status group' do + expect(status).to receive(:group) + + subject.group + end + end + describe 'action details' do let(:user) { create(:user) } let(:build) { create(:ci_build) } diff --git a/spec/lib/gitlab/ci/status/build/play_spec.rb b/spec/lib/gitlab/ci/status/build/play_spec.rb index 4ddf04a8e11..f1b50a59ce6 100644 --- a/spec/lib/gitlab/ci/status/build/play_spec.rb +++ b/spec/lib/gitlab/ci/status/build/play_spec.rb @@ -18,6 +18,10 @@ describe Gitlab::Ci::Status::Build::Play do it { expect(subject.icon).to eq 'icon_status_manual' } end + describe '#group' do + it { expect(subject.group).to eq 'manual' } + end + describe 'action details' do let(:user) { create(:user) } let(:build) { create(:ci_build) } diff --git a/spec/lib/gitlab/ci/status/build/retryable_spec.rb b/spec/lib/gitlab/ci/status/build/retryable_spec.rb index d61e5bbaa6b..62036f8ec5d 100644 --- a/spec/lib/gitlab/ci/status/build/retryable_spec.rb +++ b/spec/lib/gitlab/ci/status/build/retryable_spec.rb @@ -32,6 +32,14 @@ describe Gitlab::Ci::Status::Build::Retryable do end end + describe '#group' do + it 'does not override status group' do + expect(status).to receive(:group) + + subject.group + end + end + describe 'action details' do let(:user) { create(:user) } let(:build) { create(:ci_build) } diff --git a/spec/lib/gitlab/ci/status/build/stop_spec.rb b/spec/lib/gitlab/ci/status/build/stop_spec.rb index 59a85b55f90..597e02e86e4 100644 --- a/spec/lib/gitlab/ci/status/build/stop_spec.rb +++ b/spec/lib/gitlab/ci/status/build/stop_spec.rb @@ -20,6 +20,10 @@ describe Gitlab::Ci::Status::Build::Stop do it { expect(subject.icon).to eq 'icon_status_manual' } end + describe '#group' do + it { expect(subject.group).to eq 'manual' } + end + describe 'action details' do let(:user) { create(:user) } let(:build) { create(:ci_build) } diff --git a/spec/lib/gitlab/ci/status/canceled_spec.rb b/spec/lib/gitlab/ci/status/canceled_spec.rb index 4639278ad45..38412fe2e4f 100644 --- a/spec/lib/gitlab/ci/status/canceled_spec.rb +++ b/spec/lib/gitlab/ci/status/canceled_spec.rb @@ -16,4 +16,8 @@ describe Gitlab::Ci::Status::Canceled do describe '#icon' do it { expect(subject.icon).to eq 'icon_status_canceled' } end + + describe '#group' do + it { expect(subject.group).to eq 'canceled' } + end end diff --git a/spec/lib/gitlab/ci/status/created_spec.rb b/spec/lib/gitlab/ci/status/created_spec.rb index 2ce176a29d6..6d847484693 100644 --- a/spec/lib/gitlab/ci/status/created_spec.rb +++ b/spec/lib/gitlab/ci/status/created_spec.rb @@ -16,4 +16,8 @@ describe Gitlab::Ci::Status::Created do describe '#icon' do it { expect(subject.icon).to eq 'icon_status_created' } end + + describe '#group' do + it { expect(subject.group).to eq 'created' } + end end diff --git a/spec/lib/gitlab/ci/status/failed_spec.rb b/spec/lib/gitlab/ci/status/failed_spec.rb index 9d527e6a7ef..990d686d22c 100644 --- a/spec/lib/gitlab/ci/status/failed_spec.rb +++ b/spec/lib/gitlab/ci/status/failed_spec.rb @@ -16,4 +16,8 @@ describe Gitlab::Ci::Status::Failed do describe '#icon' do it { expect(subject.icon).to eq 'icon_status_failed' } end + + describe '#group' do + it { expect(subject.group).to eq 'failed' } + end end diff --git a/spec/lib/gitlab/ci/status/pending_spec.rb b/spec/lib/gitlab/ci/status/pending_spec.rb index d03f595d3c7..7bb6579c317 100644 --- a/spec/lib/gitlab/ci/status/pending_spec.rb +++ b/spec/lib/gitlab/ci/status/pending_spec.rb @@ -16,4 +16,8 @@ describe Gitlab::Ci::Status::Pending do describe '#icon' do it { expect(subject.icon).to eq 'icon_status_pending' } end + + describe '#group' do + it { expect(subject.group).to eq 'pending' } + end end diff --git a/spec/lib/gitlab/ci/status/pipeline/success_with_warnings_spec.rb b/spec/lib/gitlab/ci/status/pipeline/success_with_warnings_spec.rb index 7e3383c307f..979160eb9c4 100644 --- a/spec/lib/gitlab/ci/status/pipeline/success_with_warnings_spec.rb +++ b/spec/lib/gitlab/ci/status/pipeline/success_with_warnings_spec.rb @@ -17,6 +17,10 @@ describe Gitlab::Ci::Status::Pipeline::SuccessWithWarnings do it { expect(subject.icon).to eq 'icon_status_warning' } end + describe '#group' do + it { expect(subject.group).to eq 'success_with_warnings' } + end + describe '.matches?' do context 'when pipeline is successful' do let(:pipeline) do diff --git a/spec/lib/gitlab/ci/status/running_spec.rb b/spec/lib/gitlab/ci/status/running_spec.rb index 9f47090d396..852d6c06baf 100644 --- a/spec/lib/gitlab/ci/status/running_spec.rb +++ b/spec/lib/gitlab/ci/status/running_spec.rb @@ -16,4 +16,8 @@ describe Gitlab::Ci::Status::Running do describe '#icon' do it { expect(subject.icon).to eq 'icon_status_running' } end + + describe '#group' do + it { expect(subject.group).to eq 'running' } + end end diff --git a/spec/lib/gitlab/ci/status/skipped_spec.rb b/spec/lib/gitlab/ci/status/skipped_spec.rb index 94601648a8d..e00b356a24b 100644 --- a/spec/lib/gitlab/ci/status/skipped_spec.rb +++ b/spec/lib/gitlab/ci/status/skipped_spec.rb @@ -16,4 +16,8 @@ describe Gitlab::Ci::Status::Skipped do describe '#icon' do it { expect(subject.icon).to eq 'icon_status_skipped' } end + + describe '#group' do + it { expect(subject.group).to eq 'skipped' } + end end diff --git a/spec/lib/gitlab/ci/status/success_spec.rb b/spec/lib/gitlab/ci/status/success_spec.rb index 90f9f615e0d..4a89e1faf40 100644 --- a/spec/lib/gitlab/ci/status/success_spec.rb +++ b/spec/lib/gitlab/ci/status/success_spec.rb @@ -16,4 +16,8 @@ describe Gitlab::Ci::Status::Success do describe '#icon' do it { expect(subject.icon).to eq 'icon_status_success' } end + + describe '#group' do + it { expect(subject.group).to eq 'success' } + end end diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json index ed9df468ced..931d426c87f 100644 --- a/spec/lib/gitlab/import_export/project.json +++ b/spec/lib/gitlab/import_export/project.json @@ -2517,7 +2517,7 @@ "merge_params": { "force_remove_source_branch": null }, - "merge_when_build_succeeds": false, + "merge_when_build_succeeds": true, "merge_user_id": null, "merge_commit_sha": null, "deleted_at": null, @@ -6548,7 +6548,9 @@ "url": null }, "erased_by_id": null, - "erased_at": null + "erased_at": null, + "type": "Ci::Build", + "token": "abcd" }, { "id": 72, @@ -7409,6 +7411,28 @@ "category": "common", "default": false, "wiki_page_events": true + }, + { + "id": 101, + "title": "JenkinsDeprecated", + "project_id": 5, + "created_at": "2016-06-14T15:01:51.031Z", + "updated_at": "2016-06-14T15:01:51.031Z", + "active": false, + "properties": { + + }, + "template": false, + "push_events": true, + "issues_events": true, + "merge_requests_events": true, + "tag_push_events": true, + "note_events": true, + "build_events": true, + "category": "common", + "default": false, + "wiki_page_events": true, + "type": "JenkinsDeprecatedService" } ], "hooks": [ diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb index 3038ab53ad8..4b07fa53bf5 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -189,6 +189,14 @@ describe Gitlab::ImportExport::ProjectTreeRestorer, services: true do end end end + + context 'when there is an existing build with build token' do + it 'restores project json correctly' do + create(:ci_build, token: 'abcd') + + expect(restored_project_json).to be true + end + end end end end diff --git a/spec/lib/gitlab/serialize/ci/variables_spec.rb b/spec/lib/gitlab/serialize/ci/variables_spec.rb new file mode 100644 index 00000000000..7ea74da5252 --- /dev/null +++ b/spec/lib/gitlab/serialize/ci/variables_spec.rb @@ -0,0 +1,18 @@ +require 'spec_helper' + +describe Gitlab::Serialize::Ci::Variables do + subject do + described_class.load(described_class.dump(object)) + end + + let(:object) do + [{ key: :key, value: 'value', public: true }, + { key: 'wee', value: 1, public: false }] + end + + it 'converts keys into strings' do + is_expected.to eq([ + { key: 'key', value: 'value', public: true }, + { key: 'wee', value: 1, public: false }]) + end +end diff --git a/spec/models/build_spec.rb b/spec/models/build_spec.rb index 6f1c2ae0fd8..cd3b6d51545 100644 --- a/spec/models/build_spec.rb +++ b/spec/models/build_spec.rb @@ -458,7 +458,7 @@ describe Ci::Build, models: true do }) end let(:variables) do - [{ key: :KEY, value: 'value', public: true }] + [{ key: 'KEY', value: 'value', public: true }] end it { is_expected.to eq(predefined_variables + variables) } @@ -1306,11 +1306,25 @@ describe Ci::Build, models: true do describe '#expanded_environment_name' do subject { build.expanded_environment_name } - context 'when environment uses variables' do - let(:build) { create(:ci_build, ref: 'master', environment: 'review/$CI_BUILD_REF_NAME') } + context 'when environment uses $CI_BUILD_REF_NAME' do + let(:build) do + create(:ci_build, + ref: 'master', + environment: 'review/$CI_BUILD_REF_NAME') + end it { is_expected.to eq('review/master') } end + + context 'when environment uses yaml_variables containing symbol keys' do + let(:build) do + create(:ci_build, + yaml_variables: [{ key: :APP_HOST, value: 'host' }], + environment: 'review/$APP_HOST') + end + + it { is_expected.to eq('review/host') } + end end describe '#detailed_status' do diff --git a/spec/models/route_spec.rb b/spec/models/route_spec.rb index 6f491fdf9a0..8481a9bef16 100644 --- a/spec/models/route_spec.rb +++ b/spec/models/route_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Route, models: true do - let!(:group) { create(:group) } + let!(:group) { create(:group, path: 'gitlab') } let!(:route) { group.route } describe 'relationships' do @@ -17,13 +17,15 @@ describe Route, models: true do describe '#rename_children' do let!(:nested_group) { create(:group, path: "test", parent: group) } let!(:deep_nested_group) { create(:group, path: "foo", parent: nested_group) } + let!(:similar_group) { create(:group, path: 'gitlab-org') } - it "updates children routes with new path" do - route.update_attributes(path: 'bar') + before { route.update_attributes(path: 'bar') } + it "updates children routes with new path" do expect(described_class.exists?(path: 'bar')).to be_truthy expect(described_class.exists?(path: 'bar/test')).to be_truthy expect(described_class.exists?(path: 'bar/test/foo')).to be_truthy + expect(described_class.exists?(path: 'gitlab-org')).to be_truthy end end end diff --git a/spec/tasks/gitlab/ldap_rake_spec.rb b/spec/tasks/gitlab/ldap_rake_spec.rb new file mode 100644 index 00000000000..12d442b9820 --- /dev/null +++ b/spec/tasks/gitlab/ldap_rake_spec.rb @@ -0,0 +1,13 @@ +require 'rake_helper' + +describe 'gitlab:ldap:rename_provider rake task' do + it 'completes without error' do + Rake.application.rake_require 'tasks/gitlab/ldap' + stub_warn_user_is_not_gitlab + ENV['force'] = 'yes' + + create(:identity) # Necessary to prevent `exit 1` from the task. + + run_rake_task('gitlab:ldap:rename_provider', 'ldapmain', 'ldapfoo') + end +end |