summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/notes.js4
-rw-r--r--app/assets/stylesheets/framework/avatar.scss4
-rw-r--r--app/controllers/concerns/notes_actions.rb22
-rw-r--r--app/controllers/projects/branches_controller.rb2
-rw-r--r--app/helpers/diff_helper.rb2
-rw-r--r--app/helpers/notes_helper.rb6
-rw-r--r--app/services/git_push_service.rb31
-rw-r--r--app/views/shared/notes/_form.html.haml1
-rw-r--r--changelogs/unreleased/12673-fix_v3_project_hooks_build_events4
-rw-r--r--changelogs/unreleased/35044-projects-logo-are-not-centered-vertically-on-projects-page.yml4
-rw-r--r--changelogs/unreleased/35695-comment-appears-in-a-wrong-place-after-changing-diff-view-to-inline.yml4
-rw-r--r--changelogs/unreleased/dm-large-push-performance.yml4
-rw-r--r--changelogs/unreleased/fix-replying-to-commit-comment-in-mr-from-fork.yml4
-rw-r--r--config/initializers/1_settings.rb2
-rw-r--r--doc/administration/high_availability/nfs.md4
-rw-r--r--doc/api/users.md40
-rw-r--r--doc/ci/yaml/README.md21
-rw-r--r--doc/development/ux_guide/copy.md8
-rw-r--r--doc/user/project/integrations/jira.md21
-rw-r--r--lib/api/helpers/related_resources_helpers.rb2
-rw-r--r--lib/api/v3/project_hooks.rb8
-rw-r--r--lib/gitlab/data_builder/push.rb4
-rw-r--r--spec/controllers/projects/notes_controller_spec.rb62
-rw-r--r--spec/features/dashboard/issues_spec.rb12
-rw-r--r--spec/features/issues/create_branch_merge_request_spec.rb10
-rw-r--r--spec/features/merge_requests/created_from_fork_spec.rb27
-rw-r--r--spec/features/projects/branches_spec.rb6
-rw-r--r--spec/helpers/diff_helper_spec.rb17
-rw-r--r--spec/models/project_wiki_spec.rb2
-rw-r--r--spec/requests/api/v3/project_hooks_spec.rb6
-rw-r--r--spec/services/git_push_service_spec.rb6
-rw-r--r--spec/spec_helper.rb1
-rw-r--r--spec/support/capybara.rb9
33 files changed, 276 insertions, 84 deletions
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index b2c503d1656..dfa07a2def4 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -529,6 +529,7 @@ export default class Notes {
form.find('#note_line_code').remove();
form.find('#note_position').remove();
form.find('#note_type').val('');
+ form.find('#note_project_id').remove();
form.find('#in_reply_to_discussion_id').remove();
form.find('.js-comment-resolve-button').closest('comment-and-resolve-btn').remove();
this.parentTimeline = form.parents('.timeline');
@@ -556,6 +557,7 @@ export default class Notes {
form.find('#note_noteable_id').val(),
form.find('#note_commit_id').val(),
form.find('#note_type').val(),
+ form.find('#note_project_id').val(),
form.find('#in_reply_to_discussion_id').val(),
// LegacyDiffNote
@@ -848,6 +850,8 @@ export default class Notes {
form.find('#in_reply_to_discussion_id').val(discussionID);
}
+ form.find('#note_project_id').val(dataHolder.data('discussionProjectId'));
+
form.attr('data-line-code', dataHolder.data('lineCode'));
form.find('#line_type').val(dataHolder.data('lineType'));
diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss
index 0dfa7a31d31..cb41df8a88d 100644
--- a/app/assets/stylesheets/framework/avatar.scss
+++ b/app/assets/stylesheets/framework/avatar.scss
@@ -88,6 +88,10 @@
overflow: hidden;
display: flex;
+ a {
+ display: flex;
+ }
+
.avatar {
border-radius: 0;
border: none;
diff --git a/app/controllers/concerns/notes_actions.rb b/app/controllers/concerns/notes_actions.rb
index a57d9e6e6c0..af5f683bab5 100644
--- a/app/controllers/concerns/notes_actions.rb
+++ b/app/controllers/concerns/notes_actions.rb
@@ -4,6 +4,7 @@ module NotesActions
included do
before_action :authorize_admin_note!, only: [:update, :destroy]
+ before_action :note_project, only: [:create]
end
def index
@@ -28,7 +29,8 @@ module NotesActions
merge_request_diff_head_sha: params[:merge_request_diff_head_sha],
in_reply_to_discussion_id: params[:in_reply_to_discussion_id]
)
- @note = Notes::CreateService.new(project, current_user, create_params).execute
+
+ @note = Notes::CreateService.new(note_project, current_user, create_params).execute
if @note.is_a?(Note)
Banzai::NoteRenderer.render([@note], @project, current_user)
@@ -177,4 +179,22 @@ module NotesActions
def notes_finder
@notes_finder ||= NotesFinder.new(project, current_user, finder_params)
end
+
+ def note_project
+ return @note_project if defined?(@note_project)
+ return nil unless project
+
+ note_project_id = params[:note_project_id]
+
+ @note_project =
+ if note_project_id.present?
+ Project.find(note_project_id)
+ else
+ project
+ end
+
+ return access_denied! unless can?(current_user, :create_note, @note_project)
+
+ @note_project
+ end
end
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index 86058531179..747768eefb1 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -8,7 +8,7 @@ class Projects::BranchesController < Projects::ApplicationController
before_action :authorize_push_code!, only: [:new, :create, :destroy, :destroy_all_merged]
def index
- @sort = params[:sort].presence || sort_value_name
+ @sort = params[:sort].presence || sort_value_recently_updated
@branches = BranchesFinder.new(@repository, params).execute
@branches = Kaminari.paginate_array(@branches).page(params[:page])
diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb
index 926502bf239..91ddd73fac1 100644
--- a/app/helpers/diff_helper.rb
+++ b/app/helpers/diff_helper.rb
@@ -15,7 +15,7 @@ module DiffHelper
def diff_view
@diff_view ||= begin
diff_views = %w(inline parallel)
- diff_view = cookies[:diff_view]
+ diff_view = params[:view] || cookies[:diff_view]
diff_view = diff_views.first unless diff_views.include?(diff_view)
diff_view.to_sym
end
diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb
index 505579674c9..e857e837c16 100644
--- a/app/helpers/notes_helper.rb
+++ b/app/helpers/notes_helper.rb
@@ -62,7 +62,11 @@ module NotesHelper
def link_to_reply_discussion(discussion, line_type = nil)
return unless current_user
- data = { discussion_id: discussion.reply_id, line_type: line_type }
+ data = {
+ discussion_id: discussion.reply_id,
+ discussion_project_id: discussion.project&.id,
+ line_type: line_type
+ }
button_tag 'Reply...', class: 'btn btn-text-field js-discussion-reply-button',
data: data, title: 'Add a reply'
diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb
index bb7680c5054..ada2b64a3a6 100644
--- a/app/services/git_push_service.rb
+++ b/app/services/git_push_service.rb
@@ -45,6 +45,7 @@ class GitPushService < BaseService
elsif push_to_existing_branch?
# Collect data for this git push
@push_commits = @project.repository.commits_between(params[:oldrev], params[:newrev])
+
process_commit_messages
# Update the bare repositories info/attributes file using the contents of the default branches
@@ -66,15 +67,21 @@ class GitPushService < BaseService
def update_caches
if is_default_branch?
- paths = Set.new
+ if push_to_new_branch?
+ # If this is the initial push into the default branch, the file type caches
+ # will already be reset as a result of `Project#change_head`.
+ types = []
+ else
+ paths = Set.new
- @push_commits.each do |commit|
- commit.raw_deltas.each do |diff|
- paths << diff.new_path
+ @push_commits.last(PROCESS_COMMIT_LIMIT).each do |commit|
+ commit.raw_deltas.each do |diff|
+ paths << diff.new_path
+ end
end
- end
- types = Gitlab::FileDetector.types_in_paths(paths.to_a)
+ types = Gitlab::FileDetector.types_in_paths(paths.to_a)
+ end
else
types = []
end
@@ -92,7 +99,7 @@ class GitPushService < BaseService
def process_commit_messages
default = is_default_branch?
- push_commits.last(PROCESS_COMMIT_LIMIT).each do |commit|
+ @push_commits.last(PROCESS_COMMIT_LIMIT).each do |commit|
if commit.matches_cross_reference_regex?
ProcessCommitWorker
.perform_async(project.id, current_user.id, commit.to_hash, default)
@@ -111,7 +118,7 @@ class GitPushService < BaseService
EventCreateService.new.push(@project, current_user, build_push_data)
Ci::CreatePipelineService.new(@project, current_user, build_push_data).execute(:push)
-
+
SystemHookPushWorker.perform_async(build_push_data.dup, :push_hooks)
@project.execute_hooks(build_push_data.dup, :push_hooks)
@project.execute_services(build_push_data.dup, :push_hooks)
@@ -131,7 +138,10 @@ class GitPushService < BaseService
end
def process_default_branch
- @push_commits = project.repository.commits(params[:newrev])
+ @push_commits_count = project.repository.commit_count_for_ref(params[:ref])
+
+ offset = [@push_commits_count - PROCESS_COMMIT_LIMIT, 0].max
+ @push_commits = project.repository.commits(params[:newrev], offset: offset, limit: PROCESS_COMMIT_LIMIT)
# Ensure HEAD points to the default branch in case it is not master
project.change_head(branch_name)
@@ -160,7 +170,8 @@ class GitPushService < BaseService
params[:oldrev],
params[:newrev],
params[:ref],
- push_commits)
+ @push_commits,
+ commits_count: @push_commits_count)
end
def push_to_existing_branch?
diff --git a/app/views/shared/notes/_form.html.haml b/app/views/shared/notes/_form.html.haml
index c6b5dcc3647..725bf916592 100644
--- a/app/views/shared/notes/_form.html.haml
+++ b/app/views/shared/notes/_form.html.haml
@@ -10,6 +10,7 @@
= hidden_field_tag :line_type
= hidden_field_tag :merge_request_diff_head_sha, @note.noteable.try(:diff_head_sha)
= hidden_field_tag :in_reply_to_discussion_id
+ = hidden_field_tag :note_project_id
= note_target_fields(@note)
= f.hidden_field :noteable_type
diff --git a/changelogs/unreleased/12673-fix_v3_project_hooks_build_events b/changelogs/unreleased/12673-fix_v3_project_hooks_build_events
new file mode 100644
index 00000000000..59bc646406f
--- /dev/null
+++ b/changelogs/unreleased/12673-fix_v3_project_hooks_build_events
@@ -0,0 +1,4 @@
+---
+title: "Fix v3 api project_hooks POST and PUT operations for build_events"
+merge_request: 12673
+author: Richard Clamp
diff --git a/changelogs/unreleased/35044-projects-logo-are-not-centered-vertically-on-projects-page.yml b/changelogs/unreleased/35044-projects-logo-are-not-centered-vertically-on-projects-page.yml
new file mode 100644
index 00000000000..9de4dbefd35
--- /dev/null
+++ b/changelogs/unreleased/35044-projects-logo-are-not-centered-vertically-on-projects-page.yml
@@ -0,0 +1,4 @@
+---
+title: Fix project logos that are not centered vertically on list pages
+merge_request: 13124
+author: Florian Lemaitre
diff --git a/changelogs/unreleased/35695-comment-appears-in-a-wrong-place-after-changing-diff-view-to-inline.yml b/changelogs/unreleased/35695-comment-appears-in-a-wrong-place-after-changing-diff-view-to-inline.yml
new file mode 100644
index 00000000000..1c9ad20bc95
--- /dev/null
+++ b/changelogs/unreleased/35695-comment-appears-in-a-wrong-place-after-changing-diff-view-to-inline.yml
@@ -0,0 +1,4 @@
+---
+title: Fix display of new diff comments after changing b between diff views
+merge_request:
+author:
diff --git a/changelogs/unreleased/dm-large-push-performance.yml b/changelogs/unreleased/dm-large-push-performance.yml
new file mode 100644
index 00000000000..f5fe1bd3b28
--- /dev/null
+++ b/changelogs/unreleased/dm-large-push-performance.yml
@@ -0,0 +1,4 @@
+---
+title: Improve performance of large (initial) push into default branch
+merge_request:
+author:
diff --git a/changelogs/unreleased/fix-replying-to-commit-comment-in-mr-from-fork.yml b/changelogs/unreleased/fix-replying-to-commit-comment-in-mr-from-fork.yml
new file mode 100644
index 00000000000..f4136460626
--- /dev/null
+++ b/changelogs/unreleased/fix-replying-to-commit-comment-in-mr-from-fork.yml
@@ -0,0 +1,4 @@
+---
+title: Fix replying to commit comments on merge requests created from forks
+merge_request:
+author:
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 02d3161f769..63f4c8c9e0a 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -223,7 +223,7 @@ Settings.gitlab['default_can_create_group'] = true if Settings.gitlab['default_c
Settings.gitlab['host'] ||= ENV['GITLAB_HOST'] || 'localhost'
Settings.gitlab['ssh_host'] ||= Settings.gitlab.host
Settings.gitlab['https'] = false if Settings.gitlab['https'].nil?
-Settings.gitlab['port'] ||= Settings.gitlab.https ? 443 : 80
+Settings.gitlab['port'] ||= ENV['GITLAB_PORT'] || (Settings.gitlab.https ? 443 : 80)
Settings.gitlab['relative_url_root'] ||= ENV['RAILS_RELATIVE_URL_ROOT'] || ''
Settings.gitlab['protocol'] ||= Settings.gitlab.https ? "https" : "http"
Settings.gitlab['email_enabled'] ||= true if Settings.gitlab['email_enabled'].nil?
diff --git a/doc/administration/high_availability/nfs.md b/doc/administration/high_availability/nfs.md
index bd6b7327aed..90a2e9298bf 100644
--- a/doc/administration/high_availability/nfs.md
+++ b/doc/administration/high_availability/nfs.md
@@ -46,6 +46,10 @@ GitLab does not recommend using EFS with GitLab.
many small files are written in a serialized manner are not well-suited for EFS.
EBS with an NFS server on top will perform much better.
+In addition, avoid storing GitLab log files (e.g. those in `/var/log/gitlab`)
+because this will also affect performance. We recommend that the log files be
+stored on a local volume.
+
For more details on another person's experience with EFS, see
[Amazon's Elastic File System: Burst Credits](https://www.rawkode.io/2017/04/amazons-elastic-file-system-burst-credits/)
diff --git a/doc/api/users.md b/doc/api/users.md
index 6e5ec3231c5..57a13eb477d 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -241,26 +241,26 @@ POST /users
Parameters:
-- `email` (required) - Email
-- `password` (optional) - Password
-- `reset_password` (optional) - Send user password reset link - true or false(default)
-- `username` (required) - Username
-- `name` (required) - Name
-- `skype` (optional) - Skype ID
-- `linkedin` (optional) - LinkedIn
-- `twitter` (optional) - Twitter account
-- `website_url` (optional) - Website URL
-- `organization` (optional) - Organization name
-- `projects_limit` (optional) - Number of projects user can create
-- `extern_uid` (optional) - External UID
-- `provider` (optional) - External provider name
-- `bio` (optional) - User's biography
-- `location` (optional) - User's location
-- `admin` (optional) - User is admin - true or false (default)
-- `can_create_group` (optional) - User can create groups - true or false
-- `confirm` (optional) - Require confirmation - true (default) or false
-- `external` (optional) - Flags the user as external - true or false(default)
-- `avatar` (optional) - Image file for user's avatar
+- `email` (required) - Email
+- `password` (optional) - Password
+- `reset_password` (optional) - Send user password reset link - true or false(default)
+- `username` (required) - Username
+- `name` (required) - Name
+- `skype` (optional) - Skype ID
+- `linkedin` (optional) - LinkedIn
+- `twitter` (optional) - Twitter account
+- `website_url` (optional) - Website URL
+- `organization` (optional) - Organization name
+- `projects_limit` (optional) - Number of projects user can create
+- `extern_uid` (optional) - External UID
+- `provider` (optional) - External provider name
+- `bio` (optional) - User's biography
+- `location` (optional) - User's location
+- `admin` (optional) - User is admin - true or false (default)
+- `can_create_group` (optional) - User can create groups - true or false
+- `skip_confirmation` (optional) - Skip confirmation - true or false (default)
+- `external` (optional) - Flags the user as external - true or false(default)
+- `avatar` (optional) - Image file for user's avatar
## User modification
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index e12ef6e2685..1869782fe6e 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -441,13 +441,25 @@ There are a few rules that apply to the usage of refs policy:
* `only` and `except` are inclusive. If both `only` and `except` are defined
in a job specification, the ref is filtered by `only` and `except`.
* `only` and `except` allow the use of regular expressions.
-* `only` and `except` allow the use of special keywords:
-`api`, `branches`, `external`, `tags`, `pushes`, `schedules`, `triggers`, and `web`
* `only` and `except` allow to specify a repository path to filter jobs for
forks.
+In addition, `only` and `except` allow the use of special keywords:
+
+| **Value** | **Description** |
+| --------- | ---------------- |
+| `branches` | When a branch is pushed. |
+| `tags` | When a tag is pushed. |
+| `api` | When pipeline has been triggered by a second pipelines API (not triggers API). |
+| `external` | When using CI services other than GitLab. |
+| `pipelines` | For multi-project triggers, created using the API with `CI_JOB_TOKEN`. |
+| `pushes` | Pipeline is triggered by a `git push` by the user. |
+| `schedules` | For [scheduled pipelines][schedules]. |
+| `triggers` | For pipelines created using a trigger token. |
+| `web` | For pipelines created using **Run pipeline** button in GitLab UI (under your project's **Pipelines**). |
+
In the example below, `job` will run only for refs that start with `issue-`,
-whereas all branches will be skipped.
+whereas all branches will be skipped:
```yaml
job:
@@ -460,7 +472,7 @@ job:
```
In this example, `job` will run only for refs that are tagged, or if a build is
-explicitly requested via an API trigger or a [Pipeline Schedule](../../user/project/pipelines/schedules.md).
+explicitly requested via an API trigger or a [Pipeline Schedule][schedules]:
```yaml
job:
@@ -1532,3 +1544,4 @@ CI with various languages.
[ce-7983]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7983
[ce-7447]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/7447
[ce-3442]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/3442
+[schedules]: ../../user/project/pipelines/schedules.md
diff --git a/doc/development/ux_guide/copy.md b/doc/development/ux_guide/copy.md
index 794c8eb6bfe..12e8d0a31bb 100644
--- a/doc/development/ux_guide/copy.md
+++ b/doc/development/ux_guide/copy.md
@@ -106,6 +106,14 @@ When using verbs or adjectives:
* If the context clearly refers to the object, use them alone. Example: `Edit` or `Closed`
* If the context isn’t clear enough, use them with the object. Example: `Edit issue` or `Closed issues`
+### Search
+
+| Term | Use |
+| ---- | --- |
+| Search | When using all metadata to add criteria that match/don't match. Search can also affect ordering, by ranking best results. |
+| Filter | When taking a single criteria that removes items within a list that match/don't match. Filters do not affect ordering. |
+| Sort | Orders a list based on a single or grouped criteria |
+
### Projects and Groups
| Term | Use | :no_entry_sign: Don't |
diff --git a/doc/user/project/integrations/jira.md b/doc/user/project/integrations/jira.md
index cfa4c8a93f8..4f583879a4e 100644
--- a/doc/user/project/integrations/jira.md
+++ b/doc/user/project/integrations/jira.md
@@ -1,18 +1,22 @@
# GitLab JIRA integration
-GitLab can be configured to interact with JIRA. Configuration happens via
-user name and password. Connecting to a JIRA server via CAS is not possible.
+GitLab can be configured to interact with [JIRA], a project management platform.
-Each project can be configured to connect to a different JIRA instance, see the
-[configuration](#configuration) section. If you have one JIRA instance you can
-pre-fill the settings page with a default template. To configure the template
-see the [Services Templates][services-templates] document.
+Once your GitLab project is connected to JIRA, you can reference and close the
+issues in JIRA directly from GitLab.
-Once the project is connected to JIRA, you can reference and close the issues
-in JIRA directly from GitLab.
+For a use case, check out this article of [How and why to integrate GitLab with
+JIRA](https://www.programmableweb.com/news/how-and-why-to-integrate-gitlab-jira/how-to/2017/04/25).
## Configuration
+Each GitLab project can be configured to connect to a different JIRA instance.
+If you have one JIRA instance you can pre-fill the settings page with a default
+template, see the [Services Templates][services-templates] docs.
+
+Configuration happens via user name and password. Connecting to a JIRA server
+via CAS is not possible.
+
In order to enable the JIRA service in GitLab, you need to first configure the
project in JIRA and then enter the correct values in GitLab.
@@ -213,3 +217,4 @@ your project needs to close a ticket.
[services-templates]: services_templates.md
[jira-repo-old-docs]: https://gitlab.com/gitlab-org/gitlab-ce/blob/8-13-stable/doc/project_services/jira.md
+[jira]: https://www.atlassian.com/software/jira
diff --git a/lib/api/helpers/related_resources_helpers.rb b/lib/api/helpers/related_resources_helpers.rb
index 769cc1457fc..1f677529b07 100644
--- a/lib/api/helpers/related_resources_helpers.rb
+++ b/lib/api/helpers/related_resources_helpers.rb
@@ -12,7 +12,7 @@ module API
end
def expose_url(path)
- url_options = Rails.application.routes.default_url_options
+ url_options = Gitlab::Application.routes.default_url_options
protocol, host, port = url_options.slice(:protocol, :host, :port).values
URI::HTTP.build(scheme: protocol, host: host, port: port, path: path).to_s
diff --git a/lib/api/v3/project_hooks.rb b/lib/api/v3/project_hooks.rb
index 94614bfc8b6..51014591a93 100644
--- a/lib/api/v3/project_hooks.rb
+++ b/lib/api/v3/project_hooks.rb
@@ -56,7 +56,9 @@ module API
use :project_hook_properties
end
post ":id/hooks" do
- hook = user_project.hooks.new(declared_params(include_missing: false))
+ attrs = declared_params(include_missing: false)
+ attrs[:job_events] = attrs.delete(:build_events) if attrs.key?(:build_events)
+ hook = user_project.hooks.new(attrs)
if hook.save
present hook, with: ::API::V3::Entities::ProjectHook
@@ -77,7 +79,9 @@ module API
put ":id/hooks/:hook_id" do
hook = user_project.hooks.find(params.delete(:hook_id))
- if hook.update_attributes(declared_params(include_missing: false))
+ attrs = declared_params(include_missing: false)
+ attrs[:job_events] = attrs.delete(:build_events) if attrs.key?(:build_events)
+ if hook.update_attributes(attrs)
present hook, with: ::API::V3::Entities::ProjectHook
else
error!("Invalid url given", 422) if hook.errors[:url].present?
diff --git a/lib/gitlab/data_builder/push.rb b/lib/gitlab/data_builder/push.rb
index 8c8729b6557..5c5f507d44d 100644
--- a/lib/gitlab/data_builder/push.rb
+++ b/lib/gitlab/data_builder/push.rb
@@ -24,11 +24,11 @@ module Gitlab
# total_commits_count: Fixnum
# }
#
- def build(project, user, oldrev, newrev, ref, commits = [], message = nil)
+ def build(project, user, oldrev, newrev, ref, commits = [], message = nil, commits_count: nil)
commits = Array(commits)
# Total commits count
- commits_count = commits.size
+ commits_count ||= commits.size
# Get latest 20 commits ASC
commits_limited = commits.last(20)
diff --git a/spec/controllers/projects/notes_controller_spec.rb b/spec/controllers/projects/notes_controller_spec.rb
index 45f4cf9180d..3b88d5b0d7d 100644
--- a/spec/controllers/projects/notes_controller_spec.rb
+++ b/spec/controllers/projects/notes_controller_spec.rb
@@ -131,7 +131,7 @@ describe Projects::NotesController do
before do
sign_in(user)
- project.team << [user, :developer]
+ project.add_developer(user)
end
it "returns status 302 for html" do
@@ -165,6 +165,66 @@ describe Projects::NotesController do
expect(response).to have_http_status(302)
end
end
+
+ context 'when creating a commit comment from an MR fork' do
+ let(:project) { create(:project) }
+
+ let(:fork_project) do
+ create(:project).tap do |fork|
+ create(:forked_project_link, forked_to_project: fork, forked_from_project: project)
+ end
+ end
+
+ let(:merge_request) do
+ create(:merge_request, source_project: fork_project, target_project: project, source_branch: 'feature', target_branch: 'master')
+ end
+
+ let(:existing_comment) do
+ create(:note_on_commit, note: 'a note', project: fork_project, commit_id: merge_request.commit_shas.first)
+ end
+
+ def post_create(extra_params = {})
+ post :create, {
+ note: { note: 'some other note' },
+ namespace_id: project.namespace,
+ project_id: project,
+ target_type: 'merge_request',
+ target_id: merge_request.id,
+ note_project_id: fork_project.id,
+ in_reply_to_discussion_id: existing_comment.discussion_id
+ }.merge(extra_params)
+ end
+
+ context 'when the note_project_id is not correct' do
+ it 'returns a 404' do
+ post_create(note_project_id: Project.maximum(:id).succ)
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'when the user has no access to the fork' do
+ it 'returns a 404' do
+ post_create
+
+ expect(response).to have_http_status(404)
+ end
+ end
+
+ context 'when the user has access to the fork' do
+ let(:discussion) { fork_project.notes.find_discussion(existing_comment.discussion_id) }
+
+ before do
+ fork_project.add_developer(user)
+
+ existing_comment
+ end
+
+ it 'creates the note' do
+ expect { post_create }.to change { fork_project.notes.count }.by(1)
+ end
+ end
+ end
end
describe 'DELETE destroy' do
diff --git a/spec/features/dashboard/issues_spec.rb b/spec/features/dashboard/issues_spec.rb
index 7c0bf8de14c..82adde6258f 100644
--- a/spec/features/dashboard/issues_spec.rb
+++ b/spec/features/dashboard/issues_spec.rb
@@ -79,15 +79,7 @@ RSpec.describe 'Dashboard Issues' do
end
end
- it 'shows the new issue page', js: true do
- original_defaults = Gitlab::Application.routes.default_url_options
-
- Gitlab::Application.routes.default_url_options = {
- host: Capybara.current_session.server.host,
- port: Capybara.current_session.server.port,
- protocol: 'http'
- }
-
+ it 'shows the new issue page', :js do
find('.new-project-item-select-button').trigger('click')
wait_for_requests
find('.select2-results li').click
@@ -97,8 +89,6 @@ RSpec.describe 'Dashboard Issues' do
page.within('#content-body') do
expect(page).to have_selector('.issue-form')
end
-
- Gitlab::Application.routes.default_url_options = original_defaults
end
end
end
diff --git a/spec/features/issues/create_branch_merge_request_spec.rb b/spec/features/issues/create_branch_merge_request_spec.rb
index c10b99a4386..f59f687cf51 100644
--- a/spec/features/issues/create_branch_merge_request_spec.rb
+++ b/spec/features/issues/create_branch_merge_request_spec.rb
@@ -15,16 +15,14 @@ feature 'Create Branch/Merge Request Dropdown on issue page', js: true do
visit project_issue_path(project, issue)
select_dropdown_option('create-mr')
+
+ expect(page).to have_content('WIP: Resolve "Cherry-Coloured Funk"')
+ expect(current_path).to eq(project_merge_request_path(project, MergeRequest.first))
- wait_for_requests
+ visit project_issue_path(project, issue)
expect(page).to have_content("created branch 1-cherry-coloured-funk")
expect(page).to have_content("mentioned in merge request !1")
-
- visit project_merge_request_path(project, MergeRequest.first)
-
- expect(page).to have_content('WIP: Resolve "Cherry-Coloured Funk"')
- expect(current_path).to eq(project_merge_request_path(project, MergeRequest.first))
end
it 'allows creating a branch from the issue page' do
diff --git a/spec/features/merge_requests/created_from_fork_spec.rb b/spec/features/merge_requests/created_from_fork_spec.rb
index 68d793ec9ba..09541873f71 100644
--- a/spec/features/merge_requests/created_from_fork_spec.rb
+++ b/spec/features/merge_requests/created_from_fork_spec.rb
@@ -25,6 +25,33 @@ feature 'Merge request created from fork' do
expect(page).to have_content 'Test merge request'
end
+ context 'when a commit comment exists on the merge request' do
+ given(:comment) { 'A commit comment' }
+ given(:reply) { 'A reply comment' }
+
+ background do
+ create(:note_on_commit, note: comment,
+ project: fork_project,
+ commit_id: merge_request.commit_shas.first)
+ end
+
+ scenario 'user can reply to the comment', js: true do
+ visit_merge_request(merge_request)
+
+ expect(page).to have_content(comment)
+
+ page.within('.discussion-notes') do
+ find('.btn-text-field').click
+ find('#note_note').send_keys(reply)
+ find('.comment-btn').click
+ end
+
+ wait_for_requests
+
+ expect(page).to have_content(reply)
+ end
+ end
+
context 'source project is deleted' do
background do
MergeRequests::MergeService.new(project, user).execute(merge_request)
diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb
index 6e787de2dd6..ad4527a0b74 100644
--- a/spec/features/projects/branches_spec.rb
+++ b/spec/features/projects/branches_spec.rb
@@ -29,7 +29,7 @@ describe 'Branches' do
it 'sorts the branches by name' do
visit project_branches_path(project)
- click_button "Name" # Open sorting dropdown
+ click_button "Last updated" # Open sorting dropdown
click_link "Name"
sorted = repository.branches_sorted_by(:name).first(20).map do |branch|
@@ -41,7 +41,7 @@ describe 'Branches' do
it 'sorts the branches by last updated' do
visit project_branches_path(project)
- click_button "Name" # Open sorting dropdown
+ click_button "Last updated" # Open sorting dropdown
click_link "Last updated"
sorted = repository.branches_sorted_by(:updated_desc).first(20).map do |branch|
@@ -53,7 +53,7 @@ describe 'Branches' do
it 'sorts the branches by oldest updated' do
visit project_branches_path(project)
- click_button "Name" # Open sorting dropdown
+ click_button "Last updated" # Open sorting dropdown
click_link "Oldest updated"
sorted = repository.branches_sorted_by(:updated_asc).first(20).map do |branch|
diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb
index 0d909e6e140..060c112e20d 100644
--- a/spec/helpers/diff_helper_spec.rb
+++ b/spec/helpers/diff_helper_spec.rb
@@ -12,19 +12,32 @@ describe DiffHelper do
let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs: diff_refs, repository: repository) }
describe 'diff_view' do
+ it 'uses the view param over the cookie' do
+ controller.params[:view] = 'parallel'
+ helper.request.cookies[:diff_view] = 'inline'
+
+ expect(helper.diff_view).to eq :parallel
+ end
+
+ it 'returns the default value when the view param is invalid' do
+ controller.params[:view] = 'invalid'
+
+ expect(helper.diff_view).to eq :inline
+ end
+
it 'returns a valid value when cookie is set' do
helper.request.cookies[:diff_view] = 'parallel'
expect(helper.diff_view).to eq :parallel
end
- it 'returns a default value when cookie is invalid' do
+ it 'returns the default value when cookie is invalid' do
helper.request.cookies[:diff_view] = 'invalid'
expect(helper.diff_view).to eq :inline
end
- it 'returns a default value when cookie is nil' do
+ it 'returns the default value when cookie is nil' do
expect(helper.request.cookies).to be_empty
expect(helper.diff_view).to eq :inline
diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb
index 7fcbeb459e0..c6ceb092810 100644
--- a/spec/models/project_wiki_spec.rb
+++ b/spec/models/project_wiki_spec.rb
@@ -21,7 +21,7 @@ describe ProjectWiki do
describe '#web_url' do
it 'returns the full web URL to the wiki' do
- expect(subject.web_url).to match("https?://[^\/]+/#{project.path_with_namespace}/wikis/home")
+ expect(subject.web_url).to eq("#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/wikis/home")
end
end
diff --git a/spec/requests/api/v3/project_hooks_spec.rb b/spec/requests/api/v3/project_hooks_spec.rb
index 1969d1c7f2b..b0eddbb5dd2 100644
--- a/spec/requests/api/v3/project_hooks_spec.rb
+++ b/spec/requests/api/v3/project_hooks_spec.rb
@@ -87,7 +87,7 @@ describe API::ProjectHooks, 'ProjectHooks' do
it "adds hook to project" do
expect do
post v3_api("/projects/#{project.id}/hooks", user),
- url: "http://example.com", issues_events: true, wiki_page_events: true
+ url: "http://example.com", issues_events: true, wiki_page_events: true, build_events: true
end.to change {project.hooks.count}.by(1)
expect(response).to have_http_status(201)
@@ -97,7 +97,7 @@ describe API::ProjectHooks, 'ProjectHooks' do
expect(json_response['merge_requests_events']).to eq(false)
expect(json_response['tag_push_events']).to eq(false)
expect(json_response['note_events']).to eq(false)
- expect(json_response['build_events']).to eq(false)
+ expect(json_response['build_events']).to eq(true)
expect(json_response['pipeline_events']).to eq(false)
expect(json_response['wiki_page_events']).to eq(true)
expect(json_response['enable_ssl_verification']).to eq(true)
@@ -135,7 +135,7 @@ describe API::ProjectHooks, 'ProjectHooks' do
describe "PUT /projects/:id/hooks/:hook_id" do
it "updates an existing project hook" do
put v3_api("/projects/#{project.id}/hooks/#{hook.id}", user),
- url: 'http://example.org', push_events: false
+ url: 'http://example.org', push_events: false, build_events: true
expect(response).to have_http_status(200)
expect(json_response['url']).to eq('http://example.org')
expect(json_response['issues_events']).to eq(hook.issues_events)
diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb
index 4023c33aa59..3fb677b65be 100644
--- a/spec/services/git_push_service_spec.rb
+++ b/spec/services/git_push_service_spec.rb
@@ -658,8 +658,7 @@ describe GitPushService, services: true do
end
it 'only schedules a limited number of commits' do
- allow(service).to receive(:push_commits)
- .and_return(Array.new(1000, double(:commit, to_hash: {}, matches_cross_reference_regex?: true)))
+ service.push_commits = Array.new(1000, double(:commit, to_hash: {}, matches_cross_reference_regex?: true))
expect(ProcessCommitWorker).to receive(:perform_async).exactly(100).times
@@ -667,8 +666,7 @@ describe GitPushService, services: true do
end
it "skips commits which don't include cross-references" do
- allow(service).to receive(:push_commits)
- .and_return([double(:commit, to_hash: {}, matches_cross_reference_regex?: false)])
+ service.push_commits = [double(:commit, to_hash: {}, matches_cross_reference_regex?: false)]
expect(ProcessCommitWorker).not_to receive(:perform_async)
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index e7329210896..85335643921 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -59,6 +59,7 @@ RSpec.configure do |config|
config.include Gitlab::Routing, type: :routing
config.include MigrationsHelpers, :migration
config.include StubFeatureFlags
+ config.include StubENV
config.infer_spec_type_from_file_location!
diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb
index 3e5d6cf1364..c45c4a4310d 100644
--- a/spec/support/capybara.rb
+++ b/spec/support/capybara.rb
@@ -36,7 +36,14 @@ RSpec.configure do |config|
$capybara_server_already_started = true
end
- config.after(:each, :js) do |example|
+ config.before(:example, :js) do
+ allow(Gitlab::Application.routes).to receive(:default_url_options).and_return(
+ host: Capybara.current_session.server.host,
+ port: Capybara.current_session.server.port,
+ protocol: 'http')
+ end
+
+ config.after(:example, :js) do |example|
# capybara/rspec already calls Capybara.reset_sessions! in an `after` hook,
# but `block_and_wait_for_requests_complete` is called before it so by
# calling it explicitely here, we prevent any new requests from being fired