summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml1
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock4
-rw-r--r--app/assets/javascripts/dispatcher.js4
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss27
-rw-r--r--app/assets/stylesheets/framework/variables.scss4
-rw-r--r--app/controllers/admin/appearances_controller.rb6
-rw-r--r--app/helpers/appearances_helper.rb20
-rw-r--r--app/helpers/button_helper.rb2
-rw-r--r--app/models/appearance.rb3
-rw-r--r--app/models/ci/build.rb19
-rw-r--r--app/models/ci/runner.rb6
-rw-r--r--app/services/ci/register_job_service.rb10
-rw-r--r--app/views/admin/appearances/_form.html.haml38
-rw-r--r--app/views/admin/appearances/preview_sign_in.html.haml (renamed from app/views/admin/appearances/preview.html.haml)0
-rw-r--r--app/views/layouts/devise.html.haml2
-rw-r--r--app/views/projects/_md_preview.html.haml2
-rw-r--r--app/views/projects/new.html.haml1
-rw-r--r--app/views/shared/_clone_panel.html.haml2
-rw-r--r--changelogs/unreleased/40508-snippets-zen-mode.yml5
-rw-r--r--changelogs/unreleased/feature-custom-text-for-new-projects.yml5
-rw-r--r--changelogs/unreleased/perform-sql-matching-of-tags.yml5
-rw-r--r--config/routes/admin.rb2
-rw-r--r--db/migrate/20171122131600_add_new_project_guidelines_to_appearances.rb12
-rw-r--r--db/schema.rb2
-rw-r--r--doc/README.md1
-rw-r--r--doc/administration/raketasks/maintenance.md4
-rw-r--r--doc/customization/new_project_page.md20
-rw-r--r--doc/customization/new_project_page/appearance_settings.pngbin0 -> 71178 bytes
-rw-r--r--doc/customization/new_project_page/custom_new_project_page.pngbin0 -> 164962 bytes
-rw-r--r--doc/customization/new_project_page/default_new_project_page.pngbin0 -> 146906 bytes
-rw-r--r--doc/integration/slash_commands.md3
-rw-r--r--doc/user/permissions.md17
-rw-r--r--lib/gitlab/database.rb4
-rw-r--r--lib/gitlab/git/commit.rb16
-rw-r--r--lib/gitlab/git/repository.rb53
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb20
-rw-r--r--lib/gitlab/gitaly_client/operation_service.rb32
-rw-r--r--spec/factories/appearances.rb1
-rw-r--r--spec/features/admin/admin_appearance_spec.rb33
-rw-r--r--spec/features/projects/snippets_spec.rb5
-rw-r--r--spec/helpers/button_helper_spec.rb28
-rw-r--r--spec/lib/gitlab/database_spec.rb22
-rw-r--r--spec/lib/gitlab/git/commit_spec.rb29
-rw-r--r--spec/models/appearance_spec.rb3
-rw-r--r--spec/models/ci/build_spec.rb73
-rw-r--r--spec/models/repository_spec.rb54
-rw-r--r--spec/services/ci/register_job_service_spec.rb23
49 files changed, 509 insertions, 118 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 60a2b5d5b5b..19540e4331e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -586,6 +586,7 @@ codequality:
paths: [codeclimate.json]
qa:internal:
+ <<: *except-docs
stage: test
variables:
SETUP_DB: "false"
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 2f4c74eb2dd..46448c71b9d 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-0.56.0
+0.57.0
diff --git a/Gemfile b/Gemfile
index 044778498a2..222e63904a0 100644
--- a/Gemfile
+++ b/Gemfile
@@ -400,7 +400,7 @@ group :ed25519 do
end
# Gitaly GRPC client
-gem 'gitaly-proto', '~> 0.58.0', require: 'gitaly'
+gem 'gitaly-proto', '~> 0.59.0', require: 'gitaly'
gem 'toml-rb', '~> 0.3.15', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index fdb81b101f5..48e46e3fab0 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -276,7 +276,7 @@ GEM
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
gherkin-ruby (0.3.2)
- gitaly-proto (0.58.0)
+ gitaly-proto (0.59.0)
google-protobuf (~> 3.1)
grpc (~> 1.0)
github-linguist (4.7.6)
@@ -1037,7 +1037,7 @@ DEPENDENCIES
gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.2.0)
- gitaly-proto (~> 0.58.0)
+ gitaly-proto (~> 0.59.0)
github-linguist (~> 4.7.0)
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-markup (~> 1.6.2)
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index a21c92f24d6..6d2907e2164 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -298,18 +298,21 @@ import ProjectVariables from './project_variables';
break;
case 'projects:snippets:show':
initNotes();
+ new ZenMode();
break;
case 'projects:snippets:new':
case 'projects:snippets:edit':
case 'projects:snippets:create':
case 'projects:snippets:update':
new GLForm($('.snippet-form'), true);
+ new ZenMode();
break;
case 'snippets:new':
case 'snippets:edit':
case 'snippets:create':
case 'snippets:update':
new GLForm($('.snippet-form'), false);
+ new ZenMode();
break;
case 'projects:releases:edit':
new ZenMode();
@@ -546,6 +549,7 @@ import ProjectVariables from './project_variables';
new LineHighlighter();
new BlobViewer();
initNotes();
+ new ZenMode();
break;
case 'import:fogbugz:new_user_map':
new UsersSelect();
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 30d5d7a653b..8d83554d813 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -608,7 +608,7 @@
}
.dropdown-content {
- max-height: 215px;
+ max-height: $dropdown-max-height;
overflow-y: auto;
}
@@ -1030,3 +1030,28 @@ header.header-content .dropdown-menu.projects-dropdown-menu {
}
}
}
+
+.dropdown-content-faded-mask {
+ position: relative;
+
+ .dropdown-list {
+ max-height: $dropdown-max-height;
+ overflow-y: auto;
+ position: relative;
+ }
+
+ &::after {
+ height: $dropdown-fade-mask-height;
+ width: 100%;
+ position: absolute;
+ bottom: 0;
+ background: linear-gradient(to top, $white-light 0, rgba($white-light, 0));
+ transition: opacity $fade-mask-transition-duration $fade-mask-transition-curve;
+ content: '';
+ pointer-events: none;
+ }
+
+ &.fade-out::after {
+ opacity: 0;
+ }
+}
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index cb2a237f574..6525b39d55c 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -337,6 +337,7 @@ $regular_font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-San
* Dropdowns
*/
$dropdown-width: 300px;
+$dropdown-max-height: 215px;
$dropdown-vertical-offset: 4px;
$dropdown-link-color: #555;
$dropdown-link-hover-bg: $row-hover;
@@ -353,6 +354,7 @@ $dropdown-loading-bg: rgba(#fff, .6);
$dropdown-chevron-size: 10px;
$dropdown-toggle-active-border-color: darken($border-color, 14%);
$dropdown-item-hover-bg: $gray-darker;
+$dropdown-fade-mask-height: 32px;
/*
* Filtered Search
@@ -564,6 +566,8 @@ $label-border-radius: 100px;
* Animation
*/
$fade-in-duration: 200ms;
+$fade-mask-transition-duration: .1s;
+$fade-mask-transition-curve: ease-in-out;
/*
* Lint
diff --git a/app/controllers/admin/appearances_controller.rb b/app/controllers/admin/appearances_controller.rb
index 92df1c8dff0..dd0b38970bd 100644
--- a/app/controllers/admin/appearances_controller.rb
+++ b/app/controllers/admin/appearances_controller.rb
@@ -4,8 +4,8 @@ class Admin::AppearancesController < Admin::ApplicationController
def show
end
- def preview
- render 'preview', layout: 'devise'
+ def preview_sign_in
+ render 'preview_sign_in', layout: 'devise'
end
def create
@@ -52,7 +52,7 @@ class Admin::AppearancesController < Admin::ApplicationController
def appearance_params
params.require(:appearance).permit(
:title, :description, :logo, :logo_cache, :header_logo, :header_logo_cache,
- :updated_by
+ :new_project_guidelines, :updated_by
)
end
end
diff --git a/app/helpers/appearances_helper.rb b/app/helpers/appearances_helper.rb
index df590cf47c8..c037de33c22 100644
--- a/app/helpers/appearances_helper.rb
+++ b/app/helpers/appearances_helper.rb
@@ -1,30 +1,26 @@
module AppearancesHelper
def brand_title
- if brand_item && brand_item.title
- brand_item.title
- else
- 'GitLab Community Edition'
- end
+ brand_item&.title.presence || 'GitLab Community Edition'
end
def brand_image
- if brand_item.logo?
- image_tag brand_item.logo
- else
- nil
- end
+ image_tag(brand_item.logo) if brand_item&.logo?
end
def brand_text
markdown_field(brand_item, :description)
end
+ def brand_new_project_guidelines
+ markdown_field(brand_item, :new_project_guidelines)
+ end
+
def brand_item
@appearance ||= Appearance.current
end
def brand_header_logo
- if brand_item && brand_item.header_logo?
+ if brand_item&.header_logo?
image_tag brand_item.header_logo
else
render 'shared/logo.svg'
@@ -33,7 +29,7 @@ module AppearancesHelper
# Skip the 'GitLab' type logo when custom brand logo is set
def brand_header_logo_type
- unless brand_item && brand_item.header_logo?
+ unless brand_item&.header_logo?
render 'shared/logo_type.svg'
end
end
diff --git a/app/helpers/button_helper.rb b/app/helpers/button_helper.rb
index d06cf2de2c3..3605d6a3c95 100644
--- a/app/helpers/button_helper.rb
+++ b/app/helpers/button_helper.rb
@@ -84,7 +84,7 @@ module ButtonHelper
button_content << content_tag(:span, description, class: 'dropdown-menu-inner-content') if description
content_tag (href ? :a : :span),
- button_content,
+ (href ? button_content : title),
class: "#{title.downcase}-selector",
href: (href if href)
end
diff --git a/app/models/appearance.rb b/app/models/appearance.rb
index ff15689ecac..76cfe28742a 100644
--- a/app/models/appearance.rb
+++ b/app/models/appearance.rb
@@ -2,9 +2,8 @@ class Appearance < ActiveRecord::Base
include CacheMarkdownField
cache_markdown_field :description
+ cache_markdown_field :new_project_guidelines
- validates :title, presence: true
- validates :description, presence: true
validates :logo, file_size: { maximum: 1.megabyte }
validates :header_logo, file_size: { maximum: 1.megabyte }
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 8738e094510..d2402b55184 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -47,6 +47,25 @@ module Ci
scope :manual_actions, ->() { where(when: :manual, status: COMPLETED_STATUSES + [:manual]) }
scope :ref_protected, -> { where(protected: true) }
+ scope :matches_tag_ids, -> (tag_ids) do
+ matcher = ::ActsAsTaggableOn::Tagging
+ .where(taggable_type: CommitStatus)
+ .where(context: 'tags')
+ .where('taggable_id = ci_builds.id')
+ .where.not(tag_id: tag_ids).select('1')
+
+ where("NOT EXISTS (?)", matcher)
+ end
+
+ scope :with_any_tags, -> do
+ matcher = ::ActsAsTaggableOn::Tagging
+ .where(taggable_type: CommitStatus)
+ .where(context: 'tags')
+ .where('taggable_id = ci_builds.id').select('1')
+
+ where("EXISTS (?)", matcher)
+ end
+
mount_uploader :legacy_artifacts_file, LegacyArtifactUploader, mount_on: :artifacts_file
mount_uploader :legacy_artifacts_metadata, LegacyArtifactUploader, mount_on: :artifacts_metadata
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index d39610a8995..dcbb397fb78 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -112,7 +112,7 @@ module Ci
def can_pick?(build)
return false if self.ref_protected? && !build.protected?
- assignable_for?(build.project) && accepting_tags?(build)
+ assignable_for?(build.project_id) && accepting_tags?(build)
end
def only_for?(project)
@@ -171,8 +171,8 @@ module Ci
end
end
- def assignable_for?(project)
- is_shared? || projects.exists?(id: project.id)
+ def assignable_for?(project_id)
+ is_shared? || projects.exists?(id: project_id)
end
def accepting_tags?(build)
diff --git a/app/services/ci/register_job_service.rb b/app/services/ci/register_job_service.rb
index b8db709211a..2ef76e03031 100644
--- a/app/services/ci/register_job_service.rb
+++ b/app/services/ci/register_job_service.rb
@@ -22,6 +22,16 @@ module Ci
valid = true
+ if Feature.enabled?('ci_job_request_with_tags_matcher')
+ # pick builds that does not have other tags than runner's one
+ builds = builds.matches_tag_ids(runner.tags.ids)
+
+ # pick builds that have at least one tag
+ unless runner.run_untagged?
+ builds = builds.with_any_tags
+ end
+ end
+
builds.find do |build|
next unless runner.can_pick?(build)
diff --git a/app/views/admin/appearances/_form.html.haml b/app/views/admin/appearances/_form.html.haml
index 4a2238fe277..15bda97c3b5 100644
--- a/app/views/admin/appearances/_form.html.haml
+++ b/app/views/admin/appearances/_form.html.haml
@@ -1,6 +1,23 @@
= form_for @appearance, url: admin_appearances_path, html: { class: 'form-horizontal'} do |f|
= form_errors(@appearance)
+ %fieldset.app_logo
+ %legend
+ Navigation bar:
+ .form-group
+ = f.label :header_logo, 'Header logo', class: 'control-label'
+ .col-sm-10
+ - if @appearance.header_logo?
+ = image_tag @appearance.header_logo_url, class: 'appearance-light-logo-preview'
+ - if @appearance.persisted?
+ %br
+ = link_to 'Remove header logo', header_logos_admin_appearances_path, data: { confirm: "Header logo will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-logo"
+ %hr
+ = f.hidden_field :header_logo_cache
+ = f.file_field :header_logo, class: ""
+ .hint
+ Maximum file size is 1MB. Pages are optimized for a 28px tall header logo
+
%fieldset.sign-in
%legend
Sign in/Sign up pages:
@@ -28,27 +45,22 @@
.hint
Maximum file size is 1MB. Pages are optimized for a 640x360 px logo.
- %fieldset.app_logo
+ %fieldset
%legend
- Navigation bar:
+ New project pages:
.form-group
- = f.label :header_logo, 'Header logo', class: 'control-label'
+ = f.label :new_project_guidelines, class: 'control-label'
.col-sm-10
- - if @appearance.header_logo?
- = image_tag @appearance.header_logo_url, class: 'appearance-light-logo-preview'
- - if @appearance.persisted?
- %br
- = link_to 'Remove header logo', header_logos_admin_appearances_path, data: { confirm: "Header logo will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-sm remove-logo"
- %hr
- = f.hidden_field :header_logo_cache
- = f.file_field :header_logo, class: ""
+ = f.text_area :new_project_guidelines, class: "form-control", rows: 10
.hint
- Maximum file size is 1MB. Pages are optimized for a 28px tall header logo
+ Guidelines parsed with #{link_to "GitLab Flavored Markdown", help_page_path('user/markdown'), target: '_blank'}.
.form-actions
= f.submit 'Save', class: 'btn btn-save append-right-10'
- if @appearance.persisted?
- = link_to 'Preview last save', preview_admin_appearances_path, class: 'btn', target: '_blank', rel: 'noopener noreferrer'
+ Preview last save:
+ = link_to 'Sign-in page', preview_sign_in_admin_appearances_path, class: 'btn', target: '_blank', rel: 'noopener noreferrer'
+ = link_to 'New project page', new_project_path, class: 'btn', target: '_blank', rel: 'noopener noreferrer'
- if @appearance.updated_at
%span.pull-right
diff --git a/app/views/admin/appearances/preview.html.haml b/app/views/admin/appearances/preview_sign_in.html.haml
index 1af7dd5bb67..1af7dd5bb67 100644
--- a/app/views/admin/appearances/preview.html.haml
+++ b/app/views/admin/appearances/preview_sign_in.html.haml
diff --git a/app/views/layouts/devise.html.haml b/app/views/layouts/devise.html.haml
index 97016d28535..691d2528022 100644
--- a/app/views/layouts/devise.html.haml
+++ b/app/views/layouts/devise.html.haml
@@ -15,8 +15,8 @@
.col-sm-7.brand-holder.pull-left
%h1
= brand_title
- - if brand_item
= brand_image
+ - if brand_item&.description?
= brand_text
- else
%h3 Open source software to collaborate on code
diff --git a/app/views/projects/_md_preview.html.haml b/app/views/projects/_md_preview.html.haml
index a9431cc4956..2cd5d0c60ea 100644
--- a/app/views/projects/_md_preview.html.haml
+++ b/app/views/projects/_md_preview.html.haml
@@ -25,7 +25,7 @@
= markdown_toolbar_button({ icon: "list-bulleted", data: { "md-tag" => "* ", "md-prepend" => true }, title: "Add a bullet list" })
= markdown_toolbar_button({ icon: "list-numbered", data: { "md-tag" => "1. ", "md-prepend" => true }, title: "Add a numbered list" })
= markdown_toolbar_button({ icon: "task-done", data: { "md-tag" => "* [ ] ", "md-prepend" => true }, title: "Add a task list" })
- %button.toolbar-btn.toolbar-fullscreen-btn.js-zen-enter.has-tooltip{ type: "button", tabindex: -1, aria: { label: "Go full screen" }, title: "Go full screen", data: { container: "body" } }
+ %button.toolbar-btn.toolbar-fullscreen-btn.js-zen-enter.has-tooltip{ type: "button", tabindex: -1, "aria-label": "Go full screen", title: "Go full screen", data: { container: "body" } }
= sprite_icon("screen-full")
.md-write-holder
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index 0a7880ce4cd..cad7c2e83db 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -18,6 +18,7 @@
A project is where you house your files (repository), plan your work (issues), and publish your documentation (wiki), #{link_to 'among other things', help_page_path("user/project/index.md", anchor: "projects-features"), target: '_blank'}.
%p
All features are enabled when you create a project, but you can disable the ones you don’t need in the project settings.
+ = brand_new_project_guidelines
.col-lg-9.js-toggle-container
%ul.nav-links.gitlab-tabs{ role: 'tablist' }
%li.active{ role: 'presentation' }
diff --git a/app/views/shared/_clone_panel.html.haml b/app/views/shared/_clone_panel.html.haml
index fba08092351..1cba4fc6c41 100644
--- a/app/views/shared/_clone_panel.html.haml
+++ b/app/views/shared/_clone_panel.html.haml
@@ -3,7 +3,7 @@
.git-clone-holder.input-group
.input-group-btn
- if allowed_protocols_present?
- .clone-dropdown-btn.btn.btn-static
+ .clone-dropdown-btn.btn
%span
= enabled_project_button(project, enabled_protocol)
- else
diff --git a/changelogs/unreleased/40508-snippets-zen-mode.yml b/changelogs/unreleased/40508-snippets-zen-mode.yml
new file mode 100644
index 00000000000..c205218575b
--- /dev/null
+++ b/changelogs/unreleased/40508-snippets-zen-mode.yml
@@ -0,0 +1,5 @@
+---
+title: Init zen mode in snippets pages
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/feature-custom-text-for-new-projects.yml b/changelogs/unreleased/feature-custom-text-for-new-projects.yml
new file mode 100644
index 00000000000..905d76dab33
--- /dev/null
+++ b/changelogs/unreleased/feature-custom-text-for-new-projects.yml
@@ -0,0 +1,5 @@
+---
+title: Add custom brand text on new project pages
+merge_request: 15541
+author: Markus Koller
+type: changed
diff --git a/changelogs/unreleased/perform-sql-matching-of-tags.yml b/changelogs/unreleased/perform-sql-matching-of-tags.yml
new file mode 100644
index 00000000000..39f8a867a4d
--- /dev/null
+++ b/changelogs/unreleased/perform-sql-matching-of-tags.yml
@@ -0,0 +1,5 @@
+---
+title: Perform SQL matching of Build&Runner tags to greatly speed-up job picking
+merge_request:
+author:
+type: performance
diff --git a/config/routes/admin.rb b/config/routes/admin.rb
index c0748231813..e22fb440abc 100644
--- a/config/routes/admin.rb
+++ b/config/routes/admin.rb
@@ -97,7 +97,7 @@ namespace :admin do
resource :appearances, only: [:show, :create, :update], path: 'appearance' do
member do
- get :preview
+ get :preview_sign_in
delete :logo
delete :header_logos
end
diff --git a/db/migrate/20171122131600_add_new_project_guidelines_to_appearances.rb b/db/migrate/20171122131600_add_new_project_guidelines_to_appearances.rb
new file mode 100644
index 00000000000..f141c442d97
--- /dev/null
+++ b/db/migrate/20171122131600_add_new_project_guidelines_to_appearances.rb
@@ -0,0 +1,12 @@
+class AddNewProjectGuidelinesToAppearances < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ change_table :appearances do |t|
+ t.text :new_project_guidelines
+ t.text :new_project_guidelines_html
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 8e5bcc8b51d..0984ca6487f 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -36,6 +36,8 @@ ActiveRecord::Schema.define(version: 20171124150326) do
t.datetime_with_timezone "updated_at", null: false
t.text "description_html"
t.integer "cached_markdown_version"
+ t.text "new_project_guidelines"
+ t.text "new_project_guidelines_html"
end
create_table "application_settings", force: :cascade do |t|
diff --git a/doc/README.md b/doc/README.md
index d4119d35162..95cb9683a15 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -189,6 +189,7 @@ have access to GitLab administration tools and settings.
- [Issue closing pattern](administration/issue_closing_pattern.md): Customize how to close an issue from commit messages.
- [Libravatar](customization/libravatar.md): Use Libravatar instead of Gravatar for user avatars.
- [Welcome message](customization/welcome_message.md): Add a custom welcome message to the sign-in page.
+- [New project page](customization/new_project_page.md): Customize the new project page.
### Admin tools
diff --git a/doc/administration/raketasks/maintenance.md b/doc/administration/raketasks/maintenance.md
index 5b6ee354887..136192191f9 100644
--- a/doc/administration/raketasks/maintenance.md
+++ b/doc/administration/raketasks/maintenance.md
@@ -58,7 +58,9 @@ Runs the following rake tasks:
It will check that each component was setup according to the installation guide and suggest fixes for issues found.
-You may also have a look at our [Trouble Shooting Guide](https://github.com/gitlabhq/gitlab-public-wiki/wiki/Trouble-Shooting-Guide).
+You may also have a look at our Trouble Shooting Guides:
+- [Trouble Shooting Guide (GitLab)](http://docs.gitlab.com/ee/README.html#troubleshooting)
+- [Trouble Shooting Guide (Omnibus Gitlab)](http://docs.gitlab.com/omnibus/README.html#troubleshooting)
**Omnibus Installation**
diff --git a/doc/customization/new_project_page.md b/doc/customization/new_project_page.md
new file mode 100644
index 00000000000..148bf9512c6
--- /dev/null
+++ b/doc/customization/new_project_page.md
@@ -0,0 +1,20 @@
+# Customizing the new project page
+
+It is possible to add a markdown-formatted message to your GitLab
+new project page.
+
+By default, the new project page shows a sidebar with general information:
+
+![](new_project_page/default_new_project_page.png)
+
+## Changing the appearance of the new project page
+
+Navigate to the **Admin** area and go to the **Appearance** page.
+
+Fill in your project guidelines:
+
+![](new_project_page/appearance_settings.png)
+
+After saving the page, your new project page will show the guidelines in the sidebar, below the general information:
+
+![](new_project_page/custom_new_project_page.png)
diff --git a/doc/customization/new_project_page/appearance_settings.png b/doc/customization/new_project_page/appearance_settings.png
new file mode 100644
index 00000000000..08eea684e14
--- /dev/null
+++ b/doc/customization/new_project_page/appearance_settings.png
Binary files differ
diff --git a/doc/customization/new_project_page/custom_new_project_page.png b/doc/customization/new_project_page/custom_new_project_page.png
new file mode 100644
index 00000000000..662c715f193
--- /dev/null
+++ b/doc/customization/new_project_page/custom_new_project_page.png
Binary files differ
diff --git a/doc/customization/new_project_page/default_new_project_page.png b/doc/customization/new_project_page/default_new_project_page.png
new file mode 100644
index 00000000000..4a0bcf09903
--- /dev/null
+++ b/doc/customization/new_project_page/default_new_project_page.png
Binary files differ
diff --git a/doc/integration/slash_commands.md b/doc/integration/slash_commands.md
index aa52b5415cf..36a8844e953 100644
--- a/doc/integration/slash_commands.md
+++ b/doc/integration/slash_commands.md
@@ -17,6 +17,9 @@ Taking the trigger term as `project-name`, the commands are:
| `/project-name issue search <query>` | Shows up to 5 issues matching `<query>` |
| `/project-name deploy <from> to <to>` | Deploy from the `<from>` environment to the `<to>` environment |
+Note that if you are using the [GitLab Slack application](https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html) for
+your GitLab.com projects, you need to [add the `gitlab` keyword at the beginning of the command](https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html#usage).
+
## Issue commands
It is possible to create new issue, display issue details and search up to 5 issues.
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index b9532bf897f..4fa83388d0c 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -23,25 +23,26 @@ The following table depicts the various user permission levels in a project.
|---------------------------------------|---------|------------|-------------|----------|--------|
| Create new issue | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
| Create confidential issue | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
-| View confidential issues | (✓) [^2] | ✓ | ✓ | ✓ | ✓ |
+| View confidential issues | (✓) [^2] | ✓ | ✓ | ✓ | ✓ |
| Leave comments | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
| Lock discussions (issues and merge requests) | | | | ✓ | ✓ |
| See a list of jobs | ✓ [^3] | ✓ | ✓ | ✓ | ✓ |
-| See a job log | ✓ [^3] | ✓ | ✓ | ✓ | ✓ |
+| See a job log | ✓ [^3] | ✓ | ✓ | ✓ | ✓ |
| Download and browse job artifacts | ✓ [^3] | ✓ | ✓ | ✓ | ✓ |
| View wiki pages | ✓ [^1] | ✓ | ✓ | ✓ | ✓ |
| Pull project code | [^1] | ✓ | ✓ | ✓ | ✓ |
| Download project | [^1] | ✓ | ✓ | ✓ | ✓ |
+| Assign issues and merge requests | | ✓ | ✓ | ✓ | ✓ |
+| Label issues and merge requests | | ✓ | ✓ | ✓ | ✓ |
| Create code snippets | | ✓ | ✓ | ✓ | ✓ |
| Manage issue tracker | | ✓ | ✓ | ✓ | ✓ |
| Manage labels | | ✓ | ✓ | ✓ | ✓ |
| See a commit status | | ✓ | ✓ | ✓ | ✓ |
| See a container registry | | ✓ | ✓ | ✓ | ✓ |
| See environments | | ✓ | ✓ | ✓ | ✓ |
+| See a list of merge requests | | ✓ | ✓ | ✓ | ✓ |
| Create new environments | | | ✓ | ✓ | ✓ |
-| Use environment terminals | | | | ✓ | ✓ |
| Stop environments | | | ✓ | ✓ | ✓ |
-| See a list of merge requests | | ✓ | ✓ | ✓ | ✓ |
| Manage/Accept merge requests | | | ✓ | ✓ | ✓ |
| Create new merge request | | | ✓ | ✓ | ✓ |
| Create new branches | | | ✓ | ✓ | ✓ |
@@ -55,10 +56,11 @@ The following table depicts the various user permission levels in a project.
| Update a container registry | | | ✓ | ✓ | ✓ |
| Remove a container registry image | | | ✓ | ✓ | ✓ |
| Create/edit/delete project milestones | | | ✓ | ✓ | ✓ |
+| Use environment terminals | | | | ✓ | ✓ |
| Add new team members | | | | ✓ | ✓ |
| Push to protected branches | | | | ✓ | ✓ |
| Enable/disable branch protection | | | | ✓ | ✓ |
-| Turn on/off protected branch push for devs| | | | ✓ | ✓ |
+| Turn on/off protected branch push for devs| | | | ✓ | ✓ |
| Enable/disable tag protections | | | | ✓ | ✓ |
| Rewrite/remove Git tags | | | | ✓ | ✓ |
| Edit project | | | | ✓ | ✓ |
@@ -69,14 +71,15 @@ The following table depicts the various user permission levels in a project.
| Manage variables | | | | ✓ | ✓ |
| Manage pages | | | | ✓ | ✓ |
| Manage pages domains and certificates | | | | ✓ | ✓ |
+| Manage clusters | | | | ✓ | ✓ |
+| Edit comments (posted by any user) | | | | ✓ | ✓ |
| Switch visibility level | | | | | ✓ |
| Transfer project to another namespace | | | | | ✓ |
| Remove project | | | | | ✓ |
| Delete issues | | | | | ✓ |
+| Remove pages | | | | | ✓ |
| Force push to protected branches [^4] | | | | | |
| Remove protected branches [^4] | | | | | |
-| Remove pages | | | | | ✓ |
-| Manage clusters | | | | ✓ | ✓ |
## Project features permissions
diff --git a/lib/gitlab/database.rb b/lib/gitlab/database.rb
index cd7b4c043da..96922e1a62f 100644
--- a/lib/gitlab/database.rb
+++ b/lib/gitlab/database.rb
@@ -50,6 +50,10 @@ module Gitlab
postgresql? && version.to_f >= 9.3
end
+ def self.replication_slots_supported?
+ postgresql? && version.to_f >= 9.4
+ end
+
def self.nulls_last_order(field, direction = 'ASC')
order = "#{field} #{direction}"
diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb
index c85dcfa0475..8900e2d7afe 100644
--- a/lib/gitlab/git/commit.rb
+++ b/lib/gitlab/git/commit.rb
@@ -213,11 +213,17 @@ module Gitlab
end
def shas_with_signatures(repository, shas)
- shas.select do |sha|
- begin
- Rugged::Commit.extract_signature(repository.rugged, sha)
- rescue Rugged::OdbError
- false
+ GitalyClient.migrate(:filter_shas_with_signatures) do |is_enabled|
+ if is_enabled
+ Gitlab::GitalyClient::CommitService.new(repository).filter_shas_with_signatures(shas)
+ else
+ shas.select do |sha|
+ begin
+ Rugged::Commit.extract_signature(repository.rugged, sha)
+ rescue Rugged::OdbError
+ false
+ end
+ end
end
end
end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index eab04bcac65..1468069a991 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -776,24 +776,21 @@ module Gitlab
end
def revert(user:, commit:, branch_name:, message:, start_branch_name:, start_repository:)
- OperationService.new(user, self).with_branch(
- branch_name,
- start_branch_name: start_branch_name,
- start_repository: start_repository
- ) do |start_commit|
-
- Gitlab::Git.check_namespace!(commit, start_repository)
-
- revert_tree_id = check_revert_content(commit, start_commit.sha)
- raise CreateTreeError unless revert_tree_id
-
- committer = user_to_committer(user)
+ gitaly_migrate(:revert) do |is_enabled|
+ args = {
+ user: user,
+ commit: commit,
+ branch_name: branch_name,
+ message: message,
+ start_branch_name: start_branch_name,
+ start_repository: start_repository
+ }
- create_commit(message: message,
- author: committer,
- committer: committer,
- tree: revert_tree_id,
- parents: [start_commit.sha])
+ if is_enabled
+ gitaly_operations_client.user_revert(args)
+ else
+ rugged_revert(args)
+ end
end
end
@@ -1769,6 +1766,28 @@ module Gitlab
end
end
+ def rugged_revert(user:, commit:, branch_name:, message:, start_branch_name:, start_repository:)
+ OperationService.new(user, self).with_branch(
+ branch_name,
+ start_branch_name: start_branch_name,
+ start_repository: start_repository
+ ) do |start_commit|
+
+ Gitlab::Git.check_namespace!(commit, start_repository)
+
+ revert_tree_id = check_revert_content(commit, start_commit.sha)
+ raise CreateTreeError unless revert_tree_id
+
+ committer = user_to_committer(user)
+
+ create_commit(message: message,
+ author: committer,
+ committer: committer,
+ tree: revert_tree_id,
+ parents: [start_commit.sha])
+ end
+ end
+
def gitaly_add_branch(branch_name, user, target)
gitaly_operation_client.user_create_branch(branch_name, user, target)
rescue GRPC::FailedPrecondition => ex
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index 34807d280e5..7985f5b5457 100644
--- a/lib/gitlab/gitaly_client/commit_service.rb
+++ b/lib/gitlab/gitaly_client/commit_service.rb
@@ -250,6 +250,26 @@ module Gitlab
consume_commits_response(response)
end
+ def filter_shas_with_signatures(shas)
+ request = Gitaly::FilterShasWithSignaturesRequest.new(repository: @gitaly_repo)
+
+ enum = Enumerator.new do |y|
+ shas.each_slice(20) do |revs|
+ request.shas = GitalyClient.encode_repeated(revs)
+
+ y.yield request
+
+ request = Gitaly::FilterShasWithSignaturesRequest.new
+ end
+ end
+
+ response = GitalyClient.call(@repository.storage, :commit_service, :filter_shas_with_signatures, enum)
+
+ response.flat_map do |msg|
+ msg.shas.map { |sha| EncodingHelper.encode!(sha) }
+ end
+ end
+
private
def call_commit_diff(request_params, options = {})
diff --git a/lib/gitlab/gitaly_client/operation_service.rb b/lib/gitlab/gitaly_client/operation_service.rb
index 51de6a9a75d..400a4af363b 100644
--- a/lib/gitlab/gitaly_client/operation_service.rb
+++ b/lib/gitlab/gitaly_client/operation_service.rb
@@ -124,7 +124,31 @@ module Gitlab
end
def user_cherry_pick(user:, commit:, branch_name:, message:, start_branch_name:, start_repository:)
- request = Gitaly::UserCherryPickRequest.new(
+ call_cherry_pick_or_revert(:cherry_pick,
+ user: user,
+ commit: commit,
+ branch_name: branch_name,
+ message: message,
+ start_branch_name: start_branch_name,
+ start_repository: start_repository)
+ end
+
+ def user_revert(user:, commit:, branch_name:, message:, start_branch_name:, start_repository:)
+ call_cherry_pick_or_revert(:revert,
+ user: user,
+ commit: commit,
+ branch_name: branch_name,
+ message: message,
+ start_branch_name: start_branch_name,
+ start_repository: start_repository)
+ end
+
+ private
+
+ def call_cherry_pick_or_revert(rpc, user:, commit:, branch_name:, message:, start_branch_name:, start_repository:)
+ request_class = "Gitaly::User#{rpc.to_s.camelcase}Request".constantize
+
+ request = request_class.new(
repository: @gitaly_repo,
user: Gitlab::Git::User.from_gitlab(user).to_gitaly,
commit: commit.to_gitaly_commit,
@@ -137,11 +161,15 @@ module Gitlab
response = GitalyClient.call(
@repository.storage,
:operation_service,
- :user_cherry_pick,
+ :"user_#{rpc}",
request,
remote_storage: start_repository.storage
)
+ handle_cherry_pick_or_revert_response(response)
+ end
+
+ def handle_cherry_pick_or_revert_response(response)
if response.pre_receive_error.presence
raise Gitlab::Git::HooksService::PreReceiveError, response.pre_receive_error
elsif response.commit_error.presence
diff --git a/spec/factories/appearances.rb b/spec/factories/appearances.rb
index cf2a2b76bcb..860973024c9 100644
--- a/spec/factories/appearances.rb
+++ b/spec/factories/appearances.rb
@@ -4,5 +4,6 @@ FactoryGirl.define do
factory :appearance do
title "MepMep"
description "This is my Community Edition instance"
+ new_project_guidelines "Custom project guidelines"
end
end
diff --git a/spec/features/admin/admin_appearance_spec.rb b/spec/features/admin/admin_appearance_spec.rb
index 5f3a37c1dcc..d91dcf76191 100644
--- a/spec/features/admin/admin_appearance_spec.rb
+++ b/spec/features/admin/admin_appearance_spec.rb
@@ -9,6 +9,7 @@ feature 'Admin Appearance' do
fill_in 'appearance_title', with: 'MyCompany'
fill_in 'appearance_description', with: 'dev server'
+ fill_in 'appearance_new_project_guidelines', with: 'Custom project guidelines'
click_button 'Save'
expect(current_path).to eq admin_appearances_path
@@ -16,21 +17,39 @@ feature 'Admin 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_field('appearance_new_project_guidelines', with: 'Custom project guidelines')
expect(page).to have_content 'Last edit'
end
- scenario 'Preview appearance' do
+ scenario 'Preview sign-in page appearance' do
sign_in(create(:admin))
visit admin_appearances_path
- click_link "Preview"
+ click_link "Sign-in page"
- expect_page_has_custom_appearance(appearance)
+ expect_custom_sign_in_appearance(appearance)
+ end
+
+ scenario 'Preview new project page appearance' do
+ sign_in(create(:admin))
+
+ visit admin_appearances_path
+ click_link "New project page"
+
+ expect_custom_new_project_appearance(appearance)
end
scenario 'Custom sign-in page' do
visit new_user_session_path
- expect_page_has_custom_appearance(appearance)
+
+ expect_custom_sign_in_appearance(appearance)
+ end
+
+ scenario 'Custom new project page' do
+ sign_in create(:user)
+ visit new_project_path
+
+ expect_custom_new_project_appearance(appearance)
end
scenario 'Appearance logo' do
@@ -57,11 +76,15 @@ feature 'Admin Appearance' do
expect(page).not_to have_css(header_logo_selector)
end
- def expect_page_has_custom_appearance(appearance)
+ def expect_custom_sign_in_appearance(appearance)
expect(page).to have_content appearance.title
expect(page).to have_content appearance.description
end
+ def expect_custom_new_project_appearance(appearance)
+ expect(page).to have_content appearance.new_project_guidelines
+ end
+
def logo_selector
'//img[data-src^="/uploads/-/system/appearance/logo"]'
end
diff --git a/spec/features/projects/snippets_spec.rb b/spec/features/projects/snippets_spec.rb
index 1cfbbb4cb62..0fa7ca9afd4 100644
--- a/spec/features/projects/snippets_spec.rb
+++ b/spec/features/projects/snippets_spec.rb
@@ -39,6 +39,11 @@ describe 'Project snippets', :js do
expect(page).to have_selector('.atwho-view')
end
+
+ it 'should have zen mode' do
+ find('.js-zen-enter').click()
+ expect(page).to have_selector('.fullscreen')
+ end
end
end
end
diff --git a/spec/helpers/button_helper_spec.rb b/spec/helpers/button_helper_spec.rb
index d2c7867febb..fee8df10129 100644
--- a/spec/helpers/button_helper_spec.rb
+++ b/spec/helpers/button_helper_spec.rb
@@ -92,6 +92,34 @@ describe ButtonHelper do
end
end
+ describe 'ssh and http clone buttons' do
+ let(:user) { create(:user) }
+ let(:project) { build_stubbed(:project) }
+
+ def http_button_element
+ element = helper.http_clone_button(project, append_link: false)
+
+ Nokogiri::HTML::DocumentFragment.parse(element).first_element_child
+ end
+
+ def ssh_button_element
+ element = helper.ssh_clone_button(project, append_link: false)
+
+ Nokogiri::HTML::DocumentFragment.parse(element).first_element_child
+ end
+
+ before do
+ allow(helper).to receive(:current_user).and_return(user)
+ end
+
+ it 'only shows the title of any of the clone buttons when append_link is false' do
+ expect(http_button_element.text).to eq('HTTP')
+ expect(http_button_element.search('.dropdown-menu-inner-content').first).to eq(nil)
+ expect(ssh_button_element.text).to eq('SSH')
+ expect(ssh_button_element.search('.dropdown-menu-inner-content').first).to eq(nil)
+ end
+ end
+
describe 'clipboard_button' do
let(:user) { create(:user) }
let(:project) { build_stubbed(:project) }
diff --git a/spec/lib/gitlab/database_spec.rb b/spec/lib/gitlab/database_spec.rb
index fcddfad3f9f..a5657b81952 100644
--- a/spec/lib/gitlab/database_spec.rb
+++ b/spec/lib/gitlab/database_spec.rb
@@ -73,6 +73,28 @@ describe Gitlab::Database do
end
end
+ describe '.replication_slots_supported?' do
+ it 'returns false when using MySQL' do
+ allow(described_class).to receive(:postgresql?).and_return(false)
+
+ expect(described_class.replication_slots_supported?).to eq(false)
+ end
+
+ it 'returns false when using PostgreSQL 9.3' do
+ allow(described_class).to receive(:postgresql?).and_return(true)
+ allow(described_class).to receive(:version).and_return('9.3.1')
+
+ expect(described_class.replication_slots_supported?).to eq(false)
+ end
+
+ it 'returns true when using PostgreSQL 9.4.0 or newer' do
+ allow(described_class).to receive(:postgresql?).and_return(true)
+ allow(described_class).to receive(:version).and_return('9.4.0')
+
+ expect(described_class.replication_slots_supported?).to eq(true)
+ end
+ end
+
describe '.nulls_last_order' do
context 'when using PostgreSQL' do
before do
diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb
index 9f4e3c49adc..5ed639543e0 100644
--- a/spec/lib/gitlab/git/commit_spec.rb
+++ b/spec/lib/gitlab/git/commit_spec.rb
@@ -278,6 +278,35 @@ describe Gitlab::Git::Commit, seed_helper: true do
it { is_expected.not_to include(SeedRepo::FirstCommit::ID) }
end
+ shared_examples '.shas_with_signatures' do
+ let(:signed_shas) { %w[5937ac0a7beb003549fc5fd26fc247adbce4a52e 570e7b2abdd848b95f2f578043fc23bd6f6fd24d] }
+ let(:unsigned_shas) { %w[19e2e9b4ef76b422ce1154af39a91323ccc57434 c642fe9b8b9f28f9225d7ea953fe14e74748d53b] }
+ let(:first_signed_shas) { %w[5937ac0a7beb003549fc5fd26fc247adbce4a52e c642fe9b8b9f28f9225d7ea953fe14e74748d53b] }
+
+ it 'has 2 signed shas' do
+ ret = described_class.shas_with_signatures(repository, signed_shas)
+ expect(ret).to eq(signed_shas)
+ end
+
+ it 'has 0 signed shas' do
+ ret = described_class.shas_with_signatures(repository, unsigned_shas)
+ expect(ret).to eq([])
+ end
+
+ it 'has 1 signed sha' do
+ ret = described_class.shas_with_signatures(repository, first_signed_shas)
+ expect(ret).to contain_exactly(first_signed_shas.first)
+ end
+ end
+
+ describe '.shas_with_signatures with gitaly on' do
+ it_should_behave_like '.shas_with_signatures'
+ end
+
+ describe '.shas_with_signatures with gitaly disabled', :disable_gitaly do
+ it_should_behave_like '.shas_with_signatures'
+ end
+
describe '.find_all' do
shared_examples 'finding all commits' do
it 'should return a return a collection of commits' do
diff --git a/spec/models/appearance_spec.rb b/spec/models/appearance_spec.rb
index 49f44525b29..56b5d616284 100644
--- a/spec/models/appearance_spec.rb
+++ b/spec/models/appearance_spec.rb
@@ -5,9 +5,6 @@ describe Appearance do
it { is_expected.to be_valid }
- it { is_expected.to validate_presence_of(:title) }
- it { is_expected.to validate_presence_of(:description) }
-
it { is_expected.to have_many(:uploads).dependent(:destroy) }
describe '.current', :use_clean_rails_memory_store_caching do
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 9070692abfe..26d33663dad 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -1921,4 +1921,77 @@ describe Ci::Build do
end
end
end
+
+ describe '.matches_tag_ids' do
+ set(:build) { create(:ci_build, project: project, user: user) }
+ let(:tag_ids) { ::ActsAsTaggableOn::Tag.named_any(tag_list).ids }
+
+ subject { described_class.where(id: build).matches_tag_ids(tag_ids) }
+
+ before do
+ build.update(tag_list: build_tag_list)
+ end
+
+ context 'when have different tags' do
+ let(:build_tag_list) { %w(A B) }
+ let(:tag_list) { %w(C D) }
+
+ it "does not match a build" do
+ is_expected.not_to contain_exactly(build)
+ end
+ end
+
+ context 'when have a subset of tags' do
+ let(:build_tag_list) { %w(A B) }
+ let(:tag_list) { %w(A B C D) }
+
+ it "does match a build" do
+ is_expected.to contain_exactly(build)
+ end
+ end
+
+ context 'when build does not have tags' do
+ let(:build_tag_list) { [] }
+ let(:tag_list) { %w(C D) }
+
+ it "does match a build" do
+ is_expected.to contain_exactly(build)
+ end
+ end
+
+ context 'when does not have a subset of tags' do
+ let(:build_tag_list) { %w(A B C) }
+ let(:tag_list) { %w(C D) }
+
+ it "does not match a build" do
+ is_expected.not_to contain_exactly(build)
+ end
+ end
+ end
+
+ describe '.matches_tags' do
+ set(:build) { create(:ci_build, project: project, user: user) }
+
+ subject { described_class.where(id: build).with_any_tags }
+
+ before do
+ build.update(tag_list: tag_list)
+ end
+
+ context 'when does have tags' do
+ let(:tag_list) { %w(A B) }
+
+ it "does match a build" do
+ is_expected.to contain_exactly(build)
+ end
+ end
+
+ context 'when does not have tags' do
+ let(:tag_list) { [] }
+
+ it "does not match a build" do
+ is_expected.not_to contain_exactly(build)
+ end
+ end
+ end
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index af0c86abe86..d37e3d2c527 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -1372,39 +1372,49 @@ describe Repository do
end
describe '#revert' do
- let(:new_image_commit) { repository.commit('33f3729a45c02fc67d00adb1b8bca394b0e761d9') }
- let(:update_image_commit) { repository.commit('2f63565e7aac07bcdadb654e253078b727143ec4') }
- let(:message) { 'revert message' }
+ shared_examples 'reverting a commit' do
+ let(:new_image_commit) { repository.commit('33f3729a45c02fc67d00adb1b8bca394b0e761d9') }
+ let(:update_image_commit) { repository.commit('2f63565e7aac07bcdadb654e253078b727143ec4') }
+ let(:message) { 'revert message' }
- context 'when there is a conflict' do
- it 'raises an error' do
- expect { repository.revert(user, new_image_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
+ context 'when there is a conflict' do
+ it 'raises an error' do
+ expect { repository.revert(user, new_image_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
+ end
end
- end
- context 'when commit was already reverted' do
- it 'raises an error' do
- repository.revert(user, update_image_commit, 'master', message)
+ context 'when commit was already reverted' do
+ it 'raises an error' do
+ repository.revert(user, update_image_commit, 'master', message)
- expect { repository.revert(user, update_image_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
+ expect { repository.revert(user, update_image_commit, 'master', message) }.to raise_error(Gitlab::Git::Repository::CreateTreeError)
+ end
end
- end
- context 'when commit can be reverted' do
- it 'reverts the changes' do
- expect(repository.revert(user, update_image_commit, 'master', message)).to be_truthy
+ context 'when commit can be reverted' do
+ it 'reverts the changes' do
+ expect(repository.revert(user, update_image_commit, 'master', message)).to be_truthy
+ end
end
- end
- context 'reverting a merge commit' do
- it 'reverts the changes' do
- merge_commit
- expect(repository.blob_at_branch('master', 'files/ruby/feature.rb')).to be_present
+ context 'reverting a merge commit' do
+ it 'reverts the changes' do
+ merge_commit
+ expect(repository.blob_at_branch('master', 'files/ruby/feature.rb')).to be_present
- repository.revert(user, merge_commit, 'master', message)
- expect(repository.blob_at_branch('master', 'files/ruby/feature.rb')).not_to be_present
+ repository.revert(user, merge_commit, 'master', message)
+ expect(repository.blob_at_branch('master', 'files/ruby/feature.rb')).not_to be_present
+ end
end
end
+
+ context 'when Gitaly revert feature is enabled' do
+ it_behaves_like 'reverting a commit'
+ end
+
+ context 'when Gitaly revert feature is disabled', :disable_gitaly do
+ it_behaves_like 'reverting a commit'
+ end
end
describe '#cherry_pick' do
diff --git a/spec/services/ci/register_job_service_spec.rb b/spec/services/ci/register_job_service_spec.rb
index 5ac30111ec9..decdd577226 100644
--- a/spec/services/ci/register_job_service_spec.rb
+++ b/spec/services/ci/register_job_service_spec.rb
@@ -15,16 +15,14 @@ module Ci
describe '#execute' do
context 'runner follow tag list' do
it "picks build with the same tag" do
- pending_job.tag_list = ["linux"]
- pending_job.save
- specific_runner.tag_list = ["linux"]
+ pending_job.update(tag_list: ["linux"])
+ specific_runner.update(tag_list: ["linux"])
expect(execute(specific_runner)).to eq(pending_job)
end
it "does not pick build with different tag" do
- pending_job.tag_list = ["linux"]
- pending_job.save
- specific_runner.tag_list = ["win32"]
+ pending_job.update(tag_list: ["linux"])
+ specific_runner.update(tag_list: ["win32"])
expect(execute(specific_runner)).to be_falsey
end
@@ -33,13 +31,12 @@ module Ci
end
it "does not pick build with tag" do
- pending_job.tag_list = ["linux"]
- pending_job.save
+ pending_job.update(tag_list: ["linux"])
expect(execute(specific_runner)).to be_falsey
end
it "pick build without tag" do
- specific_runner.tag_list = ["win32"]
+ specific_runner.update(tag_list: ["win32"])
expect(execute(specific_runner)).to eq(pending_job)
end
end
@@ -172,7 +169,7 @@ module Ci
context 'when first build is stalled' do
before do
- pending_job.lock_version = 10
+ pending_job.update(lock_version: 0)
end
subject { described_class.new(specific_runner).execute }
@@ -182,7 +179,7 @@ module Ci
before do
allow_any_instance_of(Ci::RegisterJobService).to receive(:builds_for_specific_runner)
- .and_return([pending_job, other_build])
+ .and_return(Ci::Build.where(id: [pending_job, other_build]))
end
it "receives second build from the queue" do
@@ -194,7 +191,7 @@ module Ci
context 'when single build is in queue' do
before do
allow_any_instance_of(Ci::RegisterJobService).to receive(:builds_for_specific_runner)
- .and_return([pending_job])
+ .and_return(Ci::Build.where(id: pending_job))
end
it "does not receive any valid result" do
@@ -205,7 +202,7 @@ module Ci
context 'when there is no build in queue' do
before do
allow_any_instance_of(Ci::RegisterJobService).to receive(:builds_for_specific_runner)
- .and_return([])
+ .and_return(Ci::Build.none)
end
it "does not receive builds but result is valid" do