summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab-ci.yml5
-rw-r--r--.rubocop.yml18
-rw-r--r--.rubocop_todo.yml5
-rw-r--r--PROCESS.md16
-rw-r--r--app/assets/javascripts/diff_notes/diff_notes_bundle.js4
-rw-r--r--app/assets/javascripts/dispatcher.js2
-rw-r--r--app/assets/javascripts/fly_out_nav.js8
-rw-r--r--app/assets/javascripts/lib/utils/sticky.js2
-rw-r--r--app/assets/javascripts/main.js4
-rw-r--r--app/assets/javascripts/render_gfm.js4
-rw-r--r--app/assets/stylesheets/framework/nav.scss2
-rw-r--r--app/assets/stylesheets/new_sidebar.scss8
-rw-r--r--app/controllers/concerns/issuable_actions.rb2
-rw-r--r--app/controllers/groups/application_controller.rb2
-rw-r--r--app/controllers/import/github_controller.rb2
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb4
-rw-r--r--app/controllers/projects/cycle_analytics/events_controller.rb24
-rw-r--r--app/controllers/projects/merge_requests_controller.rb4
-rw-r--r--app/controllers/uploads_controller.rb2
-rw-r--r--app/helpers/commits_helper.rb6
-rw-r--r--app/helpers/import_helper.rb2
-rw-r--r--app/helpers/issuables_helper.rb13
-rw-r--r--app/helpers/milestones_helper.rb13
-rw-r--r--app/helpers/pipeline_schedules_helper.rb10
-rw-r--r--app/helpers/projects_helper.rb7
-rw-r--r--app/helpers/version_check_helper.rb2
-rw-r--r--app/models/blob_viewer/notebook.rb2
-rw-r--r--app/models/ci/build.rb5
-rw-r--r--app/models/commit.rb2
-rw-r--r--app/models/concerns/cache_markdown_field.rb6
-rw-r--r--app/models/concerns/internal_id.rb2
-rw-r--r--app/models/concerns/mentionable.rb4
-rw-r--r--app/models/concerns/participable.rb2
-rw-r--r--app/models/concerns/project_features_compatibility.rb2
-rw-r--r--app/models/deploy_keys_project.rb2
-rw-r--r--app/models/network/commit.rb2
-rw-r--r--app/models/project.rb10
-rw-r--r--app/models/project_services/chat_notification_service.rb2
-rw-r--r--app/models/project_services/hipchat_service.rb2
-rw-r--r--app/models/protectable_dropdown.rb8
-rw-r--r--app/models/redirect_route.rb2
-rw-r--r--app/models/repository.rb10
-rw-r--r--app/models/user.rb2
-rw-r--r--app/serializers/project_entity.rb2
-rw-r--r--app/services/akismet_service.rb2
-rw-r--r--app/services/ci/retry_build_service.rb2
-rw-r--r--app/services/commits/change_service.rb1
-rw-r--r--app/services/issuable_base_service.rb2
-rw-r--r--app/services/members/destroy_service.rb2
-rw-r--r--app/services/merge_requests/create_service.rb1
-rw-r--r--app/services/notification_service.rb2
-rw-r--r--app/services/system_hooks_service.rb2
-rw-r--r--app/services/test_hooks/base_service.rb2
-rw-r--r--app/views/help/ui.html.haml2
-rw-r--r--app/views/layouts/nav/_new_admin_sidebar.html.haml271
-rw-r--r--app/views/layouts/nav/_new_group_sidebar.html.haml153
-rw-r--r--app/views/layouts/nav/_new_profile_sidebar.html.haml153
-rw-r--r--app/views/layouts/nav/_new_project_sidebar.html.haml479
-rw-r--r--app/views/projects/merge_requests/_discussion.html.haml6
-rw-r--r--app/views/shared/milestones/_milestone.html.haml2
-rw-r--r--app/views/shared/milestones/_top.html.haml2
-rw-r--r--app/workers/gitlab_shell_worker.rb2
-rw-r--r--changelogs/unreleased/34049-public-commits-should-not-require-authentication.yml4
-rw-r--r--changelogs/unreleased/34643-fix-project-path-slugify.yml4
-rw-r--r--config/gitlab.yml.example3
-rw-r--r--config/initializers/0_acts_as_taggable.rb2
-rw-r--r--config/initializers/1_settings.rb2
-rw-r--r--config/initializers/6_validations.rb4
-rw-r--r--config/initializers/static_files.rb10
-rw-r--r--config/initializers/trusted_proxies.rb2
-rw-r--r--config/routes/repository.rb2
-rw-r--r--db/migrate/20161020075830_default_request_access_projects.rb2
-rw-r--r--db/post_migrate/20170503004427_update_retried_for_ci_build.rb2
-rw-r--r--db/post_migrate/20170523083112_migrate_old_artifacts.rb6
-rw-r--r--db/post_migrate/20170815060945_remove_duplicate_mr_events.rb26
-rw-r--r--db/schema.rb2
-rw-r--r--doc/install/installation.md2
-rw-r--r--doc/user/search/img/group_issues_filter.pngbin0 -> 45288 bytes
-rw-r--r--doc/user/search/index.md8
-rw-r--r--features/steps/profile/emails.rb2
-rw-r--r--lib/api/api_guard.rb2
-rw-r--r--lib/api/entities.rb7
-rw-r--r--lib/api/protected_branches.rb2
-rw-r--r--lib/api/runners.rb2
-rw-r--r--lib/api/v3/notes.rb6
-rw-r--r--lib/banzai/filter/external_issue_reference_filter.rb4
-rw-r--r--lib/banzai/filter/image_lazy_load_filter.rb4
-rw-r--r--lib/banzai/object_renderer.rb2
-rw-r--r--lib/banzai/pipeline/base_pipeline.rb2
-rw-r--r--lib/banzai/renderer.rb4
-rw-r--r--lib/bitbucket/collection.rb2
-rw-r--r--lib/ci/ansi2html.rb2
-rw-r--r--lib/constraints/project_url_constrainer.rb2
-rw-r--r--lib/declarative_policy/base.rb4
-rw-r--r--lib/declarative_policy/dsl.rb2
-rw-r--r--lib/file_size_validator.rb4
-rw-r--r--lib/gitlab/auth.rb4
-rw-r--r--lib/gitlab/auth/ip_rate_limiter.rb12
-rw-r--r--lib/gitlab/cache/request_cache.rb2
-rw-r--r--lib/gitlab/ci/build/artifacts/metadata.rb2
-rw-r--r--lib/gitlab/diff/line_mapper.rb6
-rw-r--r--lib/gitlab/git/blob.rb4
-rw-r--r--lib/gitlab/git/repository.rb22
-rw-r--r--lib/gitlab/git/tree.rb2
-rw-r--r--lib/gitlab/gitaly_client.rb2
-rw-r--r--lib/gitlab/github_import/base_formatter.rb4
-rw-r--r--lib/gitlab/github_import/client.rb2
-rw-r--r--lib/gitlab/github_import/importer.rb2
-rw-r--r--lib/gitlab/import_export/attributes_finder.rb1
-rw-r--r--lib/gitlab/lazy.rb2
-rw-r--r--lib/gitlab/ldap/auth_hash.rb2
-rw-r--r--lib/gitlab/ldap/person.rb4
-rw-r--r--lib/gitlab/markdown/pipeline.rb2
-rw-r--r--lib/gitlab/middleware/rails_queue_duration.rb2
-rw-r--r--lib/gitlab/redis/cache.rb5
-rw-r--r--lib/gitlab/redis/queues.rb5
-rw-r--r--lib/gitlab/redis/shared_state.rb5
-rw-r--r--lib/gitlab/redis/wrapper.rb13
-rw-r--r--lib/gitlab/shell.rb12
-rw-r--r--lib/gitlab/slash_commands/presenters/help.rb2
-rw-r--r--lib/gitlab/utils.rb13
-rw-r--r--lib/tasks/gitlab/gitaly.rake2
-rw-r--r--lib/uploaded_file.rb2
-rw-r--r--qa/qa/runtime/release.rb2
-rw-r--r--spec/features/admin/admin_settings_spec.rb2
-rw-r--r--spec/features/groups/milestone_spec.rb29
-rw-r--r--spec/features/issues/filtered_search/dropdown_assignee_spec.rb12
-rw-r--r--spec/features/issues/filtered_search/dropdown_author_spec.rb10
-rw-r--r--spec/features/issues/filtered_search/dropdown_label_spec.rb18
-rw-r--r--spec/features/issues/filtered_search/dropdown_milestone_spec.rb20
-rw-r--r--spec/features/issues/filtered_search/filter_issues_spec.rb192
-rw-r--r--spec/features/issues/filtered_search/search_bar_spec.rb2
-rw-r--r--spec/features/issues/filtered_search/visual_tokens_spec.rb4
-rw-r--r--spec/features/issues_spec.rb2
-rw-r--r--spec/features/merge_requests/conflicts_spec.rb10
-rw-r--r--spec/features/merge_requests/filter_by_milestone_spec.rb2
-rw-r--r--spec/features/merge_requests/filter_merge_requests_spec.rb58
-rw-r--r--spec/features/milestones/show_spec.rb2
-rw-r--r--spec/features/projects/files/undo_template_spec.rb2
-rw-r--r--spec/features/search_spec.rb12
-rw-r--r--spec/helpers/version_check_helper_spec.rb2
-rw-r--r--spec/javascripts/fixtures/prometheus_service.rb2
-rw-r--r--spec/javascripts/fixtures/services.rb1
-rw-r--r--spec/javascripts/fly_out_nav_spec.js6
-rw-r--r--spec/lib/file_size_validator_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/trace/stream_spec.rb2
-rw-r--r--spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb4
-rw-r--r--spec/lib/gitlab/git/storage/circuit_breaker_spec.rb59
-rw-r--r--spec/lib/gitlab/key_fingerprint_spec.rb4
-rw-r--r--spec/lib/gitlab/ldap/auth_hash_spec.rb12
-rw-r--r--spec/lib/gitlab/o_auth/user_spec.rb2
-rw-r--r--spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb4
-rw-r--r--spec/lib/gitlab/redis/wrapper_spec.rb7
-rw-r--r--spec/lib/gitlab/shell_spec.rb35
-rw-r--r--spec/lib/gitlab/utils_spec.rb16
-rw-r--r--spec/migrations/migrate_old_artifacts_spec.rb4
-rw-r--r--spec/migrations/remove_duplicate_mr_events_spec.rb26
-rw-r--r--spec/models/ci/build_spec.rb2
-rw-r--r--spec/models/protectable_dropdown_spec.rb7
-rw-r--r--spec/requests/api/commits_spec.rb213
-rw-r--r--spec/requests/api/protected_branches_spec.rb4
-rw-r--r--spec/requests/api/settings_spec.rb2
-rw-r--r--spec/requests/ci/api/builds_spec.rb2
-rw-r--r--spec/services/merge_requests/create_service_spec.rb10
-rw-r--r--spec/services/web_hook_service_spec.rb2
-rw-r--r--spec/support/filtered_search_helpers.rb26
-rwxr-xr-xspec/support/generate-seed-repo-rb12
-rw-r--r--spec/support/matchers/access_matchers_for_controller.rb2
-rw-r--r--spec/support/stub_configuration.rb5
-rw-r--r--spec/tasks/gitlab/gitaly_rake_spec.rb2
170 files changed, 1406 insertions, 1046 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index cd19b6f47ff..df7244d5a2e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,4 +1,4 @@
-image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.3-golang-1.8-git-2.7-phantomjs-2.1-node-7.1-postgresql-9.6"
+image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.3-golang-1.8-git-2.13-phantomjs-2.1-node-7.1-postgresql-9.6"
.default-cache: &default-cache
key: "ruby-233-with-yarn"
@@ -474,7 +474,6 @@ db:rollback-mysql:
variables:
SIZE: "1"
SETUP_DB: "false"
- RAILS_ENV: "development"
script:
- git clone https://gitlab.com/gitlab-org/gitlab-test.git
/home/git/repositories/gitlab-org/gitlab-test.git
@@ -523,7 +522,7 @@ karma:
<<: *dedicated-runner
<<: *except-docs
<<: *pull-cache
- image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.3-golang-1.8-git-2.7-chrome-59.0-node-7.1-postgresql-9.6"
+ image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.3-golang-1.8-git-2.13-chrome-59.0-node-7.1-postgresql-9.6"
stage: test
variables:
BABEL_ENV: "coverage"
diff --git a/.rubocop.yml b/.rubocop.yml
index d25b4ac39c9..23bb0fa8be8 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -251,6 +251,10 @@ Layout/Tab:
Layout/TrailingBlankLines:
Enabled: true
+# Avoid trailing whitespace.
+Layout/TrailingWhitespace:
+ Enabled: true
+
# Style #######################################################################
# Check the naming of accessor methods for get_/set_.
@@ -1174,29 +1178,33 @@ RSpec/VerifiedDoubles:
GitlabSecurity/DeepMunge:
Enabled: true
Exclude:
- - 'spec/**/*'
- 'lib/**/*.rake'
+ - 'spec/**/*'
GitlabSecurity/PublicSend:
Enabled: true
Exclude:
- - 'spec/**/*'
+ - 'config/**/*'
+ - 'db/**/*'
+ - 'features/**/*'
- 'lib/**/*.rake'
+ - 'qa/**/*'
+ - 'spec/**/*'
GitlabSecurity/RedirectToParamsUpdate:
Enabled: true
Exclude:
- - 'spec/**/*'
- 'lib/**/*.rake'
+ - 'spec/**/*'
GitlabSecurity/SqlInjection:
Enabled: true
Exclude:
- - 'spec/**/*'
- 'lib/**/*.rake'
+ - 'spec/**/*'
GitlabSecurity/SystemCommandInjection:
Enabled: true
Exclude:
- - 'spec/**/*'
- 'lib/**/*.rake'
+ - 'spec/**/*'
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index cf14285ec2a..4b4f14efea4 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -57,11 +57,6 @@ Layout/SpaceInsideParens:
Layout/SpaceInsidePercentLiteralDelimiters:
Enabled: false
-# Offense count: 89
-# Cop supports --auto-correct.
-Layout/TrailingWhitespace:
- Enabled: false
-
# Offense count: 272
RSpec/EmptyLineAfterFinalLet:
Enabled: false
diff --git a/PROCESS.md b/PROCESS.md
index e5b17784d20..538e4389e00 100644
--- a/PROCESS.md
+++ b/PROCESS.md
@@ -141,18 +141,22 @@ the stable branch are:
* Fixes for security issues
* New or updated translations (as long as they do not touch application code)
-Any merge requests cherry-picked into the stable branch for a previous release
-will also be picked into the latest stable branch. These fixes will be shipped
-in the next RC for that release if it is before the 22nd. If the fixes are are
-completed on or after the 22nd, they will be shipped in a patch for that
-release.
-
During the feature freeze all merge requests that are meant to go into the upcoming
release should have the correct milestone assigned _and_ have the label
~"Pick into Stable" set, so that release managers can find and pick them.
Merge requests without a milestone and this label will
not be merged into any stable branches.
+Fixes marked like this will be shipped in the next RC for that release. Once
+the final RC has been prepared ready for release on the 22nd, further fixes
+marked ~"Pick into Stable" will go into a patch for that release.
+
+If a merge request is to be picked into more than one release it will also need
+the ~"Pick into Backports" label set to remind the release manager to change
+the milestone after cherry-picking. As before, it should still have the
+~"Pick into Stable" label and the milestone of the highest release it will be
+picked into.
+
### Asking for an exception
If you think a merge request should go into an RC or patch even though it does not meet these requirements,
diff --git a/app/assets/javascripts/diff_notes/diff_notes_bundle.js b/app/assets/javascripts/diff_notes/diff_notes_bundle.js
index a2d33b0936e..5decfc1dc01 100644
--- a/app/assets/javascripts/diff_notes/diff_notes_bundle.js
+++ b/app/assets/javascripts/diff_notes/diff_notes_bundle.js
@@ -42,6 +42,10 @@ $(() => {
$components.each(function () {
const $this = $(this);
const noteId = $this.attr(':note-id');
+ const discussionId = $this.attr(':discussion-id');
+
+ if ($this.is('comment-and-resolve-btn') && !discussionId) return;
+
const tmp = Vue.extend({
template: $this.get(0).outerHTML
});
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index de47485c9f2..a0ed5c23ffe 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -644,7 +644,7 @@ import initChangesDropdown from './init_changes_dropdown';
return Dispatcher;
})();
- $(function() {
+ $(window).on('load', function() {
new Dispatcher();
});
}).call(window);
diff --git a/app/assets/javascripts/fly_out_nav.js b/app/assets/javascripts/fly_out_nav.js
index cbc3ad23990..32cb42c8b10 100644
--- a/app/assets/javascripts/fly_out_nav.js
+++ b/app/assets/javascripts/fly_out_nav.js
@@ -15,6 +15,10 @@ export const setOpenMenu = (menu = null) => { currentOpenMenu = menu; };
export const slope = (a, b) => (b.y - a.y) / (b.x - a.x);
+let headerHeight = 50;
+
+export const getHeaderHeight = () => headerHeight;
+
export const canShowActiveSubItems = (el) => {
const isHiddenByMedia = bp.getBreakpointSize() === 'sm' || bp.getBreakpointSize() === 'md';
@@ -74,7 +78,7 @@ export const moveSubItemsToPosition = (el, subItems) => {
const isAbove = top < boundingRect.top;
subItems.classList.add('fly-out-list');
- subItems.style.transform = `translate3d(0, ${Math.floor(top)}px, 0)`; // eslint-disable-line no-param-reassign
+ subItems.style.transform = `translate3d(0, ${Math.floor(top) - headerHeight}px, 0)`; // eslint-disable-line no-param-reassign
const subItemsRect = subItems.getBoundingClientRect();
@@ -153,6 +157,8 @@ export default () => {
}, getHideSubItemsInterval());
});
+ headerHeight = document.querySelector('.nav-sidebar').offsetTop;
+
items.forEach((el) => {
const subItems = el.querySelector('.sidebar-sub-level-items');
diff --git a/app/assets/javascripts/lib/utils/sticky.js b/app/assets/javascripts/lib/utils/sticky.js
index 43a808b6ab3..ff2b66046b4 100644
--- a/app/assets/javascripts/lib/utils/sticky.js
+++ b/app/assets/javascripts/lib/utils/sticky.js
@@ -1,7 +1,7 @@
export const isSticky = (el, scrollY, stickyTop) => {
const top = el.offsetTop - scrollY;
- if (top === stickyTop) {
+ if (top <= stickyTop) {
el.classList.add('is-stuck');
} else {
el.classList.remove('is-stuck');
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 37f531c78f4..6d7c7e3c930 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -132,8 +132,9 @@ import './project_select';
import './project_show';
import './project_variables';
import './projects_list';
-import './render_gfm';
+import './syntax_highlight';
import './render_math';
+import './render_gfm';
import './right_sidebar';
import './search';
import './search_autocomplete';
@@ -141,7 +142,6 @@ import './smart_interval';
import './star';
import './subscription';
import './subscription_select';
-import './syntax_highlight';
import './dispatcher';
diff --git a/app/assets/javascripts/render_gfm.js b/app/assets/javascripts/render_gfm.js
index 2c3a9cacd38..bcdc0fd67b8 100644
--- a/app/assets/javascripts/render_gfm.js
+++ b/app/assets/javascripts/render_gfm.js
@@ -11,7 +11,5 @@
return this;
};
- $(document).on('ready load', function() {
- return $('body').renderGFM();
- });
+ $(() => $('body').renderGFM());
}).call(window);
diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss
index d386ac5ba9c..071f20fc457 100644
--- a/app/assets/stylesheets/framework/nav.scss
+++ b/app/assets/stylesheets/framework/nav.scss
@@ -161,6 +161,8 @@
}
.nav-controls {
+ @include new-style-dropdown;
+
display: inline-block;
float: right;
text-align: right;
diff --git a/app/assets/stylesheets/new_sidebar.scss b/app/assets/stylesheets/new_sidebar.scss
index faedd207e01..d078c8b956b 100644
--- a/app/assets/stylesheets/new_sidebar.scss
+++ b/app/assets/stylesheets/new_sidebar.scss
@@ -97,9 +97,9 @@ $new-sidebar-collapsed-width: 50px;
top: $header-height;
bottom: 0;
left: 0;
- overflow: auto;
background-color: $gray-normal;
box-shadow: inset -2px 0 0 $border-color;
+ transform: translate3d(0, 0, 0);
&.sidebar-icons-only {
width: $new-sidebar-collapsed-width;
@@ -176,6 +176,12 @@ $new-sidebar-collapsed-width: 50px;
}
}
+.nav-sidebar-inner-scroll {
+ height: 100%;
+ width: 100%;
+ overflow: auto;
+}
+
.with-performance-bar .nav-sidebar {
top: $header-height + $performance-bar-height;
}
diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb
index 0c3b68a7ac3..4079072a930 100644
--- a/app/controllers/concerns/issuable_actions.rb
+++ b/app/controllers/concerns/issuable_actions.rb
@@ -10,7 +10,7 @@ module IssuableActions
def destroy
issuable.destroy
destroy_method = "destroy_#{issuable.class.name.underscore}".to_sym
- TodoService.new.public_send(destroy_method, issuable, current_user)
+ TodoService.new.public_send(destroy_method, issuable, current_user) # rubocop:disable GitlabSecurity/PublicSend
name = issuable.human_class_name
flash[:notice] = "The #{name} was successfully deleted."
diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb
index c0ac47e363d..96ce686c989 100644
--- a/app/controllers/groups/application_controller.rb
+++ b/app/controllers/groups/application_controller.rb
@@ -34,7 +34,7 @@ class Groups::ApplicationController < ApplicationController
def build_canonical_path(group)
params[:group_id] = group.to_param
-
+
url_for(params)
end
end
diff --git a/app/controllers/import/github_controller.rb b/app/controllers/import/github_controller.rb
index baa6645e5ce..ab18d86dcae 100644
--- a/app/controllers/import/github_controller.rb
+++ b/app/controllers/import/github_controller.rb
@@ -64,7 +64,7 @@ class Import::GithubController < Import::BaseController
end
def import_enabled?
- __send__("#{provider}_import_enabled?")
+ __send__("#{provider}_import_enabled?") # rubocop:disable GitlabSecurity/PublicSend
end
def new_import_url
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index b4213574561..7444826a5d1 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -142,13 +142,13 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def oauth
@oauth ||= request.env['omniauth.auth']
end
-
+
def fail_login
error_message = @user.errors.full_messages.to_sentence
return redirect_to omniauth_error_path(oauth['provider'], error: error_message)
end
-
+
def fail_ldap_login
flash[:alert] = 'Access denied for your LDAP account.'
diff --git a/app/controllers/projects/cycle_analytics/events_controller.rb b/app/controllers/projects/cycle_analytics/events_controller.rb
index b69d46f2c41..26f3c114108 100644
--- a/app/controllers/projects/cycle_analytics/events_controller.rb
+++ b/app/controllers/projects/cycle_analytics/events_controller.rb
@@ -2,7 +2,7 @@ module Projects
module CycleAnalytics
class EventsController < Projects::ApplicationController
include CycleAnalyticsParams
-
+
before_action :authorize_read_cycle_analytics!
before_action :authorize_read_build!, only: [:test, :staging]
before_action :authorize_read_issue!, only: [:issue, :production]
@@ -11,33 +11,33 @@ module Projects
def issue
render_events(cycle_analytics[:issue].events)
end
-
+
def plan
render_events(cycle_analytics[:plan].events)
end
-
+
def code
render_events(cycle_analytics[:code].events)
end
-
+
def test
options(events_params)[:branch] = events_params[:branch_name]
-
+
render_events(cycle_analytics[:test].events)
end
-
+
def review
render_events(cycle_analytics[:review].events)
end
-
+
def staging
render_events(cycle_analytics[:staging].events)
end
-
+
def production
render_events(cycle_analytics[:production].events)
end
-
+
private
def render_events(events)
@@ -46,14 +46,14 @@ module Projects
format.json { render json: { events: events } }
end
end
-
+
def cycle_analytics
@cycle_analytics ||= ::CycleAnalytics.new(project, options(events_params))
end
-
+
def events_params
return {} unless params[:events].present?
-
+
params[:events].permit(:start_date, :branch_name)
end
end
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index 4de814d0ca8..2a3b73577a5 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -218,8 +218,8 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
if can?(current_user, :read_environment, environment) && environment.has_metrics?
metrics_project_environment_deployment_path(environment.project, environment, deployment)
end
-
- metrics_monitoring_url =
+
+ metrics_monitoring_url =
if can?(current_user, :read_environment, environment)
environment_metrics_path(environment)
end
diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb
index dc882b17143..16a74f82d3f 100644
--- a/app/controllers/uploads_controller.rb
+++ b/app/controllers/uploads_controller.rb
@@ -89,7 +89,7 @@ class UploadsController < ApplicationController
@uploader.retrieve_from_store!(params[:filename])
else
- @uploader = @model.send(upload_mount)
+ @uploader = @model.public_send(upload_mount) # rubocop:disable GitlabSecurity/PublicSend
redirect_to @uploader.url unless @uploader.file_storage?
end
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index 69220a1c0f6..72e26b64e60 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -128,10 +128,10 @@ module CommitsHelper
# avatar: true will prepend the avatar image
# size: size of the avatar image in px
def commit_person_link(commit, options = {})
- user = commit.send(options[:source])
+ user = commit.public_send(options[:source]) # rubocop:disable GitlabSecurity/PublicSend
- source_name = clean(commit.send "#{options[:source]}_name".to_sym)
- source_email = clean(commit.send "#{options[:source]}_email".to_sym)
+ source_name = clean(commit.public_send(:"#{options[:source]}_name")) # rubocop:disable GitlabSecurity/PublicSend
+ source_email = clean(commit.public_send(:"#{options[:source]}_email")) # rubocop:disable GitlabSecurity/PublicSend
person_name = user.try(:name) || source_name
diff --git a/app/helpers/import_helper.rb b/app/helpers/import_helper.rb
index a57b5a8fea5..a18ebfb6030 100644
--- a/app/helpers/import_helper.rb
+++ b/app/helpers/import_helper.rb
@@ -5,7 +5,7 @@ module ImportHelper
end
def provider_project_link(provider, path_with_namespace)
- url = __send__("#{provider}_project_url", path_with_namespace)
+ url = __send__("#{provider}_project_url", path_with_namespace) # rubocop:disable GitlabSecurity/PublicSend
link_to path_with_namespace, url, target: '_blank', rel: 'noopener noreferrer'
end
diff --git a/app/helpers/issuables_helper.rb b/app/helpers/issuables_helper.rb
index 70ea35fab1e..197c90c4081 100644
--- a/app/helpers/issuables_helper.rb
+++ b/app/helpers/issuables_helper.rb
@@ -174,7 +174,14 @@ module IssuablesHelper
end
def assigned_issuables_count(issuable_type)
- current_user.public_send("assigned_open_#{issuable_type}_count")
+ case issuable_type
+ when :issues
+ current_user.assigned_open_issues_count
+ when :merge_requests
+ current_user.assigned_open_merge_requests_count
+ else
+ raise ArgumentError, "invalid issuable `#{issuable_type}`"
+ end
end
def issuable_filter_params
@@ -298,10 +305,6 @@ module IssuablesHelper
cookies[:collapsed_gutter] == 'true'
end
- def base_issuable_scope(issuable)
- issuable.project.send(issuable.class.table_name).send(issuable_state_scope(issuable))
- end
-
def issuable_state_scope(issuable)
if issuable.respond_to?(:merged?) && issuable.merged?
:merged
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb
index f8860bfee99..86666022a2a 100644
--- a/app/helpers/milestones_helper.rb
+++ b/app/helpers/milestones_helper.rb
@@ -32,7 +32,18 @@ module MilestonesHelper
end
def milestone_issues_by_label_count(milestone, label, state:)
- milestone.issues.with_label(label.title).send(state).size
+ issues = milestone.issues.with_label(label.title)
+ issues =
+ case state
+ when :opened
+ issues.opened
+ when :closed
+ issues.closed
+ else
+ raise ArgumentError, "invalid milestone state `#{state}`"
+ end
+
+ issues.size
end
# Returns count of milestones for different states
diff --git a/app/helpers/pipeline_schedules_helper.rb b/app/helpers/pipeline_schedules_helper.rb
index fee1edc2a1b..6edaf78de1b 100644
--- a/app/helpers/pipeline_schedules_helper.rb
+++ b/app/helpers/pipeline_schedules_helper.rb
@@ -1,10 +1,10 @@
module PipelineSchedulesHelper
def timezone_data
- ActiveSupport::TimeZone.all.map do |timezone|
- {
- name: timezone.name,
- offset: timezone.utc_offset,
- identifier: timezone.tzinfo.identifier
+ ActiveSupport::TimeZone.all.map do |timezone|
+ {
+ name: timezone.name,
+ offset: timezone.utc_offset,
+ identifier: timezone.tzinfo.identifier
}
end
end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index 278d394bc03..bee4950e414 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -149,15 +149,16 @@ module ProjectsHelper
# Don't show option "everyone with access" if project is private
options = project_feature_options
+ level = @project.project_feature.public_send(field) # rubocop:disable GitlabSecurity/PublicSend
+
if @project.private?
- level = @project.project_feature.send(field)
disabled_option = ProjectFeature::ENABLED
highest_available_option = ProjectFeature::PRIVATE if level == disabled_option
end
options = options_for_select(
options.invert,
- selected: highest_available_option || @project.project_feature.public_send(field),
+ selected: highest_available_option || level,
disabled: disabled_option
)
@@ -488,7 +489,7 @@ module ProjectsHelper
end
def filename_path(project, filename)
- if project && blob = project.repository.send(filename)
+ if project && blob = project.repository.public_send(filename) # rubocop:disable GitlabSecurity/PublicSend
project_blob_path(
project,
tree_join(project.default_branch, blob.name)
diff --git a/app/helpers/version_check_helper.rb b/app/helpers/version_check_helper.rb
index 3b175251446..456598b4c28 100644
--- a/app/helpers/version_check_helper.rb
+++ b/app/helpers/version_check_helper.rb
@@ -2,7 +2,7 @@ module VersionCheckHelper
def version_status_badge
if Rails.env.production? && current_application_settings.version_check_enabled
image_url = VersionCheck.new.url
- image_tag image_url, class: 'js-version-status-badge', lazy: false
+ image_tag image_url, class: 'js-version-status-badge'
end
end
end
diff --git a/app/models/blob_viewer/notebook.rb b/app/models/blob_viewer/notebook.rb
index 8632b8a9885..e00b47e6c17 100644
--- a/app/models/blob_viewer/notebook.rb
+++ b/app/models/blob_viewer/notebook.rb
@@ -2,7 +2,7 @@ module BlobViewer
class Notebook < Base
include Rich
include ClientSide
-
+
self.partial_name = 'notebook'
self.extensions = %w(ipynb)
self.binary = false
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 8be2dee6479..4692fb5644a 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -194,10 +194,7 @@ module Ci
# * Maximum length is 63 bytes
# * First/Last Character is not a hyphen
def ref_slug
- ref.to_s
- .downcase
- .gsub(/[^a-z0-9]/, '-')[0..62]
- .gsub(/(\A-+|-+\z)/, '')
+ Gitlab::Utils.slugify(ref.to_s)
end
# Variables whose value does not depend on environment
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 638fddc5d3d..5ca2f150247 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -200,7 +200,7 @@ class Commit
end
def method_missing(m, *args, &block)
- @raw.send(m, *args, &block)
+ @raw.__send__(m, *args, &block) # rubocop:disable GitlabSecurity/PublicSend
end
def respond_to_missing?(method, include_private = false)
diff --git a/app/models/concerns/cache_markdown_field.rb b/app/models/concerns/cache_markdown_field.rb
index 48547a938fc..193e459977a 100644
--- a/app/models/concerns/cache_markdown_field.rb
+++ b/app/models/concerns/cache_markdown_field.rb
@@ -78,7 +78,7 @@ module CacheMarkdownField
def cached_html_up_to_date?(markdown_field)
html_field = cached_markdown_fields.html_field(markdown_field)
- cached = cached_html_for(markdown_field).present? && __send__(markdown_field).present?
+ cached = cached_html_for(markdown_field).present? && __send__(markdown_field).present? # rubocop:disable GitlabSecurity/PublicSend
return false unless cached
markdown_changed = attribute_changed?(markdown_field) || false
@@ -93,14 +93,14 @@ module CacheMarkdownField
end
def attribute_invalidated?(attr)
- __send__("#{attr}_invalidated?")
+ __send__("#{attr}_invalidated?") # rubocop:disable GitlabSecurity/PublicSend
end
def cached_html_for(markdown_field)
raise ArgumentError.new("Unknown field: #{field}") unless
cached_markdown_fields.markdown_fields.include?(markdown_field)
- __send__(cached_markdown_fields.html_field(markdown_field))
+ __send__(cached_markdown_fields.html_field(markdown_field)) # rubocop:disable GitlabSecurity/PublicSend
end
included do
diff --git a/app/models/concerns/internal_id.rb b/app/models/concerns/internal_id.rb
index 67a0adfcd56..a3d0ac8d862 100644
--- a/app/models/concerns/internal_id.rb
+++ b/app/models/concerns/internal_id.rb
@@ -9,7 +9,7 @@ module InternalId
def set_iid
if iid.blank?
parent = project || group
- records = parent.send(self.class.name.tableize)
+ records = parent.public_send(self.class.name.tableize) # rubocop:disable GitlabSecurity/PublicSend
records = records.with_deleted if self.paranoid?
max_iid = records.maximum(:iid)
diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb
index c034bf9cbc0..1db6b2d2fa2 100644
--- a/app/models/concerns/mentionable.rb
+++ b/app/models/concerns/mentionable.rb
@@ -56,7 +56,7 @@ module Mentionable
end
self.class.mentionable_attrs.each do |attr, options|
- text = __send__(attr)
+ text = __send__(attr) # rubocop:disable GitlabSecurity/PublicSend
options = options.merge(
cache_key: [self, attr],
author: author,
@@ -100,7 +100,7 @@ module Mentionable
end
self.class.mentionable_attrs.any? do |attr, _|
- __send__(attr) =~ reference_pattern
+ __send__(attr) =~ reference_pattern # rubocop:disable GitlabSecurity/PublicSend
end
end
diff --git a/app/models/concerns/participable.rb b/app/models/concerns/participable.rb
index 4865c0a14b1..ce69fd34ac5 100644
--- a/app/models/concerns/participable.rb
+++ b/app/models/concerns/participable.rb
@@ -82,7 +82,7 @@ module Participable
if attr.respond_to?(:call)
source.instance_exec(current_user, ext, &attr)
else
- process << source.__send__(attr)
+ process << source.__send__(attr) # rubocop:disable GitlabSecurity/PublicSend
end
end
when Enumerable, ActiveRecord::Relation
diff --git a/app/models/concerns/project_features_compatibility.rb b/app/models/concerns/project_features_compatibility.rb
index 60734bc6660..cb59b4da3d7 100644
--- a/app/models/concerns/project_features_compatibility.rb
+++ b/app/models/concerns/project_features_compatibility.rb
@@ -32,6 +32,6 @@ module ProjectFeaturesCompatibility
build_project_feature unless project_feature
access_level = Gitlab::Utils.to_boolean(value) ? ProjectFeature::ENABLED : ProjectFeature::DISABLED
- project_feature.send(:write_attribute, field, access_level)
+ project_feature.__send__(:write_attribute, field, access_level) # rubocop:disable GitlabSecurity/PublicSend
end
end
diff --git a/app/models/deploy_keys_project.rb b/app/models/deploy_keys_project.rb
index ae8486bd9ac..b37b9bfbdac 100644
--- a/app/models/deploy_keys_project.rb
+++ b/app/models/deploy_keys_project.rb
@@ -12,7 +12,7 @@ class DeployKeysProject < ActiveRecord::Base
def destroy_orphaned_deploy_key
return unless self.deploy_key.destroyed_when_orphaned? && self.deploy_key.orphaned?
-
+
self.deploy_key.destroy
end
end
diff --git a/app/models/network/commit.rb b/app/models/network/commit.rb
index 8417f200e36..9357e55b419 100644
--- a/app/models/network/commit.rb
+++ b/app/models/network/commit.rb
@@ -12,7 +12,7 @@ module Network
end
def method_missing(m, *args, &block)
- @commit.send(m, *args, &block)
+ @commit.__send__(m, *args, &block) # rubocop:disable GitlabSecurity/PublicSend
end
def space
diff --git a/app/models/project.rb b/app/models/project.rb
index 0de7da0ddaa..22b347cc8f9 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -920,14 +920,14 @@ class Project < ActiveRecord::Base
end
def execute_hooks(data, hooks_scope = :push_hooks)
- hooks.send(hooks_scope).each do |hook|
+ hooks.public_send(hooks_scope).each do |hook| # rubocop:disable GitlabSecurity/PublicSend
hook.async_execute(data, hooks_scope.to_s)
end
end
def execute_services(data, hooks_scope = :push_hooks)
# Call only service hooks that are active for this scope
- services.send(hooks_scope).each do |service|
+ services.public_send(hooks_scope).each do |service| # rubocop:disable GitlabSecurity/PublicSend
service.async_execute(data)
end
end
@@ -1282,12 +1282,16 @@ class Project < ActiveRecord::Base
status.zero?
end
+ def full_path_slug
+ Gitlab::Utils.slugify(full_path.to_s)
+ end
+
def predefined_variables
[
{ key: 'CI_PROJECT_ID', value: id.to_s, public: true },
{ key: 'CI_PROJECT_NAME', value: path, public: true },
{ key: 'CI_PROJECT_PATH', value: full_path, public: true },
- { key: 'CI_PROJECT_PATH_SLUG', value: full_path.parameterize, public: true },
+ { key: 'CI_PROJECT_PATH_SLUG', value: full_path_slug, public: true },
{ key: 'CI_PROJECT_NAMESPACE', value: namespace.full_path, public: true },
{ key: 'CI_PROJECT_URL', value: web_url, public: true }
]
diff --git a/app/models/project_services/chat_notification_service.rb b/app/models/project_services/chat_notification_service.rb
index 6d1a321f651..7b15a5dd04d 100644
--- a/app/models/project_services/chat_notification_service.rb
+++ b/app/models/project_services/chat_notification_service.rb
@@ -115,7 +115,7 @@ class ChatNotificationService < Service
def get_channel_field(event)
field_name = event_channel_name(event)
- self.public_send(field_name)
+ self.public_send(field_name) # rubocop:disable GitlabSecurity/PublicSend
end
def build_event_channels
diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb
index e3906943ecd..f422e0ea036 100644
--- a/app/models/project_services/hipchat_service.rb
+++ b/app/models/project_services/hipchat_service.rb
@@ -53,7 +53,7 @@ class HipchatService < Service
return unless supported_events.include?(data[:object_kind])
message = create_message(data)
return unless message.present?
- gate[room].send('GitLab', message, message_options(data))
+ gate[room].send('GitLab', message, message_options(data)) # rubocop:disable GitlabSecurity/PublicSend
end
def test(data)
diff --git a/app/models/protectable_dropdown.rb b/app/models/protectable_dropdown.rb
index 122fbce257d..c96edc5a259 100644
--- a/app/models/protectable_dropdown.rb
+++ b/app/models/protectable_dropdown.rb
@@ -1,5 +1,9 @@
class ProtectableDropdown
+ REF_TYPES = %i[branches tags].freeze
+
def initialize(project, ref_type)
+ raise ArgumentError, "invalid ref type `#{ref_type}`" unless ref_type.in?(REF_TYPES)
+
@project = project
@ref_type = ref_type
end
@@ -16,7 +20,7 @@ class ProtectableDropdown
private
def refs
- @project.repository.public_send(@ref_type)
+ @project.repository.public_send(@ref_type) # rubocop:disable GitlabSecurity/PublicSend
end
def ref_names
@@ -24,7 +28,7 @@ class ProtectableDropdown
end
def protections
- @project.public_send("protected_#{@ref_type}")
+ @project.public_send("protected_#{@ref_type}") # rubocop:disable GitlabSecurity/PublicSend
end
def non_wildcard_protected_ref_names
diff --git a/app/models/redirect_route.rb b/app/models/redirect_route.rb
index 090fbd61e6f..31de204d824 100644
--- a/app/models/redirect_route.rb
+++ b/app/models/redirect_route.rb
@@ -14,7 +14,7 @@ class RedirectRoute < ActiveRecord::Base
else
'redirect_routes.path = ? OR redirect_routes.path LIKE ?'
end
-
+
where(wheres, path, "#{sanitize_sql_like(path)}/%")
end
end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index a761302b06b..c1e4fcf94a4 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -48,7 +48,9 @@ class Repository
alias_method(original, name)
define_method(name) do
- cache_method_output(name, fallback: fallback, memoize_only: memoize_only) { __send__(original) }
+ cache_method_output(name, fallback: fallback, memoize_only: memoize_only) do
+ __send__(original) # rubocop:disable GitlabSecurity/PublicSend
+ end
end
end
@@ -443,9 +445,9 @@ class Repository
def method_missing(m, *args, &block)
if m == :lookup && !block_given?
lookup_cache[m] ||= {}
- lookup_cache[m][args.join(":")] ||= raw_repository.send(m, *args, &block)
+ lookup_cache[m][args.join(":")] ||= raw_repository.__send__(m, *args, &block) # rubocop:disable GitlabSecurity/PublicSend
else
- raw_repository.send(m, *args, &block)
+ raw_repository.__send__(m, *args, &block) # rubocop:disable GitlabSecurity/PublicSend
end
end
@@ -776,7 +778,7 @@ class Repository
end
actions.each do |options|
- index.public_send(options.delete(:action), options)
+ index.public_send(options.delete(:action), options) # rubocop:disable GitlabSecurity/PublicSend
end
options = {
diff --git a/app/models/user.rb b/app/models/user.rb
index 2b25736bb26..0e2654ff757 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1070,7 +1070,7 @@ class User < ActiveRecord::Base
# Added according to https://github.com/plataformatec/devise/blob/7df57d5081f9884849ca15e4fde179ef164a575f/README.md#activejob-integration
def send_devise_notification(notification, *args)
return true unless can?(:receive_notifications)
- devise_mailer.send(notification, self, *args).deliver_later
+ devise_mailer.__send__(notification, self, *args).deliver_later # rubocop:disable GitlabSecurity/PublicSend
end
# This works around a bug in Devise 4.2.0 that erroneously causes a user to
diff --git a/app/serializers/project_entity.rb b/app/serializers/project_entity.rb
index dc283ba3e7a..b3e5fd21e97 100644
--- a/app/serializers/project_entity.rb
+++ b/app/serializers/project_entity.rb
@@ -1,6 +1,6 @@
class ProjectEntity < Grape::Entity
include RequestAwareEntity
-
+
expose :id
expose :name
diff --git a/app/services/akismet_service.rb b/app/services/akismet_service.rb
index 8e11a2a36a7..59153cbbc0a 100644
--- a/app/services/akismet_service.rb
+++ b/app/services/akismet_service.rb
@@ -58,7 +58,7 @@ class AkismetService
}
begin
- akismet_client.public_send(type, options[:ip_address], options[:user_agent], params)
+ akismet_client.public_send(type, options[:ip_address], options[:user_agent], params) # rubocop:disable GitlabSecurity/PublicSend
true
rescue => e
Rails.logger.error("Unable to connect to Akismet: #{e}, skipping!")
diff --git a/app/services/ci/retry_build_service.rb b/app/services/ci/retry_build_service.rb
index 6372e5755db..ea3b8d66ed9 100644
--- a/app/services/ci/retry_build_service.rb
+++ b/app/services/ci/retry_build_service.rb
@@ -23,7 +23,7 @@ module Ci
end
attributes = CLONE_ACCESSORS.map do |attribute|
- [attribute, build.send(attribute)]
+ [attribute, build.public_send(attribute)] # rubocop:disable GitlabSecurity/PublicSend
end
attributes.push([:user, current_user])
diff --git a/app/services/commits/change_service.rb b/app/services/commits/change_service.rb
index a48d6a976f0..85c2fcf9ea6 100644
--- a/app/services/commits/change_service.rb
+++ b/app/services/commits/change_service.rb
@@ -11,6 +11,7 @@ module Commits
def commit_change(action)
raise NotImplementedError unless repository.respond_to?(action)
+ # rubocop:disable GitlabSecurity/PublicSend
repository.public_send(
action,
current_user,
diff --git a/app/services/issuable_base_service.rb b/app/services/issuable_base_service.rb
index b84a6fd2b7d..4a4f2b91182 100644
--- a/app/services/issuable_base_service.rb
+++ b/app/services/issuable_base_service.rb
@@ -338,7 +338,7 @@ class IssuableBaseService < BaseService
def invalidate_cache_counts(issuable, users: [], skip_project_cache: false)
users.each do |user|
- user.public_send("invalidate_#{issuable.model_name.singular}_cache_counts")
+ user.public_send("invalidate_#{issuable.model_name.singular}_cache_counts") # rubocop:disable GitlabSecurity/PublicSend
end
unless skip_project_cache
diff --git a/app/services/members/destroy_service.rb b/app/services/members/destroy_service.rb
index 2e089149ca8..46c505baf8b 100644
--- a/app/services/members/destroy_service.rb
+++ b/app/services/members/destroy_service.rb
@@ -31,7 +31,7 @@ module Members
source.members.find_by(condition) ||
source.requesters.find_by!(condition)
else
- source.public_send(scope).find_by!(condition)
+ source.public_send(scope).find_by!(condition) # rubocop:disable GitlabSecurity/PublicSend
end
end
diff --git a/app/services/merge_requests/create_service.rb b/app/services/merge_requests/create_service.rb
index fa0c0b7175c..194413bf321 100644
--- a/app/services/merge_requests/create_service.rb
+++ b/app/services/merge_requests/create_service.rb
@@ -25,7 +25,6 @@ module MergeRequests
end
def after_create(issuable)
- event_service.open_mr(issuable, current_user)
todo_service.new_merge_request(issuable, current_user)
issuable.cache_merge_request_closes_issues!(current_user)
update_merge_requests_head_pipeline(issuable)
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index 4267879b03d..e2a80db06a6 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -1,3 +1,5 @@
+# rubocop:disable GitlabSecurity/PublicSend
+
# NotificationService class
#
# Used for notifying users with emails about different events
diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb
index cbcd4478af6..a1c2f8d0180 100644
--- a/app/services/system_hooks_service.rb
+++ b/app/services/system_hooks_service.rb
@@ -4,7 +4,7 @@ class SystemHooksService
end
def execute_hooks(data, hooks_scope = :all)
- SystemHook.public_send(hooks_scope).find_each do |hook|
+ SystemHook.public_send(hooks_scope).find_each do |hook| # rubocop:disable GitlabSecurity/PublicSend
hook.async_execute(data, 'system_hooks')
end
end
diff --git a/app/services/test_hooks/base_service.rb b/app/services/test_hooks/base_service.rb
index 74ba814afff..4abd2c44b2f 100644
--- a/app/services/test_hooks/base_service.rb
+++ b/app/services/test_hooks/base_service.rb
@@ -18,7 +18,7 @@ module TestHooks
end
error_message = catch(:validation_error) do
- sample_data = self.__send__(trigger_data_method)
+ sample_data = self.__send__(trigger_data_method) # rubocop:disable GitlabSecurity/PublicSend
return hook.execute(sample_data, trigger)
end
diff --git a/app/views/help/ui.html.haml b/app/views/help/ui.html.haml
index f18c3a74120..445f0dffbcc 100644
--- a/app/views/help/ui.html.haml
+++ b/app/views/help/ui.html.haml
@@ -189,7 +189,7 @@
= icon('chevron-down')
%ul.dropdown-menu
%li
- %a Sort by date
+ = link_to 'Sort by date', '#'
= link_to 'New issue', '#', class: 'btn btn-new btn-inverted'
diff --git a/app/views/layouts/nav/_new_admin_sidebar.html.haml b/app/views/layouts/nav/_new_admin_sidebar.html.haml
index 0b4a9d92bea..3cbcd841aff 100644
--- a/app/views/layouts/nav/_new_admin_sidebar.html.haml
+++ b/app/views/layouts/nav/_new_admin_sidebar.html.haml
@@ -1,150 +1,151 @@
.nav-sidebar{ class: ("sidebar-icons-only" if collapsed_sidebar?) }
- .context-header
- = link_to admin_root_path, title: 'Admin Overview' do
- .avatar-container.s40.settings-avatar
- = icon('wrench')
- .project-title Admin Area
- %ul.sidebar-top-level-items
- = nav_link(controller: %w(dashboard admin projects users groups jobs runners cohorts), html_options: {class: 'home'}) do
- = link_to admin_root_path, title: 'Overview', class: 'shortcuts-tree' do
- .nav-icon-container
- = custom_icon('overview')
- %span.nav-item-name
- Overview
-
- %ul.sidebar-sub-level-items
- = nav_link(controller: :dashboard, html_options: {class: 'home'}) do
- = link_to admin_root_path, title: 'Overview' do
- %span
- Dashboard
- = nav_link(controller: [:admin, :projects]) do
- = link_to admin_projects_path, title: 'Projects' do
- %span
- Projects
- = nav_link(controller: :users) do
- = link_to admin_users_path, title: 'Users' do
- %span
- Users
- = nav_link(controller: :groups) do
- = link_to admin_groups_path, title: 'Groups' do
- %span
- Groups
- = nav_link path: 'jobs#index' do
- = link_to admin_jobs_path, title: 'Jobs' do
- %span
- Jobs
- = nav_link path: ['runners#index', 'runners#show'] do
- = link_to admin_runners_path, title: 'Runners' do
- %span
- Runners
- = nav_link path: 'cohorts#index' do
- = link_to admin_cohorts_path, title: 'Cohorts' do
- %span
- Cohorts
+ .nav-sidebar-inner-scroll
+ .context-header
+ = link_to admin_root_path, title: 'Admin Overview' do
+ .avatar-container.s40.settings-avatar
+ = icon('wrench')
+ .project-title Admin Area
+ %ul.sidebar-top-level-items
+ = nav_link(controller: %w(dashboard admin projects users groups jobs runners cohorts), html_options: {class: 'home'}) do
+ = link_to admin_root_path, title: 'Overview', class: 'shortcuts-tree' do
+ .nav-icon-container
+ = custom_icon('overview')
+ %span.nav-item-name
+ Overview
- = nav_link(controller: %w(conversational_development_index system_info background_jobs logs health_check requests_profiles)) do
- = link_to admin_conversational_development_index_path, title: 'Monitoring' do
- .nav-icon-container
- = custom_icon('monitoring')
- %span.nav-item-name
- Monitoring
+ %ul.sidebar-sub-level-items
+ = nav_link(controller: :dashboard, html_options: {class: 'home'}) do
+ = link_to admin_root_path, title: 'Overview' do
+ %span
+ Dashboard
+ = nav_link(controller: [:admin, :projects]) do
+ = link_to admin_projects_path, title: 'Projects' do
+ %span
+ Projects
+ = nav_link(controller: :users) do
+ = link_to admin_users_path, title: 'Users' do
+ %span
+ Users
+ = nav_link(controller: :groups) do
+ = link_to admin_groups_path, title: 'Groups' do
+ %span
+ Groups
+ = nav_link path: 'jobs#index' do
+ = link_to admin_jobs_path, title: 'Jobs' do
+ %span
+ Jobs
+ = nav_link path: ['runners#index', 'runners#show'] do
+ = link_to admin_runners_path, title: 'Runners' do
+ %span
+ Runners
+ = nav_link path: 'cohorts#index' do
+ = link_to admin_cohorts_path, title: 'Cohorts' do
+ %span
+ Cohorts
- %ul.sidebar-sub-level-items
- = nav_link(controller: :conversational_development_index) do
- = link_to admin_conversational_development_index_path, title: 'ConvDev Index' do
- %span
- ConvDev Index
- = nav_link(controller: :system_info) do
- = link_to admin_system_info_path, title: 'System Info' do
- %span
- System Info
- = nav_link(controller: :background_jobs) do
- = link_to admin_background_jobs_path, title: 'Background Jobs' do
- %span
- Background Jobs
- = nav_link(controller: :logs) do
- = link_to admin_logs_path, title: 'Logs' do
- %span
- Logs
- = nav_link(controller: :health_check) do
- = link_to admin_health_check_path, title: 'Health Check' do
- %span
- Health Check
- = nav_link(controller: :requests_profiles) do
- = link_to admin_requests_profiles_path, title: 'Requests Profiles' do
- %span
- Requests Profiles
+ = nav_link(controller: %w(conversational_development_index system_info background_jobs logs health_check requests_profiles)) do
+ = link_to admin_conversational_development_index_path, title: 'Monitoring' do
+ .nav-icon-container
+ = custom_icon('monitoring')
+ %span.nav-item-name
+ Monitoring
- = nav_link(controller: :broadcast_messages) do
- = link_to admin_broadcast_messages_path, title: 'Messages' do
- .nav-icon-container
- = custom_icon('messages')
- %span.nav-item-name
- Messages
- = nav_link(controller: [:hooks, :hook_logs]) do
- = link_to admin_hooks_path, title: 'Hooks' do
- .nav-icon-container
- = custom_icon('system_hooks')
- %span.nav-item-name
- System Hooks
+ %ul.sidebar-sub-level-items
+ = nav_link(controller: :conversational_development_index) do
+ = link_to admin_conversational_development_index_path, title: 'ConvDev Index' do
+ %span
+ ConvDev Index
+ = nav_link(controller: :system_info) do
+ = link_to admin_system_info_path, title: 'System Info' do
+ %span
+ System Info
+ = nav_link(controller: :background_jobs) do
+ = link_to admin_background_jobs_path, title: 'Background Jobs' do
+ %span
+ Background Jobs
+ = nav_link(controller: :logs) do
+ = link_to admin_logs_path, title: 'Logs' do
+ %span
+ Logs
+ = nav_link(controller: :health_check) do
+ = link_to admin_health_check_path, title: 'Health Check' do
+ %span
+ Health Check
+ = nav_link(controller: :requests_profiles) do
+ = link_to admin_requests_profiles_path, title: 'Requests Profiles' do
+ %span
+ Requests Profiles
- = nav_link(controller: :applications) do
- = link_to admin_applications_path, title: 'Applications' do
- .nav-icon-container
- = custom_icon('applications')
- %span.nav-item-name
- Applications
+ = nav_link(controller: :broadcast_messages) do
+ = link_to admin_broadcast_messages_path, title: 'Messages' do
+ .nav-icon-container
+ = custom_icon('messages')
+ %span.nav-item-name
+ Messages
+ = nav_link(controller: [:hooks, :hook_logs]) do
+ = link_to admin_hooks_path, title: 'Hooks' do
+ .nav-icon-container
+ = custom_icon('system_hooks')
+ %span.nav-item-name
+ System Hooks
- = nav_link(controller: :abuse_reports) do
- = link_to admin_abuse_reports_path, title: "Abuse Reports" do
- .nav-icon-container
- = custom_icon('abuse_reports')
- %span.nav-item-name
- Abuse Reports
- %span.badge.count= number_with_delimiter(AbuseReport.count(:all))
+ = nav_link(controller: :applications) do
+ = link_to admin_applications_path, title: 'Applications' do
+ .nav-icon-container
+ = custom_icon('applications')
+ %span.nav-item-name
+ Applications
- - if akismet_enabled?
- = nav_link(controller: :spam_logs) do
- = link_to admin_spam_logs_path, title: "Spam Logs" do
+ = nav_link(controller: :abuse_reports) do
+ = link_to admin_abuse_reports_path, title: "Abuse Reports" do
.nav-icon-container
- = custom_icon('spam_logs')
+ = custom_icon('abuse_reports')
%span.nav-item-name
- Spam Logs
+ Abuse Reports
+ %span.badge.count= number_with_delimiter(AbuseReport.count(:all))
- = nav_link(controller: :deploy_keys) do
- = link_to admin_deploy_keys_path, title: 'Deploy Keys' do
- .nav-icon-container
- = custom_icon('key')
- %span.nav-item-name
- Deploy Keys
+ - if akismet_enabled?
+ = nav_link(controller: :spam_logs) do
+ = link_to admin_spam_logs_path, title: "Spam Logs" do
+ .nav-icon-container
+ = custom_icon('spam_logs')
+ %span.nav-item-name
+ Spam Logs
- = nav_link(controller: :services) do
- = link_to admin_application_settings_services_path, title: 'Service Templates' do
- .nav-icon-container
- = custom_icon('service_templates')
- %span.nav-item-name
- Service Templates
+ = nav_link(controller: :deploy_keys) do
+ = link_to admin_deploy_keys_path, title: 'Deploy Keys' do
+ .nav-icon-container
+ = custom_icon('key')
+ %span.nav-item-name
+ Deploy Keys
- = nav_link(controller: :labels) do
- = link_to admin_labels_path, title: 'Labels' do
- .nav-icon-container
- = custom_icon('labels')
- %span.nav-item-name
- Labels
+ = nav_link(controller: :services) do
+ = link_to admin_application_settings_services_path, title: 'Service Templates' do
+ .nav-icon-container
+ = custom_icon('service_templates')
+ %span.nav-item-name
+ Service Templates
- = nav_link(controller: :appearances) do
- = link_to admin_appearances_path, title: 'Appearances' do
- .nav-icon-container
- = custom_icon('appearance')
- %span.nav-item-name
- Appearance
+ = nav_link(controller: :labels) do
+ = link_to admin_labels_path, title: 'Labels' do
+ .nav-icon-container
+ = custom_icon('labels')
+ %span.nav-item-name
+ Labels
- %li.divider
- = nav_link(controller: :application_settings) do
- = link_to admin_application_settings_path, title: 'Settings' do
- .nav-icon-container
- = custom_icon('settings')
- %span.nav-item-name
- Settings
+ = nav_link(controller: :appearances) do
+ = link_to admin_appearances_path, title: 'Appearances' do
+ .nav-icon-container
+ = custom_icon('appearance')
+ %span.nav-item-name
+ Appearance
+
+ %li.divider
+ = nav_link(controller: :application_settings) do
+ = link_to admin_application_settings_path, title: 'Settings' do
+ .nav-icon-container
+ = custom_icon('settings')
+ %span.nav-item-name
+ Settings
- = render 'shared/sidebar_toggle_button'
+ = render 'shared/sidebar_toggle_button'
diff --git a/app/views/layouts/nav/_new_group_sidebar.html.haml b/app/views/layouts/nav/_new_group_sidebar.html.haml
index c7dabbd8237..ed5793f09fe 100644
--- a/app/views/layouts/nav/_new_group_sidebar.html.haml
+++ b/app/views/layouts/nav/_new_group_sidebar.html.haml
@@ -1,89 +1,90 @@
.nav-sidebar{ class: ("sidebar-icons-only" if collapsed_sidebar?) }
- .context-header
- = link_to group_path(@group), title: @group.name do
- .avatar-container.s40.group-avatar
- = image_tag group_icon(@group), class: "avatar s40 avatar-tile"
- .group-title
- = @group.name
- %ul.sidebar-top-level-items
- = nav_link(path: ['groups#show', 'groups#activity', 'groups#subgroups'], html_options: { class: 'home' }) do
- = link_to group_path(@group), title: 'Group overview' do
- .nav-icon-container
- = custom_icon('project')
- %span.nav-item-name
- Overview
-
- %ul.sidebar-sub-level-items
- = nav_link(path: ['groups#show', 'groups#subgroups'], html_options: { class: 'home' }) do
- = link_to group_path(@group), title: 'Group details' do
- %span
- Details
-
- = nav_link(path: 'groups#activity') do
- = link_to activity_group_path(@group), title: 'Activity' do
- %span
- Activity
-
- = nav_link(path: ['groups#issues', 'labels#index', 'milestones#index']) do
- = link_to issues_group_path(@group), title: 'Issues' do
- .nav-icon-container
- = custom_icon('issues')
- %span.nav-item-name
- - issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute
- Issues
- %span.badge.count= number_with_delimiter(issues.count)
-
- %ul.sidebar-sub-level-items
- = nav_link(path: 'groups#issues', html_options: { class: 'home' }) do
- = link_to issues_group_path(@group), title: 'List' do
- %span
- List
+ .nav-sidebar-inner-scroll
+ .context-header
+ = link_to group_path(@group), title: @group.name do
+ .avatar-container.s40.group-avatar
+ = image_tag group_icon(@group), class: "avatar s40 avatar-tile"
+ .group-title
+ = @group.name
+ %ul.sidebar-top-level-items
+ = nav_link(path: ['groups#show', 'groups#activity', 'groups#subgroups'], html_options: { class: 'home' }) do
+ = link_to group_path(@group), title: 'Group overview' do
+ .nav-icon-container
+ = custom_icon('project')
+ %span.nav-item-name
+ Overview
- = nav_link(path: 'labels#index') do
- = link_to group_labels_path(@group), title: 'Labels' do
- %span
- Labels
+ %ul.sidebar-sub-level-items
+ = nav_link(path: ['groups#show', 'groups#subgroups'], html_options: { class: 'home' }) do
+ = link_to group_path(@group), title: 'Group details' do
+ %span
+ Details
- = nav_link(path: 'milestones#index') do
- = link_to group_milestones_path(@group), title: 'Milestones' do
- %span
- Milestones
+ = nav_link(path: 'groups#activity') do
+ = link_to activity_group_path(@group), title: 'Activity' do
+ %span
+ Activity
- = nav_link(path: 'groups#merge_requests') do
- = link_to merge_requests_group_path(@group), title: 'Merge Requests' do
- .nav-icon-container
- = custom_icon('mr_bold')
- %span.nav-item-name
- - merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened', non_archived: true).execute
- Merge Requests
- %span.badge.count= number_with_delimiter(merge_requests.count)
- = nav_link(path: 'group_members#index') do
- = link_to group_group_members_path(@group), title: 'Members' do
- .nav-icon-container
- = custom_icon('members')
- %span.nav-item-name
- Members
- - if current_user && can?(current_user, :admin_group, @group)
- = nav_link(path: %w[groups#projects groups#edit ci_cd#show]) do
- = link_to edit_group_path(@group), title: 'Settings' do
+ = nav_link(path: ['groups#issues', 'labels#index', 'milestones#index']) do
+ = link_to issues_group_path(@group), title: 'Issues' do
.nav-icon-container
- = custom_icon('settings')
+ = custom_icon('issues')
%span.nav-item-name
- Settings
+ - issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute
+ Issues
+ %span.badge.count= number_with_delimiter(issues.count)
+
%ul.sidebar-sub-level-items
- = nav_link(path: 'groups#edit') do
- = link_to edit_group_path(@group), title: 'General' do
+ = nav_link(path: 'groups#issues', html_options: { class: 'home' }) do
+ = link_to issues_group_path(@group), title: 'List' do
%span
- General
+ List
- = nav_link(path: 'groups#projects') do
- = link_to projects_group_path(@group), title: 'Projects' do
+ = nav_link(path: 'labels#index') do
+ = link_to group_labels_path(@group), title: 'Labels' do
%span
- Projects
+ Labels
- = nav_link(controller: :ci_cd) do
- = link_to group_settings_ci_cd_path(@group), title: 'CI / CD' do
+ = nav_link(path: 'milestones#index') do
+ = link_to group_milestones_path(@group), title: 'Milestones' do
%span
- CI / CD
+ Milestones
+
+ = nav_link(path: 'groups#merge_requests') do
+ = link_to merge_requests_group_path(@group), title: 'Merge Requests' do
+ .nav-icon-container
+ = custom_icon('mr_bold')
+ %span.nav-item-name
+ - merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened', non_archived: true).execute
+ Merge Requests
+ %span.badge.count= number_with_delimiter(merge_requests.count)
+ = nav_link(path: 'group_members#index') do
+ = link_to group_group_members_path(@group), title: 'Members' do
+ .nav-icon-container
+ = custom_icon('members')
+ %span.nav-item-name
+ Members
+ - if current_user && can?(current_user, :admin_group, @group)
+ = nav_link(path: %w[groups#projects groups#edit ci_cd#show]) do
+ = link_to edit_group_path(@group), title: 'Settings' do
+ .nav-icon-container
+ = custom_icon('settings')
+ %span.nav-item-name
+ Settings
+ %ul.sidebar-sub-level-items
+ = nav_link(path: 'groups#edit') do
+ = link_to edit_group_path(@group), title: 'General' do
+ %span
+ General
+
+ = nav_link(path: 'groups#projects') do
+ = link_to projects_group_path(@group), title: 'Projects' do
+ %span
+ Projects
+
+ = nav_link(controller: :ci_cd) do
+ = link_to group_settings_ci_cd_path(@group), title: 'CI / CD' do
+ %span
+ CI / CD
- = render 'shared/sidebar_toggle_button'
+ = render 'shared/sidebar_toggle_button'
diff --git a/app/views/layouts/nav/_new_profile_sidebar.html.haml b/app/views/layouts/nav/_new_profile_sidebar.html.haml
index edae009a28e..4234df56d1d 100644
--- a/app/views/layouts/nav/_new_profile_sidebar.html.haml
+++ b/app/views/layouts/nav/_new_profile_sidebar.html.haml
@@ -1,84 +1,85 @@
.nav-sidebar{ class: ("sidebar-icons-only" if collapsed_sidebar?) }
- .context-header
- = link_to profile_path, title: 'Profile Settings' do
- .avatar-container.s40.settings-avatar
- = icon('user')
- .project-title User Settings
- %ul.sidebar-top-level-items
- = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
+ .nav-sidebar-inner-scroll
+ .context-header
= link_to profile_path, title: 'Profile Settings' do
- .nav-icon-container
- = custom_icon('profile')
- %span.nav-item-name
- Profile
- = nav_link(controller: [:accounts, :two_factor_auths]) do
- = link_to profile_account_path, title: 'Account' do
- .nav-icon-container
- = custom_icon('account')
- %span.nav-item-name
- Account
- - if current_application_settings.user_oauth_applications?
- = nav_link(controller: 'oauth/applications') do
- = link_to applications_profile_path, title: 'Applications' do
+ .avatar-container.s40.settings-avatar
+ = icon('user')
+ .project-title User Settings
+ %ul.sidebar-top-level-items
+ = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do
+ = link_to profile_path, title: 'Profile Settings' do
.nav-icon-container
- = custom_icon('applications')
+ = custom_icon('profile')
%span.nav-item-name
- Applications
- = nav_link(controller: :chat_names) do
- = link_to profile_chat_names_path, title: 'Chat' do
- .nav-icon-container
- = custom_icon('chat')
- %span.nav-item-name
- Chat
- = nav_link(controller: :personal_access_tokens) do
- = link_to profile_personal_access_tokens_path, title: 'Access Tokens' do
- .nav-icon-container
- = custom_icon('access_tokens')
- %span.nav-item-name
- Access Tokens
- = nav_link(controller: :emails) do
- = link_to profile_emails_path, title: 'Emails' do
- .nav-icon-container
- = custom_icon('emails')
- %span.nav-item-name
- Emails
- - unless current_user.ldap_user?
- = nav_link(controller: :passwords) do
- = link_to edit_profile_password_path, title: 'Password' do
+ Profile
+ = nav_link(controller: [:accounts, :two_factor_auths]) do
+ = link_to profile_account_path, title: 'Account' do
.nav-icon-container
- = custom_icon('lock')
+ = custom_icon('account')
%span.nav-item-name
- Password
- = nav_link(controller: :notifications) do
- = link_to profile_notifications_path, title: 'Notifications' do
- .nav-icon-container
- = custom_icon('notifications')
- %span.nav-item-name
- Notifications
+ Account
+ - if current_application_settings.user_oauth_applications?
+ = nav_link(controller: 'oauth/applications') do
+ = link_to applications_profile_path, title: 'Applications' do
+ .nav-icon-container
+ = custom_icon('applications')
+ %span.nav-item-name
+ Applications
+ = nav_link(controller: :chat_names) do
+ = link_to profile_chat_names_path, title: 'Chat' do
+ .nav-icon-container
+ = custom_icon('chat')
+ %span.nav-item-name
+ Chat
+ = nav_link(controller: :personal_access_tokens) do
+ = link_to profile_personal_access_tokens_path, title: 'Access Tokens' do
+ .nav-icon-container
+ = custom_icon('access_tokens')
+ %span.nav-item-name
+ Access Tokens
+ = nav_link(controller: :emails) do
+ = link_to profile_emails_path, title: 'Emails' do
+ .nav-icon-container
+ = custom_icon('emails')
+ %span.nav-item-name
+ Emails
+ - unless current_user.ldap_user?
+ = nav_link(controller: :passwords) do
+ = link_to edit_profile_password_path, title: 'Password' do
+ .nav-icon-container
+ = custom_icon('lock')
+ %span.nav-item-name
+ Password
+ = nav_link(controller: :notifications) do
+ = link_to profile_notifications_path, title: 'Notifications' do
+ .nav-icon-container
+ = custom_icon('notifications')
+ %span.nav-item-name
+ Notifications
- = nav_link(controller: :keys) do
- = link_to profile_keys_path, title: 'SSH Keys' do
- .nav-icon-container
- = custom_icon('key')
- %span.nav-item-name
- SSH Keys
- = nav_link(controller: :gpg_keys) do
- = link_to profile_gpg_keys_path, title: 'GPG Keys' do
- .nav-icon-container
- = custom_icon('key_2')
- %span.nav-item-name
- GPG Keys
- = nav_link(controller: :preferences) do
- = link_to profile_preferences_path, title: 'Preferences' do
- .nav-icon-container
- = custom_icon('preferences')
- %span.nav-item-name
- Preferences
- = nav_link(path: 'profiles#audit_log') do
- = link_to audit_log_profile_path, title: 'Authentication log' do
- .nav-icon-container
- = custom_icon('authentication_log')
- %span.nav-item-name
- Authentication log
+ = nav_link(controller: :keys) do
+ = link_to profile_keys_path, title: 'SSH Keys' do
+ .nav-icon-container
+ = custom_icon('key')
+ %span.nav-item-name
+ SSH Keys
+ = nav_link(controller: :gpg_keys) do
+ = link_to profile_gpg_keys_path, title: 'GPG Keys' do
+ .nav-icon-container
+ = custom_icon('key_2')
+ %span.nav-item-name
+ GPG Keys
+ = nav_link(controller: :preferences) do
+ = link_to profile_preferences_path, title: 'Preferences' do
+ .nav-icon-container
+ = custom_icon('preferences')
+ %span.nav-item-name
+ Preferences
+ = nav_link(path: 'profiles#audit_log') do
+ = link_to audit_log_profile_path, title: 'Authentication log' do
+ .nav-icon-container
+ = custom_icon('authentication_log')
+ %span.nav-item-name
+ Authentication log
- = render 'shared/sidebar_toggle_button'
+ = render 'shared/sidebar_toggle_button'
diff --git a/app/views/layouts/nav/_new_project_sidebar.html.haml b/app/views/layouts/nav/_new_project_sidebar.html.haml
index e0477c29ebe..0ef81375c3a 100644
--- a/app/views/layouts/nav/_new_project_sidebar.html.haml
+++ b/app/views/layouts/nav/_new_project_sidebar.html.haml
@@ -1,261 +1,262 @@
.nav-sidebar{ class: ("sidebar-icons-only" if collapsed_sidebar?) }
- - can_edit = can?(current_user, :admin_project, @project)
- .context-header
- = link_to project_path(@project), title: @project.name do
- .avatar-container.s40.project-avatar
- = project_icon(@project, alt: @project.name, class: 'avatar s40 avatar-tile')
- .project-title
- = @project.name
- %ul.sidebar-top-level-items
- = nav_link(path: ['projects#show', 'projects#activity', 'cycle_analytics#show'], html_options: { class: 'home' }) do
- = link_to project_path(@project), title: 'Project overview', class: 'shortcuts-project' do
- .nav-icon-container
- = custom_icon('project')
- %span.nav-item-name
- Overview
-
- %ul.sidebar-sub-level-items
- = nav_link(path: 'projects#show') do
- = link_to project_path(@project), title: _('Project details'), class: 'shortcuts-project' do
- %span= _('Details')
-
- = nav_link(path: 'projects#activity') do
- = link_to activity_project_path(@project), title: _('Activity'), class: 'shortcuts-project-activity' do
- %span= _('Activity')
-
- - if can?(current_user, :read_cycle_analytics, @project)
- = nav_link(path: 'cycle_analytics#show') do
- = link_to project_cycle_analytics_path(@project), title: _('Cycle Analytics'), class: 'shortcuts-project-cycle-analytics' do
- %span= _('Cycle Analytics')
-
- - if project_nav_tab? :files
- = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare projects/repositories tags branches releases graphs network)) do
- = link_to project_tree_path(@project), title: 'Repository', class: 'shortcuts-tree' do
+ .nav-sidebar-inner-scroll
+ - can_edit = can?(current_user, :admin_project, @project)
+ .context-header
+ = link_to project_path(@project), title: @project.name do
+ .avatar-container.s40.project-avatar
+ = project_icon(@project, alt: @project.name, class: 'avatar s40 avatar-tile')
+ .project-title
+ = @project.name
+ %ul.sidebar-top-level-items
+ = nav_link(path: ['projects#show', 'projects#activity', 'cycle_analytics#show'], html_options: { class: 'home' }) do
+ = link_to project_path(@project), title: 'Project overview', class: 'shortcuts-project' do
.nav-icon-container
- = custom_icon('doc_text')
+ = custom_icon('project')
%span.nav-item-name
- Repository
+ Overview
%ul.sidebar-sub-level-items
- = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file)) do
- = link_to project_tree_path(@project) do
- #{ _('Files') }
-
- = nav_link(controller: [:commit, :commits]) do
- = link_to project_commits_path(@project, current_ref) do
- #{ _('Commits') }
-
- = nav_link(html_options: {class: branches_tab_class}) do
- = link_to project_branches_path(@project) do
- #{ _('Branches') }
-
- = nav_link(controller: [:tags, :releases]) do
- = link_to project_tags_path(@project) do
- #{ _('Tags') }
-
- = nav_link(path: 'graphs#show') do
- = link_to project_graph_path(@project, current_ref) do
- #{ _('Contributors') }
-
- = nav_link(controller: %w(network)) do
- = link_to project_network_path(@project, current_ref) do
- #{ s_('ProjectNetworkGraph|Graph') }
-
- = nav_link(controller: :compare) do
- = link_to project_compare_index_path(@project, from: @repository.root_ref, to: current_ref) do
- #{ _('Compare') }
-
- = nav_link(path: 'graphs#charts') do
- = link_to charts_project_graph_path(@project, current_ref) do
- #{ _('Charts') }
-
- - if project_nav_tab? :container_registry
- = nav_link(controller: %w[projects/registry/repositories]) do
- = link_to project_container_registry_index_path(@project), title: 'Container Registry', class: 'shortcuts-container-registry' do
- .nav-icon-container
- = custom_icon('container_registry')
- %span.nav-item-name
- Registry
-
- - if project_nav_tab? :issues
- = nav_link(controller: @project.issues_enabled? ? [:issues, :labels, :milestones, :boards] : :issues) do
- = link_to project_issues_path(@project), title: 'Issues', class: 'shortcuts-issues' do
- .nav-icon-container
- = custom_icon('issues')
- %span.nav-item-name
- Issues
- - if @project.issues_enabled?
- %span.badge.count.issue_counter= number_with_delimiter(IssuesFinder.new(current_user, project_id: @project.id).execute.opened.count)
-
- %ul.sidebar-sub-level-items
- = nav_link(controller: :issues) do
- = link_to project_issues_path(@project), title: 'Issues' do
- %span
- List
-
- = nav_link(controller: :boards) do
- = link_to project_boards_path(@project), title: 'Board' do
- %span
- Board
-
- = nav_link(controller: :labels) do
- = link_to project_labels_path(@project), title: 'Labels' do
- %span
- Labels
-
- = nav_link(controller: :milestones) do
- = link_to project_milestones_path(@project), title: 'Milestones' do
- %span
- Milestones
-
- - if project_nav_tab? :merge_requests
- = nav_link(controller: @project.issues_enabled? ? :merge_requests : [:merge_requests, :labels, :milestones]) do
- = link_to project_merge_requests_path(@project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do
- .nav-icon-container
- = custom_icon('mr_bold')
- %span.nav-item-name
- Merge Requests
- %span.badge.count.merge_counter.js-merge-counter= number_with_delimiter(MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened.count)
-
- - if project_nav_tab? :pipelines
- = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :environments, :artifacts]) do
- = link_to project_pipelines_path(@project), title: 'CI / CD', class: 'shortcuts-pipelines' do
- .nav-icon-container
- = custom_icon('pipeline')
- %span.nav-item-name
- CI / CD
-
- %ul.sidebar-sub-level-items
- - if project_nav_tab? :pipelines
- = nav_link(path: ['pipelines#index', 'pipelines#show']) do
- = link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do
- %span
- Pipelines
-
- - if project_nav_tab? :builds
- = nav_link(controller: [:jobs, :artifacts]) do
- = link_to project_jobs_path(@project), title: 'Jobs', class: 'shortcuts-builds' do
+ = nav_link(path: 'projects#show') do
+ = link_to project_path(@project), title: _('Project details'), class: 'shortcuts-project' do
+ %span= _('Details')
+
+ = nav_link(path: 'projects#activity') do
+ = link_to activity_project_path(@project), title: _('Activity'), class: 'shortcuts-project-activity' do
+ %span= _('Activity')
+
+ - if can?(current_user, :read_cycle_analytics, @project)
+ = nav_link(path: 'cycle_analytics#show') do
+ = link_to project_cycle_analytics_path(@project), title: _('Cycle Analytics'), class: 'shortcuts-project-cycle-analytics' do
+ %span= _('Cycle Analytics')
+
+ - if project_nav_tab? :files
+ = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare projects/repositories tags branches releases graphs network)) do
+ = link_to project_tree_path(@project), title: 'Repository', class: 'shortcuts-tree' do
+ .nav-icon-container
+ = custom_icon('doc_text')
+ %span.nav-item-name
+ Repository
+
+ %ul.sidebar-sub-level-items
+ = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file)) do
+ = link_to project_tree_path(@project) do
+ #{ _('Files') }
+
+ = nav_link(controller: [:commit, :commits]) do
+ = link_to project_commits_path(@project, current_ref) do
+ #{ _('Commits') }
+
+ = nav_link(html_options: {class: branches_tab_class}) do
+ = link_to project_branches_path(@project) do
+ #{ _('Branches') }
+
+ = nav_link(controller: [:tags, :releases]) do
+ = link_to project_tags_path(@project) do
+ #{ _('Tags') }
+
+ = nav_link(path: 'graphs#show') do
+ = link_to project_graph_path(@project, current_ref) do
+ #{ _('Contributors') }
+
+ = nav_link(controller: %w(network)) do
+ = link_to project_network_path(@project, current_ref) do
+ #{ s_('ProjectNetworkGraph|Graph') }
+
+ = nav_link(controller: :compare) do
+ = link_to project_compare_index_path(@project, from: @repository.root_ref, to: current_ref) do
+ #{ _('Compare') }
+
+ = nav_link(path: 'graphs#charts') do
+ = link_to charts_project_graph_path(@project, current_ref) do
+ #{ _('Charts') }
+
+ - if project_nav_tab? :container_registry
+ = nav_link(controller: %w[projects/registry/repositories]) do
+ = link_to project_container_registry_index_path(@project), title: 'Container Registry', class: 'shortcuts-container-registry' do
+ .nav-icon-container
+ = custom_icon('container_registry')
+ %span.nav-item-name
+ Registry
+
+ - if project_nav_tab? :issues
+ = nav_link(controller: @project.issues_enabled? ? [:issues, :labels, :milestones, :boards] : :issues) do
+ = link_to project_issues_path(@project), title: 'Issues', class: 'shortcuts-issues' do
+ .nav-icon-container
+ = custom_icon('issues')
+ %span.nav-item-name
+ Issues
+ - if @project.issues_enabled?
+ %span.badge.count.issue_counter= number_with_delimiter(IssuesFinder.new(current_user, project_id: @project.id).execute.opened.count)
+
+ %ul.sidebar-sub-level-items
+ = nav_link(controller: :issues) do
+ = link_to project_issues_path(@project), title: 'Issues' do
%span
- Jobs
+ List
- - if project_nav_tab? :pipelines
- = nav_link(controller: :pipeline_schedules) do
- = link_to pipeline_schedules_path(@project), title: 'Schedules', class: 'shortcuts-builds' do
+ = nav_link(controller: :boards) do
+ = link_to project_boards_path(@project), title: 'Board' do
%span
- Schedules
+ Board
- - if project_nav_tab? :environments
- = nav_link(controller: :environments) do
- = link_to project_environments_path(@project), title: 'Environments', class: 'shortcuts-environments' do
+ = nav_link(controller: :labels) do
+ = link_to project_labels_path(@project), title: 'Labels' do
%span
- Environments
+ Labels
- - if @project.feature_available?(:builds, current_user) && !@project.empty_repo?
- = nav_link(path: 'pipelines#charts') do
- = link_to charts_project_pipelines_path(@project), title: 'Charts', class: 'shortcuts-pipelines-charts' do
+ = nav_link(controller: :milestones) do
+ = link_to project_milestones_path(@project), title: 'Milestones' do
%span
- Charts
+ Milestones
+
+ - if project_nav_tab? :merge_requests
+ = nav_link(controller: @project.issues_enabled? ? :merge_requests : [:merge_requests, :labels, :milestones]) do
+ = link_to project_merge_requests_path(@project), title: 'Merge Requests', class: 'shortcuts-merge_requests' do
+ .nav-icon-container
+ = custom_icon('mr_bold')
+ %span.nav-item-name
+ Merge Requests
+ %span.badge.count.merge_counter.js-merge-counter= number_with_delimiter(MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened.count)
+
+ - if project_nav_tab? :pipelines
+ = nav_link(controller: [:pipelines, :builds, :jobs, :pipeline_schedules, :environments, :artifacts]) do
+ = link_to project_pipelines_path(@project), title: 'CI / CD', class: 'shortcuts-pipelines' do
+ .nav-icon-container
+ = custom_icon('pipeline')
+ %span.nav-item-name
+ CI / CD
+
+ %ul.sidebar-sub-level-items
+ - if project_nav_tab? :pipelines
+ = nav_link(path: ['pipelines#index', 'pipelines#show']) do
+ = link_to project_pipelines_path(@project), title: 'Pipelines', class: 'shortcuts-pipelines' do
+ %span
+ Pipelines
- - if project_nav_tab? :wiki
- = nav_link(controller: :wikis) do
- = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do
- .nav-icon-container
- = custom_icon('wiki')
- %span.nav-item-name
- Wiki
+ - if project_nav_tab? :builds
+ = nav_link(controller: [:jobs, :artifacts]) do
+ = link_to project_jobs_path(@project), title: 'Jobs', class: 'shortcuts-builds' do
+ %span
+ Jobs
- - if project_nav_tab? :snippets
- = nav_link(controller: :snippets) do
- = link_to project_snippets_path(@project), title: 'Snippets', class: 'shortcuts-snippets' do
- .nav-icon-container
- = custom_icon('snippets')
- %span.nav-item-name
- Snippets
+ - if project_nav_tab? :pipelines
+ = nav_link(controller: :pipeline_schedules) do
+ = link_to pipeline_schedules_path(@project), title: 'Schedules', class: 'shortcuts-builds' do
+ %span
+ Schedules
- - if project_nav_tab? :settings
- = nav_link(path: %w[projects#edit project_members#index integrations#show services#edit repository#show ci_cd#show pages#show]) do
- = link_to edit_project_path(@project), title: 'Settings', class: 'shortcuts-tree' do
- .nav-icon-container
- = custom_icon('settings')
- %span.nav-item-name
- Settings
+ - if project_nav_tab? :environments
+ = nav_link(controller: :environments) do
+ = link_to project_environments_path(@project), title: 'Environments', class: 'shortcuts-environments' do
+ %span
+ Environments
- %ul.sidebar-sub-level-items
- - can_edit = can?(current_user, :admin_project, @project)
- - if can_edit
- = nav_link(path: %w[projects#edit]) do
- = link_to edit_project_path(@project), title: 'General' do
- %span
- General
- = nav_link(controller: :project_members) do
- = link_to project_project_members_path(@project), title: 'Members' do
- %span
- Members
- - if can_edit
- = nav_link(controller: [:integrations, :services, :hooks, :hook_logs]) do
- = link_to project_settings_integrations_path(@project), title: 'Integrations' do
- %span
- Integrations
- = nav_link(controller: :repository) do
- = link_to project_settings_repository_path(@project), title: 'Repository' do
+ - if @project.feature_available?(:builds, current_user) && !@project.empty_repo?
+ = nav_link(path: 'pipelines#charts') do
+ = link_to charts_project_pipelines_path(@project), title: 'Charts', class: 'shortcuts-pipelines-charts' do
+ %span
+ Charts
+
+ - if project_nav_tab? :wiki
+ = nav_link(controller: :wikis) do
+ = link_to get_project_wiki_path(@project), title: 'Wiki', class: 'shortcuts-wiki' do
+ .nav-icon-container
+ = custom_icon('wiki')
+ %span.nav-item-name
+ Wiki
+
+ - if project_nav_tab? :snippets
+ = nav_link(controller: :snippets) do
+ = link_to project_snippets_path(@project), title: 'Snippets', class: 'shortcuts-snippets' do
+ .nav-icon-container
+ = custom_icon('snippets')
+ %span.nav-item-name
+ Snippets
+
+ - if project_nav_tab? :settings
+ = nav_link(path: %w[projects#edit project_members#index integrations#show services#edit repository#show ci_cd#show pages#show]) do
+ = link_to edit_project_path(@project), title: 'Settings', class: 'shortcuts-tree' do
+ .nav-icon-container
+ = custom_icon('settings')
+ %span.nav-item-name
+ Settings
+
+ %ul.sidebar-sub-level-items
+ - can_edit = can?(current_user, :admin_project, @project)
+ - if can_edit
+ = nav_link(path: %w[projects#edit]) do
+ = link_to edit_project_path(@project), title: 'General' do
+ %span
+ General
+ = nav_link(controller: :project_members) do
+ = link_to project_project_members_path(@project), title: 'Members' do
%span
- Repository
- - if @project.feature_available?(:builds, current_user)
- = nav_link(controller: :ci_cd) do
- = link_to project_settings_ci_cd_path(@project), title: 'CI / CD' do
+ Members
+ - if can_edit
+ = nav_link(controller: [:integrations, :services, :hooks, :hook_logs]) do
+ = link_to project_settings_integrations_path(@project), title: 'Integrations' do
%span
- CI / CD
- - if Gitlab.config.pages.enabled
- = nav_link(controller: :pages) do
- = link_to project_pages_path(@project), title: 'Pages' do
+ Integrations
+ = nav_link(controller: :repository) do
+ = link_to project_settings_repository_path(@project), title: 'Repository' do
%span
- Pages
-
- - else
- = nav_link(path: %w[members#show]) do
- = link_to project_settings_members_path(@project), title: 'Members', class: 'shortcuts-tree' do
- .nav-icon-container
- = custom_icon('members')
- %span.nav-item-name
- Members
-
- = render 'shared/sidebar_toggle_button'
-
- -# Shortcut to Project > Activity
- %li.hidden
- = link_to activity_project_path(@project), title: 'Activity', class: 'shortcuts-project-activity' do
- %span
- Activity
-
- -# Shortcut to Repository > Graph (formerly, Network)
- - if project_nav_tab? :network
+ Repository
+ - if @project.feature_available?(:builds, current_user)
+ = nav_link(controller: :ci_cd) do
+ = link_to project_settings_ci_cd_path(@project), title: 'CI / CD' do
+ %span
+ CI / CD
+ - if Gitlab.config.pages.enabled
+ = nav_link(controller: :pages) do
+ = link_to project_pages_path(@project), title: 'Pages' do
+ %span
+ Pages
+
+ - else
+ = nav_link(path: %w[members#show]) do
+ = link_to project_settings_members_path(@project), title: 'Members', class: 'shortcuts-tree' do
+ .nav-icon-container
+ = custom_icon('members')
+ %span.nav-item-name
+ Members
+
+ = render 'shared/sidebar_toggle_button'
+
+ -# Shortcut to Project > Activity
%li.hidden
- = link_to project_network_path(@project, current_ref), title: 'Network', class: 'shortcuts-network' do
- Graph
-
- -# Shortcut to Repository > Charts (formerly, top-nav item "Graphs")
- - unless @project.empty_repo?
- %li.hidden
- = link_to charts_project_graph_path(@project, current_ref), title: 'Charts', class: 'shortcuts-repository-charts' do
- Charts
-
- -# Shortcut to Issues > New Issue
- %li.hidden
- = link_to new_project_issue_path(@project), class: 'shortcuts-new-issue' do
- Create a new issue
-
- -# Shortcut to Pipelines > Jobs
- - if project_nav_tab? :builds
+ = link_to activity_project_path(@project), title: 'Activity', class: 'shortcuts-project-activity' do
+ %span
+ Activity
+
+ -# Shortcut to Repository > Graph (formerly, Network)
+ - if project_nav_tab? :network
+ %li.hidden
+ = link_to project_network_path(@project, current_ref), title: 'Network', class: 'shortcuts-network' do
+ Graph
+
+ -# Shortcut to Repository > Charts (formerly, top-nav item "Graphs")
+ - unless @project.empty_repo?
+ %li.hidden
+ = link_to charts_project_graph_path(@project, current_ref), title: 'Charts', class: 'shortcuts-repository-charts' do
+ Charts
+
+ -# Shortcut to Issues > New Issue
%li.hidden
- = link_to project_jobs_path(@project), title: 'Jobs', class: 'shortcuts-builds' do
- Jobs
-
- -# Shortcut to commits page
- - if project_nav_tab? :commits
+ = link_to new_project_issue_path(@project), class: 'shortcuts-new-issue' do
+ Create a new issue
+
+ -# Shortcut to Pipelines > Jobs
+ - if project_nav_tab? :builds
+ %li.hidden
+ = link_to project_jobs_path(@project), title: 'Jobs', class: 'shortcuts-builds' do
+ Jobs
+
+ -# Shortcut to commits page
+ - if project_nav_tab? :commits
+ %li.hidden
+ = link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits' do
+ Commits
+
+ -# Shortcut to issue boards
%li.hidden
- = link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits' do
- Commits
-
- -# Shortcut to issue boards
- %li.hidden
- = link_to 'Issue Boards', project_boards_path(@project), title: 'Issue Boards', class: 'shortcuts-issue-boards'
+ = link_to 'Issue Boards', project_boards_path(@project), title: 'Issue Boards', class: 'shortcuts-issue-boards'
diff --git a/app/views/projects/merge_requests/_discussion.html.haml b/app/views/projects/merge_requests/_discussion.html.haml
index b787edb3427..3303aa72604 100644
--- a/app/views/projects/merge_requests/_discussion.html.haml
+++ b/app/views/projects/merge_requests/_discussion.html.haml
@@ -4,8 +4,8 @@
= link_to 'Close merge request', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, class: "btn btn-nr btn-comment btn-close close-mr-link js-note-target-close", title: "Close merge request", data: { original_text: "Close merge request", alternative_text: "Comment & close merge request"}
- if @merge_request.reopenable?
= link_to 'Reopen merge request', merge_request_path(@merge_request, merge_request: { state_event: :reopen }), method: :put, class: "btn btn-nr btn-comment btn-reopen reopen-mr-link js-note-target-close js-note-target-reopen", title: "Reopen merge request", data: { original_text: "Reopen merge request", alternative_text: "Comment & reopen merge request"}
- %comment-and-resolve-btn{ "inline-template" => true, ":discussion-id" => "" }
- %button.btn.btn-nr.btn-default.append-right-10.js-comment-resolve-button{ "v-if" => "showButton", type: "submit", data: { project_path: "#{project_path(@merge_request.project)}" } }
- {{ buttonText }}
+ %comment-and-resolve-btn{ "inline-template" => true }
+ %button.btn.btn-nr.btn-default.append-right-10.js-comment-resolve-button{ "v-if" => "showButton", type: "submit", data: { project_path: "#{project_path(@merge_request.project)}" } }
+ {{ buttonText }}
#notes= render "shared/notes/notes_with_form", :autocomplete => true
diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml
index 6f6a036b13f..6a85f7d0564 100644
--- a/app/views/shared/milestones/_milestone.html.haml
+++ b/app/views/shared/milestones/_milestone.html.haml
@@ -32,7 +32,7 @@
.col-sm-6.milestone-actions
- if can?(current_user, :admin_milestones, @group)
- if milestone.is_group_milestone?
- = link_to edit_group_milestone_path(@group, milestone.id), class: "btn btn-xs btn-grouped" do
+ = link_to edit_group_milestone_path(@group, milestone), class: "btn btn-xs btn-grouped" do
Edit
\
- if milestone.closed?
diff --git a/app/views/shared/milestones/_top.html.haml b/app/views/shared/milestones/_top.html.haml
index b93837e3087..3014300fbe7 100644
--- a/app/views/shared/milestones/_top.html.haml
+++ b/app/views/shared/milestones/_top.html.haml
@@ -23,7 +23,7 @@
.pull-right
- if can?(current_user, :admin_milestones, group)
- if milestone.is_group_milestone?
- = link_to edit_group_milestone_path(group, milestone.iid), class: "btn btn btn-grouped" do
+ = link_to edit_group_milestone_path(group, milestone), class: "btn btn btn-grouped" do
Edit
- if milestone.active?
= link_to 'Close Milestone', group_milestone_route(milestone, {state_event: :close }), method: :put, class: "btn btn-grouped btn-close"
diff --git a/app/workers/gitlab_shell_worker.rb b/app/workers/gitlab_shell_worker.rb
index 964287a1793..0ec871e00e1 100644
--- a/app/workers/gitlab_shell_worker.rb
+++ b/app/workers/gitlab_shell_worker.rb
@@ -4,6 +4,6 @@ class GitlabShellWorker
include DedicatedSidekiqQueue
def perform(action, *arg)
- gitlab_shell.send(action, *arg)
+ gitlab_shell.__send__(action, *arg) # rubocop:disable GitlabSecurity/PublicSend
end
end
diff --git a/changelogs/unreleased/34049-public-commits-should-not-require-authentication.yml b/changelogs/unreleased/34049-public-commits-should-not-require-authentication.yml
new file mode 100644
index 00000000000..278ef2a8acb
--- /dev/null
+++ b/changelogs/unreleased/34049-public-commits-should-not-require-authentication.yml
@@ -0,0 +1,4 @@
+---
+title: Added tests for commits API unauthenticated user and public/private project
+merge_request: 13287
+author: Jacopo Beschi @jacopo-beschi
diff --git a/changelogs/unreleased/34643-fix-project-path-slugify.yml b/changelogs/unreleased/34643-fix-project-path-slugify.yml
new file mode 100644
index 00000000000..f7018a1aca5
--- /dev/null
+++ b/changelogs/unreleased/34643-fix-project-path-slugify.yml
@@ -0,0 +1,4 @@
+---
+title: Fix CI_PROJECT_PATH_SLUG slugify
+merge_request: 13350
+author: Ivan Chernov
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index e73db08fcac..25285525846 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -649,6 +649,9 @@ test:
default:
path: tmp/tests/repositories/
gitaly_address: unix:tmp/tests/gitaly/gitaly.socket
+ failure_count_threshold: 999999
+ failure_wait_time: 0
+ storage_timeout: 30
broken:
path: tmp/tests/non-existent-repositories
gitaly_address: unix:tmp/tests/gitaly/gitaly.socket
diff --git a/config/initializers/0_acts_as_taggable.rb b/config/initializers/0_acts_as_taggable.rb
index 54e9fcc31db..50dc47673ab 100644
--- a/config/initializers/0_acts_as_taggable.rb
+++ b/config/initializers/0_acts_as_taggable.rb
@@ -5,5 +5,5 @@ ActsAsTaggableOn.strict_case_match = true
ActsAsTaggableOn.tags_counter = false
# validate that counter cache is disabled
-raise "Counter cache is not disabled" if
+raise "Counter cache is not disabled" if
ActsAsTaggableOn::Tagging.reflections["tag"].options[:counter_cache]
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 5c6578d3531..38ade18bdc0 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -1,3 +1,5 @@
+# rubocop:disable GitlabSecurity/PublicSend
+
require_dependency Rails.root.join('lib/gitlab') # Load Gitlab as soon as possible
class Settings < Settingslogic
diff --git a/config/initializers/6_validations.rb b/config/initializers/6_validations.rb
index 92ce4dd03cd..f8e67ce04c9 100644
--- a/config/initializers/6_validations.rb
+++ b/config/initializers/6_validations.rb
@@ -37,12 +37,12 @@ def validate_storages_config
storage_validation_error("#{name} is not a valid storage, because it has no `path` key. Refer to gitlab.yml.example for an updated example")
end
- %w(failure_count_threshold failure_wait_time failure_reset_time storage_timeout).each do |setting|
+ %w(failure_count_threshold failure_reset_time storage_timeout).each do |setting|
# Falling back to the defaults is fine!
next if repository_storage[setting].nil?
unless repository_storage[setting].to_f > 0
- storage_validation_error("#{setting}, for storage `#{name}` needs to be greater than 0")
+ storage_validation_error("`#{setting}` for storage `#{name}` needs to be greater than 0")
end
end
end
diff --git a/config/initializers/static_files.rb b/config/initializers/static_files.rb
index 9ed96ddb0b4..943e01f1496 100644
--- a/config/initializers/static_files.rb
+++ b/config/initializers/static_files.rb
@@ -1,15 +1,15 @@
app = Rails.application
if app.config.serve_static_files
- # The `ActionDispatch::Static` middleware intercepts requests for static files
- # by checking if they exist in the `/public` directory.
+ # The `ActionDispatch::Static` middleware intercepts requests for static files
+ # by checking if they exist in the `/public` directory.
# We're replacing it with our `Gitlab::Middleware::Static` that does the same,
# except ignoring `/uploads`, letting those go through to the GitLab Rails app.
app.config.middleware.swap(
- ActionDispatch::Static,
- Gitlab::Middleware::Static,
- app.paths["public"].first,
+ ActionDispatch::Static,
+ Gitlab::Middleware::Static,
+ app.paths["public"].first,
app.config.static_cache_control
)
diff --git a/config/initializers/trusted_proxies.rb b/config/initializers/trusted_proxies.rb
index fc4f02453d7..0c32528311e 100644
--- a/config/initializers/trusted_proxies.rb
+++ b/config/initializers/trusted_proxies.rb
@@ -2,7 +2,7 @@
# as the ActionDispatch::Request object. This is necessary for libraries
# like rack_attack where they don't use ActionDispatch, and we want them
# to block/throttle requests on private networks.
-# Rack Attack specific issue: https://github.com/kickstarter/rack-attack/issues/145
+# Rack Attack specific issue: https://github.com/kickstarter/rack-attack/issues/145
module Rack
class Request
def trusted_proxy?(ip)
diff --git a/config/routes/repository.rb b/config/routes/repository.rb
index 57b7c55423d..9ffdebbcff1 100644
--- a/config/routes/repository.rb
+++ b/config/routes/repository.rb
@@ -3,7 +3,7 @@
resource :repository, only: [:create] do
member do
get ':ref/archive', constraints: { format: Gitlab::PathRegex.archive_formats_regex, ref: /.+/ }, action: 'archive', as: 'archive'
-
+
# deprecated since GitLab 9.5
get 'archive', constraints: { format: Gitlab::PathRegex.archive_formats_regex }, as: 'archive_alternative'
end
diff --git a/db/migrate/20161020075830_default_request_access_projects.rb b/db/migrate/20161020075830_default_request_access_projects.rb
index cb790291b24..a3a53350e8d 100644
--- a/db/migrate/20161020075830_default_request_access_projects.rb
+++ b/db/migrate/20161020075830_default_request_access_projects.rb
@@ -1,7 +1,7 @@
class DefaultRequestAccessProjects < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
-
+
def up
change_column_default :projects, :request_access_enabled, false
end
diff --git a/db/post_migrate/20170503004427_update_retried_for_ci_build.rb b/db/post_migrate/20170503004427_update_retried_for_ci_build.rb
index 705e11ed47d..3a4d6c4916b 100644
--- a/db/post_migrate/20170503004427_update_retried_for_ci_build.rb
+++ b/db/post_migrate/20170503004427_update_retried_for_ci_build.rb
@@ -21,7 +21,7 @@ class UpdateRetriedForCiBuild < ActiveRecord::Migration
private
def up_mysql
- # This is a trick to overcome MySQL limitation:
+ # This is a trick to overcome MySQL limitation:
# Mysql2::Error: Table 'ci_builds' is specified twice, both as a target for 'UPDATE' and as a separate source for data
# However, this leads to create a temporary table from `max(ci_builds.id)` which is slow and do full database update
execute <<-SQL.strip_heredoc
diff --git a/db/post_migrate/20170523083112_migrate_old_artifacts.rb b/db/post_migrate/20170523083112_migrate_old_artifacts.rb
index f2690bd0017..3a77b9751d3 100644
--- a/db/post_migrate/20170523083112_migrate_old_artifacts.rb
+++ b/db/post_migrate/20170523083112_migrate_old_artifacts.rb
@@ -7,7 +7,7 @@ class MigrateOldArtifacts < ActiveRecord::Migration
# This uses special heuristic to find potential candidates for data migration
# Read more about this here: https://gitlab.com/gitlab-org/gitlab-ce/issues/32036#note_30422345
-
+
def up
builds_with_artifacts.find_each do |build|
build.migrate_artifacts!
@@ -51,14 +51,14 @@ class MigrateOldArtifacts < ActiveRecord::Migration
private
def source_artifacts_path
- @source_artifacts_path ||=
+ @source_artifacts_path ||=
File.join(Gitlab.config.artifacts.path,
created_at.utc.strftime('%Y_%m'),
ci_id.to_s, id.to_s)
end
def target_artifacts_path
- @target_artifacts_path ||=
+ @target_artifacts_path ||=
File.join(Gitlab.config.artifacts.path,
created_at.utc.strftime('%Y_%m'),
project_id.to_s, id.to_s)
diff --git a/db/post_migrate/20170815060945_remove_duplicate_mr_events.rb b/db/post_migrate/20170815060945_remove_duplicate_mr_events.rb
new file mode 100644
index 00000000000..6132b553177
--- /dev/null
+++ b/db/post_migrate/20170815060945_remove_duplicate_mr_events.rb
@@ -0,0 +1,26 @@
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class RemoveDuplicateMrEvents < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+ DOWNTIME = false
+
+ class Event < ActiveRecord::Base
+ self.table_name = 'events'
+ end
+
+ def up
+ base_condition = "action = 1 AND target_type = 'MergeRequest' AND created_at > '2017-08-13'"
+ Event.select('target_id, count(*)')
+ .where(base_condition)
+ .group('target_id').having('count(*) > 1').each do |event|
+ duplicates = Event.where("#{base_condition} AND target_id = #{event.target_id}").pluck(:id)
+ duplicates.shift
+
+ Event.where(id: duplicates).delete_all
+ end
+ end
+
+ def down
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 3206e106552..2ea6ae29dc7 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20170809161910) do
+ActiveRecord::Schema.define(version: 20170815060945) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
diff --git a/doc/install/installation.md b/doc/install/installation.md
index b14cb2d44c4..66eb7675896 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -80,7 +80,7 @@ Make sure you have the right version of Git installed
# Install Git
sudo apt-get install -y git-core
- # Make sure Git is version 2.8.4 or higher
+ # Make sure Git is version 2.13.0 or higher
git --version
Is the system packaged Git too old? Remove it and compile from source.
diff --git a/doc/user/search/img/group_issues_filter.png b/doc/user/search/img/group_issues_filter.png
new file mode 100644
index 00000000000..45eced79b99
--- /dev/null
+++ b/doc/user/search/img/group_issues_filter.png
Binary files differ
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index 6d59dcc6c75..79f34fd29ba 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -40,6 +40,14 @@ The same process is valid for merge requests. Navigate to your project's **Merge
and click **Search or filter results...**. Merge requests can be filtered by author, assignee,
milestone, and label.
+## Issues and merge requests per group
+
+Similar to **Issues and merge requests per project**, you can also search for issues
+within a group. Navigate to a group's **Issues** tab and query search results in
+the same way as you do for projects.
+
+![filter issues in a group](img/group_issues_filter.png)
+
## Search history
You can view recent searches by clicking on the little arrow-clock icon, which is to the left of the search input. Click the search entry to run that search again. This feature is available for issues and merge requests. Searches are stored locally in your browser.
diff --git a/features/steps/profile/emails.rb b/features/steps/profile/emails.rb
index 10ebe705365..4f44f932a6d 100644
--- a/features/steps/profile/emails.rb
+++ b/features/steps/profile/emails.rb
@@ -28,7 +28,7 @@ class Spinach::Features::ProfileEmails < Spinach::FeatureSteps
expect(email).to be_nil
expect(page).not_to have_content("my@email.com")
end
-
+
step 'I click link "Remove" for "my@email.com"' do
# there should only be one remove button at this time
click_link "Remove"
diff --git a/lib/api/api_guard.rb b/lib/api/api_guard.rb
index 0d2d71e336a..c4c0fdda665 100644
--- a/lib/api/api_guard.rb
+++ b/lib/api/api_guard.rb
@@ -122,7 +122,7 @@ module API
error_classes = [MissingTokenError, TokenNotFoundError,
ExpiredError, RevokedError, InsufficientScopeError]
- base.send :rescue_from, *error_classes, oauth2_bearer_token_error_handler
+ base.__send__(:rescue_from, *error_classes, oauth2_bearer_token_error_handler) # rubocop:disable GitlabSecurity/PublicSend
end
def oauth2_bearer_token_error_handler
diff --git a/lib/api/entities.rb b/lib/api/entities.rb
index 18cd604a216..e8dd61e493f 100644
--- a/lib/api/entities.rb
+++ b/lib/api/entities.rb
@@ -83,7 +83,7 @@ module API
expose :created_at, :last_activity_at
end
- class Project < BasicProjectDetails
+ class Project < BasicProjectDetails
include ::API::Helpers::RelatedResourcesHelpers
expose :_links do
@@ -541,8 +541,9 @@ module API
target_url = "namespace_project_#{target_type}_url"
target_anchor = "note_#{todo.note_id}" if todo.note_id?
- Gitlab::Routing.url_helpers.public_send(target_url,
- todo.project.namespace, todo.project, todo.target, anchor: target_anchor)
+ Gitlab::Routing
+ .url_helpers
+ .public_send(target_url, todo.project.namespace, todo.project, todo.target, anchor: target_anchor) # rubocop:disable GitlabSecurity/PublicSend
end
expose :body
diff --git a/lib/api/protected_branches.rb b/lib/api/protected_branches.rb
index d742f2e18d0..dccf4fa27a7 100644
--- a/lib/api/protected_branches.rb
+++ b/lib/api/protected_branches.rb
@@ -61,7 +61,7 @@ module API
service_args = [user_project, current_user, protected_branch_params]
protected_branch = ::ProtectedBranches::CreateService.new(*service_args).execute
-
+
if protected_branch.persisted?
present protected_branch, with: Entities::ProtectedBranch, project: user_project
else
diff --git a/lib/api/runners.rb b/lib/api/runners.rb
index 5bf5a18e42f..31f940fe96b 100644
--- a/lib/api/runners.rb
+++ b/lib/api/runners.rb
@@ -153,7 +153,7 @@ module API
render_api_error!('Scope contains invalid value', 400)
end
- runners.send(scope)
+ runners.public_send(scope) # rubocop:disable GitlabSecurity/PublicSend
end
def get_runner(id)
diff --git a/lib/api/v3/notes.rb b/lib/api/v3/notes.rb
index 23fe95e42e4..d49772b92f2 100644
--- a/lib/api/v3/notes.rb
+++ b/lib/api/v3/notes.rb
@@ -22,7 +22,7 @@ module API
use :pagination
end
get ":id/#{noteables_str}/:noteable_id/notes" do
- noteable = user_project.send(noteables_str.to_sym).find(params[:noteable_id])
+ noteable = user_project.public_send(noteables_str.to_sym).find(params[:noteable_id]) # rubocop:disable GitlabSecurity/PublicSend
if can?(current_user, noteable_read_ability_name(noteable), noteable)
# We exclude notes that are cross-references and that cannot be viewed
@@ -50,7 +50,7 @@ module API
requires :noteable_id, type: Integer, desc: 'The ID of the noteable'
end
get ":id/#{noteables_str}/:noteable_id/notes/:note_id" do
- noteable = user_project.send(noteables_str.to_sym).find(params[:noteable_id])
+ noteable = user_project.public_send(noteables_str.to_sym).find(params[:noteable_id]) # rubocop:disable GitlabSecurity/PublicSend
note = noteable.notes.find(params[:note_id])
can_read_note = can?(current_user, noteable_read_ability_name(noteable), noteable) && !note.cross_reference_not_visible_for?(current_user)
@@ -76,7 +76,7 @@ module API
noteable_id: params[:noteable_id]
}
- noteable = user_project.send(noteables_str.to_sym).find(params[:noteable_id])
+ noteable = user_project.public_send(noteables_str.to_sym).find(params[:noteable_id]) # rubocop:disable GitlabSecurity/PublicSend
if can?(current_user, noteable_read_ability_name(noteable), noteable)
if params[:created_at] && (current_user.admin? || user_project.owner == current_user)
diff --git a/lib/banzai/filter/external_issue_reference_filter.rb b/lib/banzai/filter/external_issue_reference_filter.rb
index 53a229256a5..ed01a72ff9f 100644
--- a/lib/banzai/filter/external_issue_reference_filter.rb
+++ b/lib/banzai/filter/external_issue_reference_filter.rb
@@ -95,10 +95,10 @@ module Banzai
private
def external_issues_cached(attribute)
- return project.public_send(attribute) unless RequestStore.active?
+ return project.public_send(attribute) unless RequestStore.active? # rubocop:disable GitlabSecurity/PublicSend
cached_attributes = RequestStore[:banzai_external_issues_tracker_attributes] ||= Hash.new { |h, k| h[k] = {} }
- cached_attributes[project.id][attribute] = project.public_send(attribute) if cached_attributes[project.id][attribute].nil?
+ cached_attributes[project.id][attribute] = project.public_send(attribute) if cached_attributes[project.id][attribute].nil? # rubocop:disable GitlabSecurity/PublicSend
cached_attributes[project.id][attribute]
end
end
diff --git a/lib/banzai/filter/image_lazy_load_filter.rb b/lib/banzai/filter/image_lazy_load_filter.rb
index 7a81d583b82..bcb4f332267 100644
--- a/lib/banzai/filter/image_lazy_load_filter.rb
+++ b/lib/banzai/filter/image_lazy_load_filter.rb
@@ -6,9 +6,9 @@ module Banzai
doc.xpath('descendant-or-self::img').each do |img|
img['class'] ||= '' << 'lazy'
img['data-src'] = img['src']
- img['src'] = LazyImageTagHelper.placeholder_image
+ img['src'] = LazyImageTagHelper.placeholder_image
end
-
+
doc
end
end
diff --git a/lib/banzai/object_renderer.rb b/lib/banzai/object_renderer.rb
index 002a3341ccd..2196a92474c 100644
--- a/lib/banzai/object_renderer.rb
+++ b/lib/banzai/object_renderer.rb
@@ -37,7 +37,7 @@ module Banzai
objects.each_with_index do |object, index|
redacted_data = redacted[index]
- object.__send__("redacted_#{attribute}_html=", redacted_data[:document].to_html.html_safe)
+ object.__send__("redacted_#{attribute}_html=", redacted_data[:document].to_html.html_safe) # rubocop:disable GitlabSecurity/PublicSend
object.user_visible_reference_count = redacted_data[:visible_reference_count]
end
end
diff --git a/lib/banzai/pipeline/base_pipeline.rb b/lib/banzai/pipeline/base_pipeline.rb
index 321fd5bbe14..3ae3bed570d 100644
--- a/lib/banzai/pipeline/base_pipeline.rb
+++ b/lib/banzai/pipeline/base_pipeline.rb
@@ -18,7 +18,7 @@ module Banzai
define_method(meth) do |text, context|
context = transform_context(context)
- html_pipeline.send(meth, text, context)
+ html_pipeline.__send__(meth, text, context) # rubocop:disable GitlabSecurity/PublicSend
end
end
end
diff --git a/lib/banzai/renderer.rb b/lib/banzai/renderer.rb
index ad08c0905e2..95d82d17658 100644
--- a/lib/banzai/renderer.rb
+++ b/lib/banzai/renderer.rb
@@ -43,7 +43,7 @@ module Banzai
# Same as +render_field+, but without consulting or updating the cache field
def self.cacheless_render_field(object, field, options = {})
- text = object.__send__(field)
+ text = object.__send__(field) # rubocop:disable GitlabSecurity/PublicSend
context = object.banzai_render_context(field).merge(options)
cacheless_render(text, context)
@@ -156,7 +156,7 @@ module Banzai
# method.
def self.full_cache_multi_key(cache_key, pipeline_name)
return unless cache_key
- Rails.cache.send(:expanded_key, full_cache_key(cache_key, pipeline_name))
+ Rails.cache.__send__(:expanded_key, full_cache_key(cache_key, pipeline_name)) # rubocop:disable GitlabSecurity/PublicSend
end
# GitLab EE needs to disable updates on GET requests in Geo
diff --git a/lib/bitbucket/collection.rb b/lib/bitbucket/collection.rb
index 3a9379ff680..a78495dbf5e 100644
--- a/lib/bitbucket/collection.rb
+++ b/lib/bitbucket/collection.rb
@@ -13,7 +13,7 @@ module Bitbucket
def method_missing(method, *args)
return super unless self.respond_to?(method)
- self.send(method, *args) do |item|
+ self.__send__(method, *args) do |item| # rubocop:disable GitlabSecurity/PublicSend
block_given? ? yield(item) : item
end
end
diff --git a/lib/ci/ansi2html.rb b/lib/ci/ansi2html.rb
index 8354fc8d595..b9e9f9f7f4a 100644
--- a/lib/ci/ansi2html.rb
+++ b/lib/ci/ansi2html.rb
@@ -208,7 +208,7 @@ module Ci
return unless command = stack.shift()
if self.respond_to?("on_#{command}", true)
- self.send("on_#{command}", stack)
+ self.__send__("on_#{command}", stack) # rubocop:disable GitlabSecurity/PublicSend
end
evaluate_command_stack(stack)
diff --git a/lib/constraints/project_url_constrainer.rb b/lib/constraints/project_url_constrainer.rb
index fd7b97d3167..5bef29eb1da 100644
--- a/lib/constraints/project_url_constrainer.rb
+++ b/lib/constraints/project_url_constrainer.rb
@@ -7,7 +7,7 @@ class ProjectUrlConstrainer
return false unless DynamicPathValidator.valid_project_path?(full_path)
# We intentionally allow SELECT(*) here so result of this query can be used
- # as cache for further Project.find_by_full_path calls within request
+ # as cache for further Project.find_by_full_path calls within request
Project.find_by_full_path(full_path, follow_redirects: request.get?).present?
end
end
diff --git a/lib/declarative_policy/base.rb b/lib/declarative_policy/base.rb
index df94cafb6a1..b028169f500 100644
--- a/lib/declarative_policy/base.rb
+++ b/lib/declarative_policy/base.rb
@@ -109,7 +109,7 @@ module DeclarativePolicy
name = name.to_sym
if delegation_block.nil?
- delegation_block = proc { @subject.__send__(name) }
+ delegation_block = proc { @subject.__send__(name) } # rubocop:disable GitlabSecurity/PublicSend
end
own_delegations[name] = delegation_block
@@ -221,7 +221,7 @@ module DeclarativePolicy
end
# computes the given ability and prints a helpful debugging output
- # showing which
+ # showing which
def debug(ability, *a)
runner(ability).debug(*a)
end
diff --git a/lib/declarative_policy/dsl.rb b/lib/declarative_policy/dsl.rb
index b26807a7622..6ba1e7a3c5c 100644
--- a/lib/declarative_policy/dsl.rb
+++ b/lib/declarative_policy/dsl.rb
@@ -93,7 +93,7 @@ module DeclarativePolicy
def method_missing(m, *a, &b)
return super unless @context_class.respond_to?(m)
- @context_class.__send__(m, *a, &b)
+ @context_class.__send__(m, *a, &b) # rubocop:disable GitlabSecurity/PublicSend
end
def respond_to_missing?(m)
diff --git a/lib/file_size_validator.rb b/lib/file_size_validator.rb
index eb19ab45ac3..de391de9059 100644
--- a/lib/file_size_validator.rb
+++ b/lib/file_size_validator.rb
@@ -44,13 +44,13 @@ class FileSizeValidator < ActiveModel::EachValidator
when Integer
check_value
when Symbol
- record.send(check_value)
+ record.public_send(check_value) # rubocop:disable GitlabSecurity/PublicSend
end
value ||= [] if key == :maximum
value_size = value.size
- next if value_size.send(validity_check, check_value)
+ next if value_size.public_send(validity_check, check_value) # rubocop:disable GitlabSecurity/PublicSend
errors_options = options.except(*RESERVED_OPTIONS)
errors_options[:file_size] = help.number_to_human_size check_value
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
index 7d3aa532750..8cb4060cd97 100644
--- a/lib/gitlab/auth.rb
+++ b/lib/gitlab/auth.rb
@@ -101,7 +101,7 @@ module Gitlab
if Service.available_services_names.include?(underscored_service)
# We treat underscored_service as a trusted input because it is included
# in the Service.available_services_names whitelist.
- service = project.public_send("#{underscored_service}_service")
+ service = project.public_send("#{underscored_service}_service") # rubocop:disable GitlabSecurity/PublicSend
if service && service.activated? && service.valid_token?(password)
Gitlab::Auth::Result.new(nil, project, :ci, build_authentication_abilities)
@@ -149,7 +149,7 @@ module Gitlab
def abilities_for_scope(scopes)
scopes.map do |scope|
- self.public_send(:"#{scope}_scope_authentication_abilities")
+ self.public_send(:"#{scope}_scope_authentication_abilities") # rubocop:disable GitlabSecurity/PublicSend
end.flatten.uniq
end
diff --git a/lib/gitlab/auth/ip_rate_limiter.rb b/lib/gitlab/auth/ip_rate_limiter.rb
index 1089bc9f89e..e6173d45af3 100644
--- a/lib/gitlab/auth/ip_rate_limiter.rb
+++ b/lib/gitlab/auth/ip_rate_limiter.rb
@@ -11,11 +11,11 @@ module Gitlab
def enabled?
config.enabled
end
-
+
def reset!
Rack::Attack::Allow2Ban.reset(ip, config)
end
-
+
def register_fail!
# Allow2Ban.filter will return false if this IP has not failed too often yet
@banned = Rack::Attack::Allow2Ban.filter(ip, config) do
@@ -23,17 +23,17 @@ module Gitlab
ip_can_be_banned?
end
end
-
+
def banned?
@banned
end
-
+
private
-
+
def config
Gitlab.config.rack_attack.git_basic_auth
end
-
+
def ip_can_be_banned?
config.ip_whitelist.exclude?(ip)
end
diff --git a/lib/gitlab/cache/request_cache.rb b/lib/gitlab/cache/request_cache.rb
index f1a04affd38..754a45c3257 100644
--- a/lib/gitlab/cache/request_cache.rb
+++ b/lib/gitlab/cache/request_cache.rb
@@ -69,7 +69,7 @@ module Gitlab
instance_variable_set(ivar_name, {})
end
- key = __send__(cache_key_method_name, args)
+ key = __send__(cache_key_method_name, args) # rubocop:disable GitlabSecurity/PublicSend
store.fetch(key) { store[key] = super(*args) }
end
diff --git a/lib/gitlab/ci/build/artifacts/metadata.rb b/lib/gitlab/ci/build/artifacts/metadata.rb
index a375ccbece0..a788fb3fcbc 100644
--- a/lib/gitlab/ci/build/artifacts/metadata.rb
+++ b/lib/gitlab/ci/build/artifacts/metadata.rb
@@ -60,7 +60,7 @@ module Gitlab
begin
path = read_string(gz).force_encoding('UTF-8')
meta = read_string(gz).force_encoding('UTF-8')
-
+
next unless path.valid_encoding? && meta.valid_encoding?
next unless path =~ match_pattern
next if path =~ INVALID_PATH_PATTERN
diff --git a/lib/gitlab/diff/line_mapper.rb b/lib/gitlab/diff/line_mapper.rb
index 576a761423e..cf71d47df8e 100644
--- a/lib/gitlab/diff/line_mapper.rb
+++ b/lib/gitlab/diff/line_mapper.rb
@@ -38,7 +38,7 @@ module Gitlab
# - The first diff line with a higher line number, if it falls between diff contexts
# - The last known diff line, if it falls after the last diff context
diff_line = diff_lines.find do |diff_line|
- diff_from_line = diff_line.send(from)
+ diff_from_line = diff_line.public_send(from) # rubocop:disable GitlabSecurity/PublicSend
diff_from_line && diff_from_line >= from_line
end
diff_line ||= diff_lines.last
@@ -47,8 +47,8 @@ module Gitlab
# mapped line number is the same as the specified line number.
return from_line unless diff_line
- diff_from_line = diff_line.send(from)
- diff_to_line = diff_line.send(to)
+ diff_from_line = diff_line.public_send(from) # rubocop:disable GitlabSecurity/PublicSend
+ diff_to_line = diff_line.public_send(to) # rubocop:disable GitlabSecurity/PublicSend
# If the line was removed, there is no mapped line number.
return unless diff_to_line
diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb
index 77b81d2d437..7780f4e4d4f 100644
--- a/lib/gitlab/git/blob.rb
+++ b/lib/gitlab/git/blob.rb
@@ -54,7 +54,7 @@ module Gitlab
# [[commit_sha, path], [commit_sha, path], ...]. If blob_size_limit < 0 then the
# full blob contents are returned. If blob_size_limit >= 0 then each blob will
# contain no more than limit bytes in its data attribute.
- #
+ #
# Keep in mind that this method may allocate a lot of memory. It is up
# to the caller to limit the number of blobs and blob_size_limit.
#
@@ -173,7 +173,7 @@ module Gitlab
def initialize(options)
%w(id name path size data mode commit_id binary).each do |key|
- self.send("#{key}=", options[key.to_sym])
+ self.__send__("#{key}=", options[key.to_sym]) # rubocop:disable GitlabSecurity/PublicSend
end
@loaded_all_data = false
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 38772d06dbd..1d5ca68137a 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -18,6 +18,28 @@ module Gitlab
InvalidBlobName = Class.new(StandardError)
InvalidRef = Class.new(StandardError)
+ class << self
+ # Unlike `new`, `create` takes the storage path, not the storage name
+ def create(storage_path, name, bare: true, symlink_hooks_to: nil)
+ repo_path = File.join(storage_path, name)
+ repo_path += '.git' unless repo_path.end_with?('.git')
+
+ FileUtils.mkdir_p(repo_path, mode: 0770)
+
+ # Equivalent to `git --git-path=#{repo_path} init [--bare]`
+ repo = Rugged::Repository.init_at(repo_path, bare)
+ repo.close
+
+ if symlink_hooks_to.present?
+ hooks_path = File.join(repo_path, 'hooks')
+ FileUtils.rm_rf(hooks_path)
+ FileUtils.ln_s(symlink_hooks_to, hooks_path)
+ end
+
+ true
+ end
+ end
+
# Full path to repo
attr_reader :path
diff --git a/lib/gitlab/git/tree.rb b/lib/gitlab/git/tree.rb
index 8e959c57c7c..b54962a4456 100644
--- a/lib/gitlab/git/tree.rb
+++ b/lib/gitlab/git/tree.rb
@@ -89,7 +89,7 @@ module Gitlab
def initialize(options)
%w(id root_id name path type mode commit_id).each do |key|
- self.send("#{key}=", options[key.to_sym])
+ self.send("#{key}=", options[key.to_sym]) # rubocop:disable GitlabSecurity/PublicSend
end
end
diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb
index 70177cd0fec..9a5f4f598b2 100644
--- a/lib/gitlab/gitaly_client.rb
+++ b/lib/gitlab/gitaly_client.rb
@@ -55,7 +55,7 @@ module Gitlab
def self.call(storage, service, rpc, request)
metadata = request_metadata(storage)
metadata = yield(metadata) if block_given?
- stub(service, storage).send(rpc, request, metadata)
+ stub(service, storage).__send__(rpc, request, metadata) # rubocop:disable GitlabSecurity/PublicSend
end
def self.request_metadata(storage)
diff --git a/lib/gitlab/github_import/base_formatter.rb b/lib/gitlab/github_import/base_formatter.rb
index 8c80791e7c9..f330041cc00 100644
--- a/lib/gitlab/github_import/base_formatter.rb
+++ b/lib/gitlab/github_import/base_formatter.rb
@@ -11,7 +11,9 @@ module Gitlab
end
def create!
- project.public_send(project_association).find_or_create_by!(find_condition) do |record|
+ association = project.public_send(project_association) # rubocop:disable GitlabSecurity/PublicSend
+
+ association.find_or_create_by!(find_condition) do |record|
record.attributes = attributes
end
end
diff --git a/lib/gitlab/github_import/client.rb b/lib/gitlab/github_import/client.rb
index 7dbeec5b010..0550f9695bd 100644
--- a/lib/gitlab/github_import/client.rb
+++ b/lib/gitlab/github_import/client.rb
@@ -120,7 +120,7 @@ module Gitlab
def request(method, *args, &block)
sleep rate_limit_sleep_time if rate_limit_exceed?
- data = api.send(method, *args)
+ data = api.__send__(method, *args) # rubocop:disable GitlabSecurity/PublicSend
return data unless data.is_a?(Array)
last_response = api.last_response
diff --git a/lib/gitlab/github_import/importer.rb b/lib/gitlab/github_import/importer.rb
index 266b1a6fece..373062b354b 100644
--- a/lib/gitlab/github_import/importer.rb
+++ b/lib/gitlab/github_import/importer.rb
@@ -289,7 +289,7 @@ module Gitlab
opts.last[:page] = current_page(resource_type)
- client.public_send(resource_type, *opts) do |resources|
+ client.public_send(resource_type, *opts) do |resources| # rubocop:disable GitlabSecurity/PublicSend
yield resources
increment_page(resource_type)
end
diff --git a/lib/gitlab/import_export/attributes_finder.rb b/lib/gitlab/import_export/attributes_finder.rb
index d230de781d5..56042ddecbf 100644
--- a/lib/gitlab/import_export/attributes_finder.rb
+++ b/lib/gitlab/import_export/attributes_finder.rb
@@ -1,7 +1,6 @@
module Gitlab
module ImportExport
class AttributesFinder
-
def initialize(included_attributes:, excluded_attributes:, methods:)
@included_attributes = included_attributes || {}
@excluded_attributes = excluded_attributes || {}
diff --git a/lib/gitlab/lazy.rb b/lib/gitlab/lazy.rb
index 2a659ae4c74..99594577141 100644
--- a/lib/gitlab/lazy.rb
+++ b/lib/gitlab/lazy.rb
@@ -16,7 +16,7 @@ module Gitlab
def method_missing(name, *args, &block)
__evaluate__
- @result.__send__(name, *args, &block)
+ @result.__send__(name, *args, &block) # rubocop:disable GitlabSecurity/PublicSend
end
def respond_to_missing?(name, include_private = false)
diff --git a/lib/gitlab/ldap/auth_hash.rb b/lib/gitlab/ldap/auth_hash.rb
index 95378e5a769..4fbc5fa5262 100644
--- a/lib/gitlab/ldap/auth_hash.rb
+++ b/lib/gitlab/ldap/auth_hash.rb
@@ -17,7 +17,7 @@ module Gitlab
value = value.first if value
break if value.present?
end
-
+
return super unless value
Gitlab::Utils.force_utf8(value)
diff --git a/lib/gitlab/ldap/person.rb b/lib/gitlab/ldap/person.rb
index 43eb73250b7..e138b466a34 100644
--- a/lib/gitlab/ldap/person.rb
+++ b/lib/gitlab/ldap/person.rb
@@ -32,7 +32,7 @@ module Gitlab
end
def uid
- entry.send(config.uid).first
+ entry.public_send(config.uid).first # rubocop:disable GitlabSecurity/PublicSend
end
def username
@@ -65,7 +65,7 @@ module Gitlab
return nil unless selected_attr
- entry.public_send(selected_attr)
+ entry.public_send(selected_attr) # rubocop:disable GitlabSecurity/PublicSend
end
end
end
diff --git a/lib/gitlab/markdown/pipeline.rb b/lib/gitlab/markdown/pipeline.rb
index 699d8b9fc07..306923902e0 100644
--- a/lib/gitlab/markdown/pipeline.rb
+++ b/lib/gitlab/markdown/pipeline.rb
@@ -23,7 +23,7 @@ module Gitlab
define_method(meth) do |text, context|
context = transform_context(context)
- html_pipeline.send(meth, text, context)
+ html_pipeline.__send__(meth, text, context) # rubocop:disable GitlabSecurity/PublicSend
end
end
end
diff --git a/lib/gitlab/middleware/rails_queue_duration.rb b/lib/gitlab/middleware/rails_queue_duration.rb
index 5d2d7d0026c..63c3372da51 100644
--- a/lib/gitlab/middleware/rails_queue_duration.rb
+++ b/lib/gitlab/middleware/rails_queue_duration.rb
@@ -8,7 +8,7 @@ module Gitlab
def initialize(app)
@app = app
end
-
+
def call(env)
trans = Gitlab::Metrics.current_transaction
proxy_start = env['HTTP_GITLAB_WORKHORSE_PROXY_START'].presence
diff --git a/lib/gitlab/redis/cache.rb b/lib/gitlab/redis/cache.rb
index b0da516ff83..9bf019b72e6 100644
--- a/lib/gitlab/redis/cache.rb
+++ b/lib/gitlab/redis/cache.rb
@@ -7,9 +7,6 @@ module Gitlab
CACHE_NAMESPACE = 'cache:gitlab'.freeze
DEFAULT_REDIS_CACHE_URL = 'redis://localhost:6380'.freeze
REDIS_CACHE_CONFIG_ENV_VAR_NAME = 'GITLAB_REDIS_CACHE_CONFIG_FILE'.freeze
- if defined?(::Rails) && ::Rails.root.present?
- DEFAULT_REDIS_CACHE_CONFIG_FILE_NAME = ::Rails.root.join('config', 'redis.cache.yml').freeze
- end
class << self
def default_url
@@ -22,7 +19,7 @@ module Gitlab
return file_name unless file_name.nil?
# otherwise, if config files exists for this class, use it
- file_name = File.expand_path(DEFAULT_REDIS_CACHE_CONFIG_FILE_NAME, __dir__)
+ file_name = config_file_path('redis.cache.yml')
return file_name if File.file?(file_name)
# this will force use of DEFAULT_REDIS_QUEUES_URL when config file is absent
diff --git a/lib/gitlab/redis/queues.rb b/lib/gitlab/redis/queues.rb
index f9249d05565..e1695aafbeb 100644
--- a/lib/gitlab/redis/queues.rb
+++ b/lib/gitlab/redis/queues.rb
@@ -8,9 +8,6 @@ module Gitlab
MAILROOM_NAMESPACE = 'mail_room:gitlab'.freeze
DEFAULT_REDIS_QUEUES_URL = 'redis://localhost:6381'.freeze
REDIS_QUEUES_CONFIG_ENV_VAR_NAME = 'GITLAB_REDIS_QUEUES_CONFIG_FILE'.freeze
- if defined?(::Rails) && ::Rails.root.present?
- DEFAULT_REDIS_QUEUES_CONFIG_FILE_NAME = ::Rails.root.join('config', 'redis.queues.yml').freeze
- end
class << self
def default_url
@@ -23,7 +20,7 @@ module Gitlab
return file_name if file_name
# otherwise, if config files exists for this class, use it
- file_name = File.expand_path(DEFAULT_REDIS_QUEUES_CONFIG_FILE_NAME, __dir__)
+ file_name = config_file_path('redis.queues.yml')
return file_name if File.file?(file_name)
# this will force use of DEFAULT_REDIS_QUEUES_URL when config file is absent
diff --git a/lib/gitlab/redis/shared_state.rb b/lib/gitlab/redis/shared_state.rb
index 395dcf082da..10bec7a90da 100644
--- a/lib/gitlab/redis/shared_state.rb
+++ b/lib/gitlab/redis/shared_state.rb
@@ -7,9 +7,6 @@ module Gitlab
SESSION_NAMESPACE = 'session:gitlab'.freeze
DEFAULT_REDIS_SHARED_STATE_URL = 'redis://localhost:6382'.freeze
REDIS_SHARED_STATE_CONFIG_ENV_VAR_NAME = 'GITLAB_REDIS_SHARED_STATE_CONFIG_FILE'.freeze
- if defined?(::Rails) && ::Rails.root.present?
- DEFAULT_REDIS_SHARED_STATE_CONFIG_FILE_NAME = ::Rails.root.join('config', 'redis.shared_state.yml').freeze
- end
class << self
def default_url
@@ -22,7 +19,7 @@ module Gitlab
return file_name if file_name
# otherwise, if config files exists for this class, use it
- file_name = File.expand_path(DEFAULT_REDIS_SHARED_STATE_CONFIG_FILE_NAME, __dir__)
+ file_name = config_file_path('redis.shared_state.yml')
return file_name if File.file?(file_name)
# this will force use of DEFAULT_REDIS_SHARED_STATE_URL when config file is absent
diff --git a/lib/gitlab/redis/wrapper.rb b/lib/gitlab/redis/wrapper.rb
index c43b37dde74..8ad06480575 100644
--- a/lib/gitlab/redis/wrapper.rb
+++ b/lib/gitlab/redis/wrapper.rb
@@ -8,9 +8,6 @@ module Gitlab
class Wrapper
DEFAULT_REDIS_URL = 'redis://localhost:6379'.freeze
REDIS_CONFIG_ENV_VAR_NAME = 'GITLAB_REDIS_CONFIG_FILE'.freeze
- if defined?(::Rails) && ::Rails.root.present?
- DEFAULT_REDIS_CONFIG_FILE_NAME = ::Rails.root.join('config', 'resque.yml').freeze
- end
class << self
delegate :params, :url, to: :new
@@ -49,13 +46,21 @@ module Gitlab
DEFAULT_REDIS_URL
end
+ # Return the absolute path to a Rails configuration file
+ #
+ # We use this instead of `Rails.root` because for certain tasks
+ # utilizing these classes, `Rails` might not be available.
+ def config_file_path(filename)
+ File.expand_path("../../../config/#{filename}", __dir__)
+ end
+
def config_file_name
# if ENV set for wrapper class, use it even if it points to a file does not exist
file_name = ENV[REDIS_CONFIG_ENV_VAR_NAME]
return file_name unless file_name.nil?
# otherwise, if config files exists for wrapper class, use it
- file_name = File.expand_path(DEFAULT_REDIS_CONFIG_FILE_NAME, __dir__)
+ file_name = config_file_path('resque.yml')
return file_name if File.file?(file_name)
# nil will force use of DEFAULT_REDIS_URL when config file is absent
diff --git a/lib/gitlab/shell.rb b/lib/gitlab/shell.rb
index 0cb28732402..280a9abf03e 100644
--- a/lib/gitlab/shell.rb
+++ b/lib/gitlab/shell.rb
@@ -73,8 +73,10 @@ module Gitlab
#
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/387
def add_repository(storage, name)
- gitlab_shell_fast_execute([gitlab_shell_projects_path,
- 'add-project', storage, "#{name}.git"])
+ Gitlab::Git::Repository.create(storage, name, bare: true, symlink_hooks_to: gitlab_shell_hooks_path)
+ rescue => err
+ Rails.logger.error("Failed to add repository #{storage}/#{name}: #{err}")
+ false
end
# Import repository
@@ -273,7 +275,11 @@ module Gitlab
protected
def gitlab_shell_path
- Gitlab.config.gitlab_shell.path
+ File.expand_path(Gitlab.config.gitlab_shell.path)
+ end
+
+ def gitlab_shell_hooks_path
+ File.expand_path(Gitlab.config.gitlab_shell.hooks_path)
end
def gitlab_shell_user_home
diff --git a/lib/gitlab/slash_commands/presenters/help.rb b/lib/gitlab/slash_commands/presenters/help.rb
index ea611a4d629..ab855319077 100644
--- a/lib/gitlab/slash_commands/presenters/help.rb
+++ b/lib/gitlab/slash_commands/presenters/help.rb
@@ -14,7 +14,7 @@ module Gitlab
if text.start_with?('help')
header_with_list("Available commands", full_commands(trigger))
else
- header_with_list("Unknown command, these commands are available", full_commands(trigger))
+ header_with_list("Unknown command, these commands are available", full_commands(trigger))
end
end
diff --git a/lib/gitlab/utils.rb b/lib/gitlab/utils.rb
index fa182c4deda..9670c93759e 100644
--- a/lib/gitlab/utils.rb
+++ b/lib/gitlab/utils.rb
@@ -14,6 +14,19 @@ module Gitlab
str.force_encoding(Encoding::UTF_8)
end
+ # A slugified version of the string, suitable for inclusion in URLs and
+ # domain names. Rules:
+ #
+ # * Lowercased
+ # * Anything not matching [a-z0-9-] is replaced with a -
+ # * Maximum length is 63 bytes
+ # * First/Last Character is not a hyphen
+ def slugify(str)
+ return str.downcase
+ .gsub(/[^a-z0-9]/, '-')[0..62]
+ .gsub(/(\A-+|-+\z)/, '')
+ end
+
def to_boolean(value)
return value if [true, false].include?(value)
return true if value =~ /^(true|t|yes|y|1|on)$/i
diff --git a/lib/tasks/gitlab/gitaly.rake b/lib/tasks/gitlab/gitaly.rake
index e337c67a0f5..08677a98fc1 100644
--- a/lib/tasks/gitlab/gitaly.rake
+++ b/lib/tasks/gitlab/gitaly.rake
@@ -18,7 +18,7 @@ namespace :gitlab do
command = status.zero? ? ['gmake'] : ['make']
if Rails.env.test?
- command += %W[BUNDLE_PATH=#{Bundler.bundle_path}]
+ command += %W[BUNDLE_PATH=#{Bundler.bundle_path}]
end
Dir.chdir(args.dir) do
diff --git a/lib/uploaded_file.rb b/lib/uploaded_file.rb
index 41dee5fdc06..4a3c40f88eb 100644
--- a/lib/uploaded_file.rb
+++ b/lib/uploaded_file.rb
@@ -27,7 +27,7 @@ class UploadedFile
alias_method :local_path, :path
def method_missing(method_name, *args, &block) #:nodoc:
- @tempfile.__send__(method_name, *args, &block)
+ @tempfile.__send__(method_name, *args, &block) # rubocop:disable GitlabSecurity/PublicSend
end
def respond_to?(method_name, include_private = false) #:nodoc:
diff --git a/qa/qa/runtime/release.rb b/qa/qa/runtime/release.rb
index 4f83a773645..12e56404cf6 100644
--- a/qa/qa/runtime/release.rb
+++ b/qa/qa/runtime/release.rb
@@ -21,7 +21,7 @@ module QA
end
def self.method_missing(name, *args)
- self.new.strategy.public_send(name, *args)
+ self.new.strategy.public_send(name, *args) # rubocop:disable GitlabSecurity/PublicSend
end
end
end
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index 5db42175c15..dbb0ae9c86e 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -74,7 +74,7 @@ feature 'Admin updates settings' do
context 'sign-in restrictions', :js do
it 'de-activates oauth sign-in source' do
find('.btn', text: 'GitLab.com').click
-
+
expect(find('.btn', text: 'GitLab.com')).not_to have_css('.active')
end
end
diff --git a/spec/features/groups/milestone_spec.rb b/spec/features/groups/milestone_spec.rb
index 32b3e13c624..56144d17d4f 100644
--- a/spec/features/groups/milestone_spec.rb
+++ b/spec/features/groups/milestone_spec.rb
@@ -35,12 +35,12 @@ feature 'Group milestones', :js do
context 'milestones list' do
let!(:other_project) { create(:project_empty_repo, group: group) }
- let!(:active_group_milestone) { create(:milestone, group: group, state: 'active') }
let!(:active_project_milestone1) { create(:milestone, project: project, state: 'active', title: 'v1.0') }
let!(:active_project_milestone2) { create(:milestone, project: other_project, state: 'active', title: 'v1.0') }
- let!(:closed_group_milestone) { create(:milestone, group: group, state: 'closed') }
let!(:closed_project_milestone1) { create(:milestone, project: project, state: 'closed', title: 'v2.0') }
let!(:closed_project_milestone2) { create(:milestone, project: other_project, state: 'closed', title: 'v2.0') }
+ let!(:active_group_milestone) { create(:milestone, group: group, state: 'active') }
+ let!(:closed_group_milestone) { create(:milestone, group: group, state: 'closed') }
before do
visit group_milestones_path(group)
@@ -58,5 +58,30 @@ feature 'Group milestones', :js do
expect(page).to have_selector("#milestone_#{active_group_milestone.id}", count: 1)
expect(page).to have_selector("#milestone_#{legacy_milestone.milestones.first.id}", count: 1)
end
+
+ it 'updates milestone' do
+ page.within(".milestones #milestone_#{active_group_milestone.id}") do
+ click_link('Edit')
+ end
+
+ page.within('.milestone-form') do
+ fill_in 'milestone_title', with: 'new title'
+ click_button('Update milestone')
+ end
+
+ expect(find('#content-body h2')).to have_content('new title')
+ end
+
+ it 'shows milestone detail and supports its edit' do
+ page.within(".milestones #milestone_#{active_group_milestone.id}") do
+ click_link(active_group_milestone.title)
+ end
+
+ page.within('.detail-page-header') do
+ click_link('Edit')
+ end
+
+ expect(page).to have_selector('.milestone-form')
+ end
end
end
diff --git a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
index a69bd8a09b7..2cc027aac9e 100644
--- a/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_assignee_spec.rb
@@ -134,8 +134,10 @@ describe 'Dropdown assignee', :js do
it 'fills in the assignee username when the assignee has not been filtered' do
click_assignee(user_jacob.name)
+ wait_for_requests
+
expect(page).to have_css(js_dropdown_assignee, visible: false)
- expect_tokens([{ name: 'assignee', value: "@#{user_jacob.username}" }])
+ expect_tokens([assignee_token(user_jacob.name)])
expect_filtered_search_input_empty
end
@@ -143,8 +145,10 @@ describe 'Dropdown assignee', :js do
filtered_search.send_keys('roo')
click_assignee(user.name)
+ wait_for_requests
+
expect(page).to have_css(js_dropdown_assignee, visible: false)
- expect_tokens([{ name: 'assignee', value: "@#{user.username}" }])
+ expect_tokens([assignee_token(user.name)])
expect_filtered_search_input_empty
end
@@ -152,7 +156,7 @@ describe 'Dropdown assignee', :js do
find('#js-dropdown-assignee .filter-dropdown-item', text: 'No Assignee').click
expect(page).to have_css(js_dropdown_assignee, visible: false)
- expect_tokens([{ name: 'assignee', value: 'none' }])
+ expect_tokens([assignee_token('none')])
expect_filtered_search_input_empty
end
end
@@ -171,7 +175,7 @@ describe 'Dropdown assignee', :js do
find('#js-dropdown-assignee .filter-dropdown-item', text: user.username).click
expect(page).to have_css(js_dropdown_assignee, visible: false)
- expect_tokens([{ name: 'assignee', value: user.username }])
+ expect_tokens([assignee_token(user.username)])
expect_filtered_search_input_empty
end
end
diff --git a/spec/features/issues/filtered_search/dropdown_author_spec.rb b/spec/features/issues/filtered_search/dropdown_author_spec.rb
index 4bbf18e1dbe..975dc035f2d 100644
--- a/spec/features/issues/filtered_search/dropdown_author_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_author_spec.rb
@@ -121,16 +121,20 @@ describe 'Dropdown author', js: true do
it 'fills in the author username when the author has not been filtered' do
click_author(user_jacob.name)
+ wait_for_requests
+
expect(page).to have_css(js_dropdown_author, visible: false)
- expect_tokens([{ name: 'author', value: "@#{user_jacob.username}" }])
+ expect_tokens([author_token(user_jacob.name)])
expect_filtered_search_input_empty
end
it 'fills in the author username when the author has been filtered' do
click_author(user.name)
+ wait_for_requests
+
expect(page).to have_css(js_dropdown_author, visible: false)
- expect_tokens([{ name: 'author', value: "@#{user.username}" }])
+ expect_tokens([author_token(user.name)])
expect_filtered_search_input_empty
end
end
@@ -149,7 +153,7 @@ describe 'Dropdown author', js: true do
find('#js-dropdown-author .filter-dropdown-item', text: user.username).click
expect(page).to have_css(js_dropdown_author, visible: false)
- expect_tokens([{ name: 'author', value: user.username }])
+ expect_tokens([author_token(user.username)])
expect_filtered_search_input_empty
end
end
diff --git a/spec/features/issues/filtered_search/dropdown_label_spec.rb b/spec/features/issues/filtered_search/dropdown_label_spec.rb
index 67eb0ef0119..e84b07ec2ef 100644
--- a/spec/features/issues/filtered_search/dropdown_label_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_label_spec.rb
@@ -47,7 +47,7 @@ describe 'Dropdown label', js: true do
filtered_search.native.send_keys(:down, :down, :enter)
- expect_tokens([{ name: 'label', value: "~#{bug_label.title}" }])
+ expect_tokens([label_token(bug_label.title)])
expect_filtered_search_input_empty
end
end
@@ -178,7 +178,7 @@ describe 'Dropdown label', js: true do
click_label(bug_label.title)
expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([{ name: 'label', value: "~#{bug_label.title}" }])
+ expect_tokens([label_token(bug_label.title)])
expect_filtered_search_input_empty
end
@@ -187,7 +187,7 @@ describe 'Dropdown label', js: true do
click_label(bug_label.title)
expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([{ name: 'label', value: "~#{bug_label.title}" }])
+ expect_tokens([label_token(bug_label.title)])
expect_filtered_search_input_empty
end
@@ -195,7 +195,7 @@ describe 'Dropdown label', js: true do
click_label(two_words_label.title)
expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([{ name: 'label', value: "\"#{two_words_label.title}\"" }])
+ expect_tokens([label_token("\"#{two_words_label.title}\"")])
expect_filtered_search_input_empty
end
@@ -203,7 +203,7 @@ describe 'Dropdown label', js: true do
click_label(long_label.title)
expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([{ name: 'label', value: "\"#{long_label.title}\"" }])
+ expect_tokens([label_token("\"#{long_label.title}\"")])
expect_filtered_search_input_empty
end
@@ -211,7 +211,7 @@ describe 'Dropdown label', js: true do
click_label(wont_fix_label.title)
expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([{ name: 'label', value: "~'#{wont_fix_label.title}'" }])
+ expect_tokens([label_token("'#{wont_fix_label.title}'")])
expect_filtered_search_input_empty
end
@@ -219,7 +219,7 @@ describe 'Dropdown label', js: true do
click_label(uppercase_label.title)
expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([{ name: 'label', value: "~#{uppercase_label.title}" }])
+ expect_tokens([label_token(uppercase_label.title)])
expect_filtered_search_input_empty
end
@@ -227,7 +227,7 @@ describe 'Dropdown label', js: true do
click_label(special_label.title)
expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([{ name: 'label', value: "~#{special_label.title}" }])
+ expect_tokens([label_token(special_label.title)])
expect_filtered_search_input_empty
end
@@ -235,7 +235,7 @@ describe 'Dropdown label', js: true do
find("#{js_dropdown_label} .filter-dropdown-item", text: 'No Label').click
expect(page).not_to have_css(js_dropdown_label)
- expect_tokens([{ name: 'label', value: 'none' }])
+ expect_tokens([label_token('none', false)])
expect_filtered_search_input_empty
end
end
diff --git a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
index 456eb05f241..5f99921ae2e 100644
--- a/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
+++ b/spec/features/issues/filtered_search/dropdown_milestone_spec.rb
@@ -134,7 +134,7 @@ describe 'Dropdown milestone', :js do
click_milestone(milestone.title)
expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([{ name: 'milestone', value: "%#{milestone.title}" }])
+ expect_tokens([milestone_token(milestone.title)])
expect_filtered_search_input_empty
end
@@ -143,7 +143,7 @@ describe 'Dropdown milestone', :js do
click_milestone(milestone.title)
expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([{ name: 'milestone', value: "%#{milestone.title}" }])
+ expect_tokens([milestone_token(milestone.title)])
expect_filtered_search_input_empty
end
@@ -151,7 +151,7 @@ describe 'Dropdown milestone', :js do
click_milestone(two_words_milestone.title)
expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([{ name: 'milestone', value: "%\"#{two_words_milestone.title}\"" }])
+ expect_tokens([milestone_token("\"#{two_words_milestone.title}\"")])
expect_filtered_search_input_empty
end
@@ -159,7 +159,7 @@ describe 'Dropdown milestone', :js do
click_milestone(long_milestone.title)
expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([{ name: 'milestone', value: "%\"#{long_milestone.title}\"" }])
+ expect_tokens([milestone_token("\"#{long_milestone.title}\"")])
expect_filtered_search_input_empty
end
@@ -167,7 +167,7 @@ describe 'Dropdown milestone', :js do
click_milestone(wont_fix_milestone.title)
expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([{ name: 'milestone', value: "%'#{wont_fix_milestone.title}'" }])
+ expect_tokens([milestone_token("'#{wont_fix_milestone.title}'")])
expect_filtered_search_input_empty
end
@@ -175,7 +175,7 @@ describe 'Dropdown milestone', :js do
click_milestone(uppercase_milestone.title)
expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([{ name: 'milestone', value: "%#{uppercase_milestone.title}" }])
+ expect_tokens([milestone_token(uppercase_milestone.title)])
expect_filtered_search_input_empty
end
@@ -183,7 +183,7 @@ describe 'Dropdown milestone', :js do
click_milestone(special_milestone.title)
expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([{ name: 'milestone', value: "%#{special_milestone.title}" }])
+ expect_tokens([milestone_token(special_milestone.title)])
expect_filtered_search_input_empty
end
@@ -191,7 +191,7 @@ describe 'Dropdown milestone', :js do
click_static_milestone('No Milestone')
expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([{ name: 'milestone', value: 'none' }])
+ expect_tokens([milestone_token('none', false)])
expect_filtered_search_input_empty
end
@@ -199,7 +199,7 @@ describe 'Dropdown milestone', :js do
click_static_milestone('Upcoming')
expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([{ name: 'milestone', value: 'upcoming' }])
+ expect_tokens([milestone_token('upcoming', false)])
expect_filtered_search_input_empty
end
@@ -207,7 +207,7 @@ describe 'Dropdown milestone', :js do
click_static_milestone('Started')
expect(page).to have_css(js_dropdown_milestone, visible: false)
- expect_tokens([{ name: 'milestone', value: 'started' }])
+ expect_tokens([milestone_token('started', false)])
expect_filtered_search_input_empty
end
end
diff --git a/spec/features/issues/filtered_search/filter_issues_spec.rb b/spec/features/issues/filtered_search/filter_issues_spec.rb
index cd2cbf4bfe7..2070043d842 100644
--- a/spec/features/issues/filtered_search/filter_issues_spec.rb
+++ b/spec/features/issues/filtered_search/filter_issues_spec.rb
@@ -97,7 +97,9 @@ describe 'Filter issues', js: true do
it 'filters issues by searched author' do
input_filtered_search("author:@#{user.username}")
- expect_tokens([{ name: 'author', value: user.username }])
+ wait_for_requests
+
+ expect_tokens([author_token(user.name)])
expect_issues_list_count(5)
expect_filtered_search_input_empty
end
@@ -117,7 +119,9 @@ describe 'Filter issues', js: true do
it 'filters issues by searched author and text' do
input_filtered_search("author:@#{user.username} #{search_term}")
- expect_tokens([{ name: 'author', value: user.username }])
+ wait_for_requests
+
+ expect_tokens([author_token(user.name)])
expect_issues_list_count(3)
expect_filtered_search_input(search_term)
end
@@ -125,10 +129,9 @@ describe 'Filter issues', js: true do
it 'filters issues by searched author, assignee and text' do
input_filtered_search("author:@#{user.username} assignee:@#{user.username} #{search_term}")
- expect_tokens([
- { name: 'author', value: user.username },
- { name: 'assignee', value: user.username }
- ])
+ wait_for_requests
+
+ expect_tokens([author_token(user.name), assignee_token(user.name)])
expect_issues_list_count(3)
expect_filtered_search_input(search_term)
end
@@ -136,10 +139,12 @@ describe 'Filter issues', js: true do
it 'filters issues by searched author, assignee, label, and text' do
input_filtered_search("author:@#{user.username} assignee:@#{user.username} label:~#{caps_sensitive_label.title} #{search_term}")
+ wait_for_requests
+
expect_tokens([
- { name: 'author', value: user.username },
- { name: 'assignee', value: user.username },
- { name: 'label', value: caps_sensitive_label.title }
+ author_token(user.name),
+ assignee_token(user.name),
+ label_token(caps_sensitive_label.title)
])
expect_issues_list_count(1)
expect_filtered_search_input(search_term)
@@ -148,11 +153,13 @@ describe 'Filter issues', js: true do
it 'filters issues by searched author, assignee, label, milestone and text' do
input_filtered_search("author:@#{user.username} assignee:@#{user.username} label:~#{caps_sensitive_label.title} milestone:%#{milestone.title} #{search_term}")
+ wait_for_requests
+
expect_tokens([
- { name: 'author', value: user.username },
- { name: 'assignee', value: user.username },
- { name: 'label', value: caps_sensitive_label.title },
- { name: 'milestone', value: milestone.title }
+ author_token(user.name),
+ assignee_token(user.name),
+ label_token(caps_sensitive_label.title),
+ milestone_token(milestone.title)
])
expect_issues_list_count(1)
expect_filtered_search_input(search_term)
@@ -169,7 +176,9 @@ describe 'Filter issues', js: true do
it 'filters issues by searched assignee' do
input_filtered_search("assignee:@#{user.username}")
- expect_tokens([{ name: 'assignee', value: user.username }])
+ wait_for_requests
+
+ expect_tokens([assignee_token(user.name)])
expect_issues_list_count(5)
expect_filtered_search_input_empty
end
@@ -177,7 +186,7 @@ describe 'Filter issues', js: true do
it 'filters issues by no assignee' do
input_filtered_search('assignee:none')
- expect_tokens([{ name: 'assignee', value: 'none' }])
+ expect_tokens([assignee_token('none')])
expect_issues_list_count(8, 1)
expect_filtered_search_input_empty
end
@@ -197,7 +206,9 @@ describe 'Filter issues', js: true do
it 'filters issues by searched assignee and text' do
input_filtered_search("assignee:@#{user.username} #{search_term}")
- expect_tokens([{ name: 'assignee', value: user.username }])
+ wait_for_requests
+
+ expect_tokens([assignee_token(user.name)])
expect_issues_list_count(2)
expect_filtered_search_input(search_term)
end
@@ -205,10 +216,9 @@ describe 'Filter issues', js: true do
it 'filters issues by searched assignee, author and text' do
input_filtered_search("assignee:@#{user.username} author:@#{user.username} #{search_term}")
- expect_tokens([
- { name: 'assignee', value: user.username },
- { name: 'author', value: user.username }
- ])
+ wait_for_requests
+
+ expect_tokens([assignee_token(user.name), author_token(user.name)])
expect_issues_list_count(2)
expect_filtered_search_input(search_term)
end
@@ -216,10 +226,12 @@ describe 'Filter issues', js: true do
it 'filters issues by searched assignee, author, label, text' do
input_filtered_search("assignee:@#{user.username} author:@#{user.username} label:~#{caps_sensitive_label.title} #{search_term}")
+ wait_for_requests
+
expect_tokens([
- { name: 'assignee', value: user.username },
- { name: 'author', value: user.username },
- { name: 'label', value: caps_sensitive_label.title }
+ assignee_token(user.name),
+ author_token(user.name),
+ label_token(caps_sensitive_label.title)
])
expect_issues_list_count(1)
expect_filtered_search_input(search_term)
@@ -229,10 +241,10 @@ describe 'Filter issues', js: true do
input_filtered_search("assignee:@#{user.username} author:@#{user.username} label:~#{caps_sensitive_label.title} milestone:%#{milestone.title} #{search_term}")
expect_tokens([
- { name: 'assignee', value: user.username },
- { name: 'author', value: user.username },
- { name: 'label', value: caps_sensitive_label.title },
- { name: 'milestone', value: milestone.title }
+ assignee_token(user.name),
+ author_token(user.name),
+ label_token(caps_sensitive_label.title),
+ milestone_token(milestone.title)
])
expect_issues_list_count(1)
expect_filtered_search_input(search_term)
@@ -253,7 +265,7 @@ describe 'Filter issues', js: true do
it 'filters issues by searched label' do
input_filtered_search("label:~#{bug_label.title}")
- expect_tokens([{ name: 'label', value: bug_label.title }])
+ expect_tokens([label_token(bug_label.title)])
expect_issues_list_count(2)
expect_filtered_search_input_empty
end
@@ -261,7 +273,7 @@ describe 'Filter issues', js: true do
it 'filters issues by no label' do
input_filtered_search('label:none')
- expect_tokens([{ name: 'label', value: 'none' }])
+ expect_tokens([label_token('none', false)])
expect_issues_list_count(9, 1)
expect_filtered_search_input_empty
end
@@ -274,8 +286,8 @@ describe 'Filter issues', js: true do
input_filtered_search("label:~#{bug_label.title} label:~#{caps_sensitive_label.title}")
expect_tokens([
- { name: 'label', value: bug_label.title },
- { name: 'label', value: caps_sensitive_label.title }
+ label_token(bug_label.title),
+ label_token(caps_sensitive_label.title)
])
expect_issues_list_count(1)
expect_filtered_search_input_empty
@@ -287,7 +299,8 @@ describe 'Filter issues', js: true do
special_issue.labels << special_label
input_filtered_search("label:~#{special_label.title}")
- expect_tokens([{ name: 'label', value: special_label.title }])
+
+ expect_tokens([label_token(special_label.title)])
expect_issues_list_count(1)
expect_filtered_search_input_empty
end
@@ -297,7 +310,7 @@ describe 'Filter issues', js: true do
input_filtered_search("label:~#{new_label.title}")
- expect_tokens([{ name: 'label', value: new_label.title }])
+ expect_tokens([label_token(new_label.title)])
expect_no_issues_list()
expect_filtered_search_input_empty
end
@@ -311,25 +324,27 @@ describe 'Filter issues', js: true do
input_filtered_search("label:~'#{special_multiple_label.title}'")
- # filtered search defaults quotations to double quotes
- expect_tokens([{ name: 'label', value: "\"#{special_multiple_label.title}\"" }])
+ # Check for search results (which makes sure that the page has changed)
expect_issues_list_count(1)
+ # filtered search defaults quotations to double quotes
+ expect_tokens([label_token("\"#{special_multiple_label.title}\"")])
+
expect_filtered_search_input_empty
end
it 'single quotes' do
input_filtered_search("label:~'#{multiple_words_label.title}'")
- expect_tokens([{ name: 'label', value: "\"#{multiple_words_label.title}\"" }])
expect_issues_list_count(1)
+ expect_tokens([label_token("\"#{multiple_words_label.title}\"")])
expect_filtered_search_input_empty
end
it 'double quotes' do
input_filtered_search("label:~\"#{multiple_words_label.title}\"")
- expect_tokens([{ name: 'label', value: "\"#{multiple_words_label.title}\"" }])
+ expect_tokens([label_token("\"#{multiple_words_label.title}\"")])
expect_issues_list_count(1)
expect_filtered_search_input_empty
end
@@ -341,7 +356,7 @@ describe 'Filter issues', js: true do
input_filtered_search("label:~'#{double_quotes_label.title}'")
- expect_tokens([{ name: 'label', value: "'#{double_quotes_label.title}'" }])
+ expect_tokens([label_token("'#{double_quotes_label.title}'")])
expect_issues_list_count(1)
expect_filtered_search_input_empty
end
@@ -353,7 +368,7 @@ describe 'Filter issues', js: true do
input_filtered_search("label:~\"#{single_quotes_label.title}\"")
- expect_tokens([{ name: 'label', value: "\"#{single_quotes_label.title}\"" }])
+ expect_tokens([label_token("\"#{single_quotes_label.title}\"")])
expect_issues_list_count(1)
expect_filtered_search_input_empty
end
@@ -363,7 +378,7 @@ describe 'Filter issues', js: true do
it 'filters issues by searched label and text' do
input_filtered_search("label:~#{caps_sensitive_label.title} #{search_term}")
- expect_tokens([{ name: 'label', value: caps_sensitive_label.title }])
+ expect_tokens([label_token(caps_sensitive_label.title)])
expect_issues_list_count(1)
expect_filtered_search_input(search_term)
end
@@ -371,10 +386,9 @@ describe 'Filter issues', js: true do
it 'filters issues by searched label, author and text' do
input_filtered_search("label:~#{caps_sensitive_label.title} author:@#{user.username} #{search_term}")
- expect_tokens([
- { name: 'label', value: caps_sensitive_label.title },
- { name: 'author', value: user.username }
- ])
+ wait_for_requests
+
+ expect_tokens([label_token(caps_sensitive_label.title), author_token(user.name)])
expect_issues_list_count(1)
expect_filtered_search_input(search_term)
end
@@ -382,10 +396,12 @@ describe 'Filter issues', js: true do
it 'filters issues by searched label, author, assignee and text' do
input_filtered_search("label:~#{caps_sensitive_label.title} author:@#{user.username} assignee:@#{user.username} #{search_term}")
+ wait_for_requests
+
expect_tokens([
- { name: 'label', value: caps_sensitive_label.title },
- { name: 'author', value: user.username },
- { name: 'assignee', value: user.username }
+ label_token(caps_sensitive_label.title),
+ author_token(user.name),
+ assignee_token(user.name)
])
expect_issues_list_count(1)
expect_filtered_search_input(search_term)
@@ -395,10 +411,10 @@ describe 'Filter issues', js: true do
input_filtered_search("label:~#{caps_sensitive_label.title} author:@#{user.username} assignee:@#{user.username} milestone:%#{milestone.title} #{search_term}")
expect_tokens([
- { name: 'label', value: caps_sensitive_label.title },
- { name: 'author', value: user.username },
- { name: 'assignee', value: user.username },
- { name: 'milestone', value: milestone.title }
+ label_token(caps_sensitive_label.title),
+ author_token(user.name),
+ assignee_token(user.name),
+ milestone_token(milestone.title)
])
expect_issues_list_count(1)
expect_filtered_search_input(search_term)
@@ -410,8 +426,8 @@ describe 'Filter issues', js: true do
input_filtered_search("label:~#{bug_label.title} label:~#{caps_sensitive_label.title} #{search_term}")
expect_tokens([
- { name: 'label', value: bug_label.title },
- { name: 'label', value: caps_sensitive_label.title }
+ label_token(bug_label.title),
+ label_token(caps_sensitive_label.title)
])
expect_issues_list_count(1)
expect_filtered_search_input(search_term)
@@ -420,10 +436,12 @@ describe 'Filter issues', js: true do
it 'filters issues by searched label, label2, author and text' do
input_filtered_search("label:~#{bug_label.title} label:~#{caps_sensitive_label.title} author:@#{user.username} #{search_term}")
+ wait_for_requests
+
expect_tokens([
- { name: 'label', value: bug_label.title },
- { name: 'label', value: caps_sensitive_label.title },
- { name: 'author', value: user.username }
+ label_token(bug_label.title),
+ label_token(caps_sensitive_label.title),
+ author_token(user.name)
])
expect_issues_list_count(1)
expect_filtered_search_input(search_term)
@@ -432,11 +450,13 @@ describe 'Filter issues', js: true do
it 'filters issues by searched label, label2, author, assignee and text' do
input_filtered_search("label:~#{bug_label.title} label:~#{caps_sensitive_label.title} author:@#{user.username} assignee:@#{user.username} #{search_term}")
+ wait_for_requests
+
expect_tokens([
- { name: 'label', value: bug_label.title },
- { name: 'label', value: caps_sensitive_label.title },
- { name: 'author', value: user.username },
- { name: 'assignee', value: user.username }
+ label_token(bug_label.title),
+ label_token(caps_sensitive_label.title),
+ author_token(user.name),
+ assignee_token(user.name)
])
expect_issues_list_count(1)
expect_filtered_search_input(search_term)
@@ -445,12 +465,14 @@ describe 'Filter issues', js: true do
it 'filters issues by searched label, label2, author, assignee, milestone and text' do
input_filtered_search("label:~#{bug_label.title} label:~#{caps_sensitive_label.title} author:@#{user.username} assignee:@#{user.username} milestone:%#{milestone.title} #{search_term}")
+ wait_for_requests
+
expect_tokens([
- { name: 'label', value: bug_label.title },
- { name: 'label', value: caps_sensitive_label.title },
- { name: 'author', value: user.username },
- { name: 'assignee', value: user.username },
- { name: 'milestone', value: milestone.title }
+ label_token(bug_label.title),
+ label_token(caps_sensitive_label.title),
+ author_token(user.name),
+ assignee_token(user.name),
+ milestone_token(milestone.title)
])
expect_issues_list_count(1)
expect_filtered_search_input(search_term)
@@ -467,7 +489,7 @@ describe 'Filter issues', js: true do
end
it 'displays in search bar' do
- expect_tokens([{ name: 'label', value: "\"#{multiple_words_label.title}\"" }])
+ expect_tokens([label_token("\"#{multiple_words_label.title}\"")])
expect_filtered_search_input_empty
end
end
@@ -484,7 +506,7 @@ describe 'Filter issues', js: true do
it 'filters issues by searched milestone' do
input_filtered_search("milestone:%#{milestone.title}")
- expect_tokens([{ name: 'milestone', value: milestone.title }])
+ expect_tokens([milestone_token(milestone.title)])
expect_issues_list_count(5)
expect_filtered_search_input_empty
end
@@ -492,7 +514,7 @@ describe 'Filter issues', js: true do
it 'filters issues by no milestone' do
input_filtered_search("milestone:none")
- expect_tokens([{ name: 'milestone', value: 'none' }])
+ expect_tokens([milestone_token('none', false)])
expect_issues_list_count(7, 1)
expect_filtered_search_input_empty
end
@@ -500,7 +522,7 @@ describe 'Filter issues', js: true do
it 'filters issues by upcoming milestones' do
input_filtered_search("milestone:upcoming")
- expect_tokens([{ name: 'milestone', value: 'upcoming' }])
+ expect_tokens([milestone_token('upcoming', false)])
expect_issues_list_count(1)
expect_filtered_search_input_empty
end
@@ -508,7 +530,7 @@ describe 'Filter issues', js: true do
it 'filters issues by started milestones' do
input_filtered_search("milestone:started")
- expect_tokens([{ name: 'milestone', value: 'started' }])
+ expect_tokens([milestone_token('started', false)])
expect_issues_list_count(5)
expect_filtered_search_input_empty
end
@@ -527,7 +549,7 @@ describe 'Filter issues', js: true do
input_filtered_search("milestone:%#{special_milestone.title}")
- expect_tokens([{ name: 'milestone', value: special_milestone.title }])
+ expect_tokens([milestone_token(special_milestone.title)])
expect_issues_list_count(1)
expect_filtered_search_input_empty
end
@@ -537,7 +559,7 @@ describe 'Filter issues', js: true do
input_filtered_search("milestone:%#{new_milestone.title}")
- expect_tokens([{ name: 'milestone', value: new_milestone.title }])
+ expect_tokens([milestone_token(new_milestone.title)])
expect_no_issues_list()
expect_filtered_search_input_empty
end
@@ -549,7 +571,7 @@ describe 'Filter issues', js: true do
it 'filters issues by searched milestone and text' do
input_filtered_search("milestone:%#{milestone.title} #{search_term}")
- expect_tokens([{ name: 'milestone', value: milestone.title }])
+ expect_tokens([milestone_token(milestone.title)])
expect_issues_list_count(2)
expect_filtered_search_input(search_term)
end
@@ -557,9 +579,11 @@ describe 'Filter issues', js: true do
it 'filters issues by searched milestone, author and text' do
input_filtered_search("milestone:%#{milestone.title} author:@#{user.username} #{search_term}")
+ wait_for_requests
+
expect_tokens([
- { name: 'milestone', value: milestone.title },
- { name: 'author', value: user.username }
+ milestone_token(milestone.title),
+ author_token(user.name)
])
expect_issues_list_count(2)
expect_filtered_search_input(search_term)
@@ -568,10 +592,12 @@ describe 'Filter issues', js: true do
it 'filters issues by searched milestone, author, assignee and text' do
input_filtered_search("milestone:%#{milestone.title} author:@#{user.username} assignee:@#{user.username} #{search_term}")
+ wait_for_requests
+
expect_tokens([
- { name: 'milestone', value: milestone.title },
- { name: 'author', value: user.username },
- { name: 'assignee', value: user.username }
+ milestone_token(milestone.title),
+ author_token(user.name),
+ assignee_token(user.name)
])
expect_issues_list_count(2)
expect_filtered_search_input(search_term)
@@ -580,11 +606,13 @@ describe 'Filter issues', js: true do
it 'filters issues by searched milestone, author, assignee, label and text' do
input_filtered_search("milestone:%#{milestone.title} author:@#{user.username} assignee:@#{user.username} label:~#{bug_label.title} #{search_term}")
+ wait_for_requests
+
expect_tokens([
- { name: 'milestone', value: milestone.title },
- { name: 'author', value: user.username },
- { name: 'assignee', value: user.username },
- { name: 'label', value: bug_label.title }
+ milestone_token(milestone.title),
+ author_token(user.name),
+ assignee_token(user.name),
+ label_token(bug_label.title)
])
expect_issues_list_count(2)
expect_filtered_search_input(search_term)
diff --git a/spec/features/issues/filtered_search/search_bar_spec.rb b/spec/features/issues/filtered_search/search_bar_spec.rb
index aa9d0d842de..a432d031337 100644
--- a/spec/features/issues/filtered_search/search_bar_spec.rb
+++ b/spec/features/issues/filtered_search/search_bar_spec.rb
@@ -32,7 +32,7 @@ describe 'Search bar', js: true do
it 'selects item' do
filtered_search.native.send_keys(:down, :down, :enter)
- expect_tokens([{ name: 'author' }])
+ expect_tokens([author_token])
expect_filtered_search_input_empty
end
end
diff --git a/spec/features/issues/filtered_search/visual_tokens_spec.rb b/spec/features/issues/filtered_search/visual_tokens_spec.rb
index 52efe944b69..14a555fde10 100644
--- a/spec/features/issues/filtered_search/visual_tokens_spec.rb
+++ b/spec/features/issues/filtered_search/visual_tokens_spec.rb
@@ -346,8 +346,8 @@ describe 'Visual tokens', js: true do
it 'tokenizes the search term to complete visual token' do
expect_tokens([
- { name: 'author', value: '@root' },
- { name: 'assignee', value: 'none' }
+ author_token(user.name),
+ assignee_token('none')
])
end
end
diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb
index 3c8e37ff920..3ffc80622f5 100644
--- a/spec/features/issues_spec.rb
+++ b/spec/features/issues_spec.rb
@@ -708,7 +708,7 @@ describe 'Issues' do
end
describe 'confidential issue#show', js: true do
- it 'shows confidential sibebar information as confidential and can be turned off' do
+ it 'shows confidential sibebar information as confidential and can be turned off' do
issue = create(:issue, :confidential, project: project)
visit project_issue_path(project, issue)
diff --git a/spec/features/merge_requests/conflicts_spec.rb b/spec/features/merge_requests/conflicts_spec.rb
index 2c560632a1b..2d2c674f8fb 100644
--- a/spec/features/merge_requests/conflicts_spec.rb
+++ b/spec/features/merge_requests/conflicts_spec.rb
@@ -28,11 +28,12 @@ feature 'Merge request conflict resolution', js: true do
end
click_button 'Commit conflict resolution'
- wait_for_requests
expect(page).to have_content('All merge conflicts were resolved')
merge_request.reload_diff
+ wait_for_requests
+
click_on 'Changes'
wait_for_requests
@@ -69,10 +70,12 @@ feature 'Merge request conflict resolution', js: true do
end
click_button 'Commit conflict resolution'
- wait_for_requests
+
expect(page).to have_content('All merge conflicts were resolved')
merge_request.reload_diff
+ wait_for_requests
+
click_on 'Changes'
wait_for_requests
@@ -140,12 +143,13 @@ feature 'Merge request conflict resolution', js: true do
end
click_button 'Commit conflict resolution'
- wait_for_requests
expect(page).to have_content('All merge conflicts were resolved')
merge_request.reload_diff
+ wait_for_requests
+
click_on 'Changes'
wait_for_requests
click_link 'Expand all'
diff --git a/spec/features/merge_requests/filter_by_milestone_spec.rb b/spec/features/merge_requests/filter_by_milestone_spec.rb
index 521fcabc881..166c02a7a7f 100644
--- a/spec/features/merge_requests/filter_by_milestone_spec.rb
+++ b/spec/features/merge_requests/filter_by_milestone_spec.rb
@@ -25,7 +25,7 @@ feature 'Merge Request filtering by Milestone' do
visit_merge_requests(project)
input_filtered_search('milestone:none')
- expect_tokens([{ name: 'milestone', value: 'none' }])
+ expect_tokens([milestone_token('none', false)])
expect_filtered_search_input_empty
expect(page).to have_issuable_counts(open: 1, closed: 0, all: 1)
diff --git a/spec/features/merge_requests/filter_merge_requests_spec.rb b/spec/features/merge_requests/filter_merge_requests_spec.rb
index 3686131fee4..b51ae0890e4 100644
--- a/spec/features/merge_requests/filter_merge_requests_spec.rb
+++ b/spec/features/merge_requests/filter_merge_requests_spec.rb
@@ -24,7 +24,9 @@ describe 'Filter merge requests' do
let(:search_query) { "assignee:@#{user.username}" }
def expect_assignee_visual_tokens
- expect_tokens([{ name: 'assignee', value: "@#{user.username}" }])
+ wait_for_requests
+
+ expect_tokens([assignee_token(user.name)])
expect_filtered_search_input_empty
end
@@ -57,7 +59,7 @@ describe 'Filter merge requests' do
let(:search_query) { "milestone:%\"#{milestone.title}\"" }
def expect_milestone_visual_tokens
- expect_tokens([{ name: 'milestone', value: "%\"#{milestone.title}\"" }])
+ expect_tokens([milestone_token("\"#{milestone.title}\"")])
expect_filtered_search_input_empty
end
@@ -91,7 +93,7 @@ describe 'Filter merge requests' do
input_filtered_search('label:none')
expect_mr_list_count(1)
- expect_tokens([{ name: 'label', value: 'none' }])
+ expect_tokens([label_token('none', false)])
expect_filtered_search_input_empty
end
@@ -99,7 +101,7 @@ describe 'Filter merge requests' do
input_filtered_search("label:~#{label.title}")
expect_mr_list_count(0)
- expect_tokens([{ name: 'label', value: "~#{label.title}" }])
+ expect_tokens([label_token(label.title)])
expect_filtered_search_input_empty
end
@@ -107,10 +109,7 @@ describe 'Filter merge requests' do
input_filtered_search("label:~\"#{wontfix.title}\" label:~#{label.title}")
expect_mr_list_count(0)
- expect_tokens([
- { name: 'label', value: "~\"#{wontfix.title}\"" },
- { name: 'label', value: "~#{label.title}" }
- ])
+ expect_tokens([label_token("\"#{wontfix.title}\""), label_token(label.title)])
expect_filtered_search_input_empty
end
@@ -118,16 +117,13 @@ describe 'Filter merge requests' do
input_filtered_search("label:~\"#{wontfix.title}\"")
expect_mr_list_count(0)
- expect_tokens([{ name: 'label', value: "~\"#{wontfix.title}\"" }])
+ expect_tokens([label_token("\"#{wontfix.title}\"")])
expect_filtered_search_input_empty
input_filtered_search_keys("label:~#{label.title}")
expect_mr_list_count(0)
- expect_tokens([
- { name: 'label', value: "~\"#{wontfix.title}\"" },
- { name: 'label', value: "~#{label.title}" }
- ])
+ expect_tokens([label_token("\"#{wontfix.title}\""), label_token(label.title)])
expect_filtered_search_input_empty
end
end
@@ -143,10 +139,9 @@ describe 'Filter merge requests' do
context 'assignee and label', js: true do
def expect_assignee_label_visual_tokens
- expect_tokens([
- { name: 'assignee', value: "@#{user.username}" },
- { name: 'label', value: "~#{label.title}" }
- ])
+ wait_for_requests
+
+ expect_tokens([assignee_token(user.name), label_token(label.title)])
expect_filtered_search_input_empty
end
@@ -214,7 +209,7 @@ describe 'Filter merge requests' do
input_filtered_search_keys(' label:~bug')
expect_mr_list_count(1)
- expect_tokens([{ name: 'label', value: '~bug' }])
+ expect_tokens([label_token('bug')])
expect_filtered_search_input('Bug')
end
@@ -227,7 +222,7 @@ describe 'Filter merge requests' do
input_filtered_search_keys(' milestone:%8')
expect_mr_list_count(1)
- expect_tokens([{ name: 'milestone', value: '%8' }])
+ expect_tokens([milestone_token('8')])
expect_filtered_search_input('Bug')
end
@@ -240,7 +235,10 @@ describe 'Filter merge requests' do
input_filtered_search_keys(" assignee:@#{user.username}")
expect_mr_list_count(1)
- expect_tokens([{ name: 'assignee', value: "@#{user.username}" }])
+
+ wait_for_requests
+
+ expect_tokens([assignee_token(user.name)])
expect_filtered_search_input('Bug')
end
@@ -252,8 +250,10 @@ describe 'Filter merge requests' do
input_filtered_search_keys(" author:@#{user.username}")
+ wait_for_requests
+
expect_mr_list_count(1)
- expect_tokens([{ name: 'author', value: "@#{user.username}" }])
+ expect_tokens([author_token(user.name)])
expect_filtered_search_input('Bug')
end
end
@@ -293,7 +293,9 @@ describe 'Filter merge requests' do
it 'filter by current user' do
visit project_merge_requests_path(project, assignee_id: user.id)
- expect_tokens([{ name: 'assignee', value: "@#{user.username}" }])
+ wait_for_requests
+
+ expect_tokens([assignee_token(user.name)])
expect_filtered_search_input_empty
end
@@ -303,7 +305,9 @@ describe 'Filter merge requests' do
visit project_merge_requests_path(project, assignee_id: new_user.id)
- expect_tokens([{ name: 'assignee', value: "@#{new_user.username}" }])
+ wait_for_requests
+
+ expect_tokens([assignee_token(new_user.name)])
expect_filtered_search_input_empty
end
end
@@ -312,7 +316,9 @@ describe 'Filter merge requests' do
it 'filter by current user' do
visit project_merge_requests_path(project, author_id: user.id)
- expect_tokens([{ name: 'author', value: "@#{user.username}" }])
+ wait_for_requests
+
+ expect_tokens([author_token(user.name)])
expect_filtered_search_input_empty
end
@@ -322,7 +328,9 @@ describe 'Filter merge requests' do
visit project_merge_requests_path(project, author_id: new_user.id)
- expect_tokens([{ name: 'author', value: "@#{new_user.username}" }])
+ wait_for_requests
+
+ expect_tokens([author_token(new_user.name)])
expect_filtered_search_input_empty
end
end
diff --git a/spec/features/milestones/show_spec.rb b/spec/features/milestones/show_spec.rb
index 20303359c46..624f13922ed 100644
--- a/spec/features/milestones/show_spec.rb
+++ b/spec/features/milestones/show_spec.rb
@@ -8,7 +8,7 @@ describe 'Milestone show' do
let(:issue_params) { { project: project, assignees: [user], author: user, milestone: milestone, labels: labels } }
before do
- project.add_user(user, :developer)
+ project.add_user(user, :developer)
sign_in(user)
end
diff --git a/spec/features/projects/files/undo_template_spec.rb b/spec/features/projects/files/undo_template_spec.rb
index 4238d25e9ee..9bcd5beabb8 100644
--- a/spec/features/projects/files/undo_template_spec.rb
+++ b/spec/features/projects/files/undo_template_spec.rb
@@ -20,7 +20,7 @@ feature 'Template Undo Button', js: true do
end
end
- context 'creating a non-matching file' do
+ context 'creating a non-matching file' do
before do
visit project_new_blob_path(project, 'master')
select_file_template_type('LICENSE')
diff --git a/spec/features/search_spec.rb b/spec/features/search_spec.rb
index 9b49fc2225d..6742d77937f 100644
--- a/spec/features/search_spec.rb
+++ b/spec/features/search_spec.rb
@@ -195,37 +195,33 @@ describe "Search" do
it 'takes user to her issues page when issues assigned is clicked' do
find('.dropdown-menu').click_link 'Issues assigned to me'
- sleep 2
expect(page).to have_selector('.filtered-search')
- expect_tokens([{ name: 'assignee', value: "@#{user.username}" }])
+ expect_tokens([assignee_token(user.name)])
expect_filtered_search_input_empty
end
it 'takes user to her issues page when issues authored is clicked' do
find('.dropdown-menu').click_link "Issues I've created"
- sleep 2
expect(page).to have_selector('.filtered-search')
- expect_tokens([{ name: 'author', value: "@#{user.username}" }])
+ expect_tokens([author_token(user.name)])
expect_filtered_search_input_empty
end
it 'takes user to her MR page when MR assigned is clicked' do
find('.dropdown-menu').click_link 'Merge requests assigned to me'
- sleep 2
expect(page).to have_selector('.merge-requests-holder')
- expect_tokens([{ name: 'assignee', value: "@#{user.username}" }])
+ expect_tokens([assignee_token(user.name)])
expect_filtered_search_input_empty
end
it 'takes user to her MR page when MR authored is clicked' do
find('.dropdown-menu').click_link "Merge requests I've created"
- sleep 2
expect(page).to have_selector('.merge-requests-holder')
- expect_tokens([{ name: 'author', value: "@#{user.username}" }])
+ expect_tokens([author_token(user.name)])
expect_filtered_search_input_empty
end
end
diff --git a/spec/helpers/version_check_helper_spec.rb b/spec/helpers/version_check_helper_spec.rb
index 889fe441171..5eba03ef576 100644
--- a/spec/helpers/version_check_helper_spec.rb
+++ b/spec/helpers/version_check_helper_spec.rb
@@ -23,7 +23,7 @@ describe VersionCheckHelper do
end
it 'should have a js prefixed css class' do
- expect(@image_tag).to match(/class="js-version-status-badge"/)
+ expect(@image_tag).to match(/class="js-version-status-badge lazy"/)
end
it 'should have a VersionCheck url as the src' do
diff --git a/spec/javascripts/fixtures/prometheus_service.rb b/spec/javascripts/fixtures/prometheus_service.rb
index 7a46e47bb15..7968c9425f2 100644
--- a/spec/javascripts/fixtures/prometheus_service.rb
+++ b/spec/javascripts/fixtures/prometheus_service.rb
@@ -7,7 +7,7 @@ describe Projects::ServicesController, '(JavaScript fixtures)', type: :controlle
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let(:project) { create(:project_empty_repo, namespace: namespace, path: 'services-project') }
let!(:service) { create(:prometheus_service, project: project) }
-
+
render_views
before(:all) do
diff --git a/spec/javascripts/fixtures/services.rb b/spec/javascripts/fixtures/services.rb
index 0a3c64d5d31..80915c32a74 100644
--- a/spec/javascripts/fixtures/services.rb
+++ b/spec/javascripts/fixtures/services.rb
@@ -7,7 +7,6 @@ describe Projects::ServicesController, '(JavaScript fixtures)', type: :controlle
let(:namespace) { create(:namespace, name: 'frontend-fixtures' )}
let(:project) { create(:project_empty_repo, namespace: namespace, path: 'services-project') }
let!(:service) { create(:custom_issue_tracker_service, project: project, title: 'Custom Issue Tracker') }
-
render_views
diff --git a/spec/javascripts/fly_out_nav_spec.js b/spec/javascripts/fly_out_nav_spec.js
index 65a7459c5ed..2e81a1b056b 100644
--- a/spec/javascripts/fly_out_nav_spec.js
+++ b/spec/javascripts/fly_out_nav_spec.js
@@ -10,6 +10,7 @@ import {
mousePos,
getHideSubItemsInterval,
documentMouseMove,
+ getHeaderHeight,
} from '~/fly_out_nav';
import bp from '~/breakpoints';
@@ -59,7 +60,7 @@ describe('Fly out sidebar navigation', () => {
describe('getHideSubItemsInterval', () => {
beforeEach(() => {
- el.innerHTML = '<div class="sidebar-sub-level-items" style="position: fixed; top: 0; left: 100px; height: 50px;"></div>';
+ el.innerHTML = '<div class="sidebar-sub-level-items" style="position: fixed; top: 0; left: 100px; height: 150px;"></div>';
});
it('returns 0 if currentOpenMenu is nil', () => {
@@ -112,6 +113,7 @@ describe('Fly out sidebar navigation', () => {
clientX: el.getBoundingClientRect().left + 20,
clientY: el.getBoundingClientRect().top + 10,
});
+ console.log(el);
expect(
getHideSubItemsInterval(),
@@ -245,7 +247,7 @@ describe('Fly out sidebar navigation', () => {
expect(
subItems.style.transform,
- ).toBe(`translate3d(0px, ${Math.floor(el.getBoundingClientRect().top)}px, 0px)`);
+ ).toBe(`translate3d(0px, ${Math.floor(el.getBoundingClientRect().top) - getHeaderHeight()}px, 0px)`);
});
it('sets is-above when element is above', () => {
diff --git a/spec/lib/file_size_validator_spec.rb b/spec/lib/file_size_validator_spec.rb
index 49501931dd2..c44bc1840df 100644
--- a/spec/lib/file_size_validator_spec.rb
+++ b/spec/lib/file_size_validator_spec.rb
@@ -24,13 +24,13 @@ describe FileSizeValidator do
describe 'options uses a symbol' do
let(:options) do
{
- maximum: :test,
+ maximum: :max_attachment_size,
attributes: { attachment: attachment }
}
end
before do
- allow(note).to receive(:test) { 10 }
+ expect(note).to receive(:max_attachment_size) { 10 }
end
it 'attachment exceeds maximum limit' do
diff --git a/spec/lib/gitlab/ci/trace/stream_spec.rb b/spec/lib/gitlab/ci/trace/stream_spec.rb
index ebe5af56160..e5555546fa8 100644
--- a/spec/lib/gitlab/ci/trace/stream_spec.rb
+++ b/spec/lib/gitlab/ci/trace/stream_spec.rb
@@ -295,7 +295,7 @@ describe Gitlab::Ci::Trace::Stream do
end
context 'malicious regexp' do
- let(:data) { malicious_text }
+ let(:data) { malicious_text }
let(:regex) { malicious_regexp }
include_examples 'malicious regexp'
diff --git a/spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb b/spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb
index 854aaa34c73..0560c47f03f 100644
--- a/spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb
+++ b/spec/lib/gitlab/cycle_analytics/base_event_fetcher_spec.rb
@@ -6,10 +6,10 @@ describe Gitlab::CycleAnalytics::BaseEventFetcher do
let(:user) { create(:user, :admin) }
let(:start_time_attrs) { Issue.arel_table[:created_at] }
let(:end_time_attrs) { [Issue::Metrics.arel_table[:first_associated_with_milestone_at]] }
- let(:options) do
+ let(:options) do
{ start_time_attrs: start_time_attrs,
end_time_attrs: end_time_attrs,
- from: 30.days.ago }
+ from: 30.days.ago }
end
subject do
diff --git a/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb b/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb
index 9d1763b96ad..c86353abb7c 100644
--- a/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb
+++ b/spec/lib/gitlab/git/storage/circuit_breaker_spec.rb
@@ -1,9 +1,30 @@
require 'spec_helper'
describe Gitlab::Git::Storage::CircuitBreaker, clean_gitlab_redis_shared_state: true, broken_storage: true do
- let(:circuit_breaker) { described_class.new('default') }
+ let(:storage_name) { 'default' }
+ let(:circuit_breaker) { described_class.new(storage_name) }
let(:hostname) { Gitlab::Environment.hostname }
- let(:cache_key) { "storage_accessible:default:#{hostname}" }
+ let(:cache_key) { "storage_accessible:#{storage_name}:#{hostname}" }
+
+ before do
+ # Override test-settings for the circuitbreaker with something more realistic
+ # for these specs.
+ stub_storage_settings('default' => {
+ 'path' => TestEnv.repos_path,
+ 'failure_count_threshold' => 10,
+ 'failure_wait_time' => 30,
+ 'failure_reset_time' => 1800,
+ 'storage_timeout' => 5
+ },
+ 'broken' => {
+ 'path' => 'tmp/tests/non-existent-repositories',
+ 'failure_count_threshold' => 10,
+ 'failure_wait_time' => 30,
+ 'failure_reset_time' => 1800,
+ 'storage_timeout' => 5
+ }
+ )
+ end
def value_from_redis(name)
Gitlab::Git::Storage.redis.with do |redis|
@@ -96,14 +117,14 @@ describe Gitlab::Git::Storage::CircuitBreaker, clean_gitlab_redis_shared_state:
end
describe '#circuit_broken?' do
- it 'is closed when there is no last failure' do
+ it 'is working when there is no last failure' do
set_in_redis(:last_failure, nil)
set_in_redis(:failure_count, 0)
expect(circuit_breaker.circuit_broken?).to be_falsey
end
- it 'is open when there was a recent failure' do
+ it 'is broken when there was a recent failure' do
Timecop.freeze do
set_in_redis(:last_failure, 1.second.ago.to_f)
set_in_redis(:failure_count, 1)
@@ -112,16 +133,34 @@ describe Gitlab::Git::Storage::CircuitBreaker, clean_gitlab_redis_shared_state:
end
end
- it 'is open when there are to many failures' do
+ it 'is broken when there are too many failures' do
set_in_redis(:last_failure, 1.day.ago.to_f)
set_in_redis(:failure_count, 200)
expect(circuit_breaker.circuit_broken?).to be_truthy
end
+
+ context 'the `failure_wait_time` is set to 0' do
+ before do
+ stub_storage_settings('default' => {
+ 'failure_wait_time' => 0,
+ 'path' => TestEnv.repos_path
+ })
+ end
+
+ it 'is working even when there is a recent failure' do
+ Timecop.freeze do
+ set_in_redis(:last_failure, 0.seconds.ago.to_f)
+ set_in_redis(:failure_count, 1)
+
+ expect(circuit_breaker.circuit_broken?).to be_falsey
+ end
+ end
+ end
end
describe "storage_available?" do
- context 'when the storage is available' do
+ context 'the storage is available' do
it 'tracks that the storage was accessible an raises the error' do
expect(circuit_breaker).to receive(:track_storage_accessible)
@@ -136,8 +175,8 @@ describe Gitlab::Git::Storage::CircuitBreaker, clean_gitlab_redis_shared_state:
end
end
- context 'when storage is not available' do
- let(:circuit_breaker) { described_class.new('broken') }
+ context 'storage is not available' do
+ let(:storage_name) { 'broken' }
it 'tracks that the storage was inaccessible' do
expect(circuit_breaker).to receive(:track_storage_inaccessible)
@@ -158,8 +197,8 @@ describe Gitlab::Git::Storage::CircuitBreaker, clean_gitlab_redis_shared_state:
end
end
- context 'when the storage is not available' do
- let(:circuit_breaker) { described_class.new('broken') }
+ context 'the storage is not available' do
+ let(:storage_name) { 'broken' }
it 'raises an error' do
expect(circuit_breaker).to receive(:track_storage_inaccessible)
diff --git a/spec/lib/gitlab/key_fingerprint_spec.rb b/spec/lib/gitlab/key_fingerprint_spec.rb
index f5fd5a96bc9..d643dc5342d 100644
--- a/spec/lib/gitlab/key_fingerprint_spec.rb
+++ b/spec/lib/gitlab/key_fingerprint_spec.rb
@@ -30,8 +30,8 @@ describe Gitlab::KeyFingerprint, lib: true do
MD5_FINGERPRINTS = {
rsa: '06:b2:8a:92:df:0e:11:2c:ca:7b:8f:a4:ba:6e:4b:fd',
- ecdsa: '45:ff:5b:98:9a:b6:8a:41:13:c1:30:8b:09:5e:7b:4e',
- ed25519: '2e:65:6a:c8:cf:bf:b2:8b:9a:bd:6d:9f:11:5c:12:16',
+ ecdsa: '45:ff:5b:98:9a:b6:8a:41:13:c1:30:8b:09:5e:7b:4e',
+ ed25519: '2e:65:6a:c8:cf:bf:b2:8b:9a:bd:6d:9f:11:5c:12:16',
dss: '57:98:86:02:5f:9c:f4:9b:ad:5a:1e:51:92:0e:fd:2b'
}.freeze
diff --git a/spec/lib/gitlab/ldap/auth_hash_spec.rb b/spec/lib/gitlab/ldap/auth_hash_spec.rb
index 57a91193004..8370adf9211 100644
--- a/spec/lib/gitlab/ldap/auth_hash_spec.rb
+++ b/spec/lib/gitlab/ldap/auth_hash_spec.rb
@@ -4,8 +4,8 @@ describe Gitlab::LDAP::AuthHash do
let(:auth_hash) do
described_class.new(
OmniAuth::AuthHash.new(
- uid: '123456',
- provider: 'ldapmain',
+ uid: '123456',
+ provider: 'ldapmain',
info: info,
extra: {
raw_info: raw_info
@@ -33,11 +33,11 @@ describe Gitlab::LDAP::AuthHash do
context "without overridden attributes" do
it "has the correct username" do
- expect(auth_hash.username).to eq("123456")
+ expect(auth_hash.username).to eq("123456")
end
it "has the correct name" do
- expect(auth_hash.name).to eq("Smith, J.")
+ expect(auth_hash.name).to eq("Smith, J.")
end
end
@@ -54,11 +54,11 @@ describe Gitlab::LDAP::AuthHash do
end
it "has the correct username" do
- expect(auth_hash.username).to eq("johnsmith@example.com")
+ expect(auth_hash.username).to eq("johnsmith@example.com")
end
it "has the correct name" do
- expect(auth_hash.name).to eq("John Smith")
+ expect(auth_hash.name).to eq("John Smith")
end
end
end
diff --git a/spec/lib/gitlab/o_auth/user_spec.rb b/spec/lib/gitlab/o_auth/user_spec.rb
index 15edb820908..2cf0f7516de 100644
--- a/spec/lib/gitlab/o_auth/user_spec.rb
+++ b/spec/lib/gitlab/o_auth/user_spec.rb
@@ -481,7 +481,7 @@ describe Gitlab::OAuth::User do
email: 'admin@othermail.com'
}
end
-
+
it 'generates the username with a counter' do
expect(gl_user.username).to eq('admin1')
end
diff --git a/spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb b/spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb
index d7df4e35c31..5589db92b1d 100644
--- a/spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb
+++ b/spec/lib/gitlab/prometheus/additional_metrics_parser_spec.rb
@@ -24,7 +24,7 @@ describe Gitlab::Prometheus::AdditionalMetricsParser do
queries: [{ query_range: 'query_range_empty' }]
- group: group_b
priority: 1
- metrics:
+ metrics:
- title: title
required_metrics: ['metric_a']
weight: 1
@@ -148,7 +148,7 @@ describe Gitlab::Prometheus::AdditionalMetricsParser do
- group: group_a
priority: 1
metrics:
- - title:
+ - title:
required_metrics: []
weight: 1
queries: []
diff --git a/spec/lib/gitlab/redis/wrapper_spec.rb b/spec/lib/gitlab/redis/wrapper_spec.rb
index e1becd0a614..0c22a0d62cc 100644
--- a/spec/lib/gitlab/redis/wrapper_spec.rb
+++ b/spec/lib/gitlab/redis/wrapper_spec.rb
@@ -17,4 +17,11 @@ describe Gitlab::Redis::Wrapper do
let(:class_redis_url) { Gitlab::Redis::Wrapper::DEFAULT_REDIS_URL }
include_examples "redis_shared_examples"
+
+ describe '.config_file_path' do
+ it 'returns the absolute path to the configuration file' do
+ expect(described_class.config_file_path('foo.yml'))
+ .to eq Rails.root.join('config', 'foo.yml').to_s
+ end
+ end
end
diff --git a/spec/lib/gitlab/shell_spec.rb b/spec/lib/gitlab/shell_spec.rb
index 2345874cf10..cfadee0bcf5 100644
--- a/spec/lib/gitlab/shell_spec.rb
+++ b/spec/lib/gitlab/shell_spec.rb
@@ -94,28 +94,41 @@ describe Gitlab::Shell do
end
describe 'projects commands' do
- let(:projects_path) { 'tmp/tests/shell-projects-test/bin/gitlab-projects' }
+ let(:gitlab_shell_path) { File.expand_path('tmp/tests/gitlab-shell') }
+ let(:projects_path) { File.join(gitlab_shell_path, 'bin/gitlab-projects') }
+ let(:gitlab_shell_hooks_path) { File.join(gitlab_shell_path, 'hooks') }
before do
- allow(Gitlab.config.gitlab_shell).to receive(:path).and_return('tmp/tests/shell-projects-test')
+ allow(Gitlab.config.gitlab_shell).to receive(:path).and_return(gitlab_shell_path)
+ allow(Gitlab.config.gitlab_shell).to receive(:hooks_path).and_return(gitlab_shell_hooks_path)
allow(Gitlab.config.gitlab_shell).to receive(:git_timeout).and_return(800)
end
describe '#add_repository' do
- it 'returns true when the command succeeds' do
- expect(Gitlab::Popen).to receive(:popen)
- .with([projects_path, 'add-project', 'current/storage', 'project/path.git'],
- nil, popen_vars).and_return([nil, 0])
+ it 'creates a repository' do
+ created_path = File.join(TestEnv.repos_path, 'project', 'path.git')
+ hooks_path = File.join(created_path, 'hooks')
+
+ begin
+ result = gitlab_shell.add_repository(TestEnv.repos_path, 'project/path')
+
+ repo_stat = File.stat(created_path) rescue nil
+ hooks_stat = File.lstat(hooks_path) rescue nil
+ hooks_dir = File.realpath(hooks_path)
+ ensure
+ FileUtils.rm_rf(created_path)
+ end
- expect(gitlab_shell.add_repository('current/storage', 'project/path')).to be true
+ expect(result).to be_truthy
+ expect(repo_stat.mode & 0o777).to eq(0o770)
+ expect(hooks_stat.symlink?).to be_truthy
+ expect(hooks_dir).to eq(gitlab_shell_hooks_path)
end
it 'returns false when the command fails' do
- expect(Gitlab::Popen).to receive(:popen)
- .with([projects_path, 'add-project', 'current/storage', 'project/path.git'],
- nil, popen_vars).and_return(["error", 1])
+ expect(FileUtils).to receive(:mkdir_p).and_raise(Errno::EEXIST)
- expect(gitlab_shell.add_repository('current/storage', 'project/path')).to be false
+ expect(gitlab_shell.add_repository('current/storage', 'project/path')).to be_falsy
end
end
diff --git a/spec/lib/gitlab/utils_spec.rb b/spec/lib/gitlab/utils_spec.rb
index 111c873f79c..92787bb262e 100644
--- a/spec/lib/gitlab/utils_spec.rb
+++ b/spec/lib/gitlab/utils_spec.rb
@@ -1,7 +1,21 @@
require 'spec_helper'
describe Gitlab::Utils do
- delegate :to_boolean, :boolean_to_yes_no, to: :described_class
+ delegate :to_boolean, :boolean_to_yes_no, :slugify, to: :described_class
+
+ describe '.slugify' do
+ {
+ 'TEST' => 'test',
+ 'project_with_underscores' => 'project-with-underscores',
+ 'namespace/project' => 'namespace-project',
+ 'a' * 70 => 'a' * 63,
+ 'test_trailing_' => 'test-trailing'
+ }.each do |original, expected|
+ it "slugifies #{original} to #{expected}" do
+ expect(slugify(original)).to eq(expected)
+ end
+ end
+ end
describe '.to_boolean' do
it 'accepts booleans' do
diff --git a/spec/migrations/migrate_old_artifacts_spec.rb b/spec/migrations/migrate_old_artifacts_spec.rb
index cfe1ca481b2..81366d15b34 100644
--- a/spec/migrations/migrate_old_artifacts_spec.rb
+++ b/spec/migrations/migrate_old_artifacts_spec.rb
@@ -10,7 +10,7 @@ describe MigrateOldArtifacts do
before do
allow(Gitlab.config.artifacts).to receive(:path).and_return(directory)
end
-
+
after do
FileUtils.remove_entry_secure(directory)
end
@@ -95,7 +95,7 @@ describe MigrateOldArtifacts do
FileUtils.copy(
Rails.root.join('spec/fixtures/ci_build_artifacts.zip'),
File.join(legacy_path(build), "ci_build_artifacts.zip"))
-
+
FileUtils.copy(
Rails.root.join('spec/fixtures/ci_build_artifacts_metadata.gz'),
File.join(legacy_path(build), "ci_build_artifacts_metadata.gz"))
diff --git a/spec/migrations/remove_duplicate_mr_events_spec.rb b/spec/migrations/remove_duplicate_mr_events_spec.rb
new file mode 100644
index 00000000000..e393374028f
--- /dev/null
+++ b/spec/migrations/remove_duplicate_mr_events_spec.rb
@@ -0,0 +1,26 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20170815060945_remove_duplicate_mr_events.rb')
+
+describe RemoveDuplicateMrEvents, truncate: true do
+ let(:migration) { described_class.new }
+
+ describe '#up' do
+ let(:user) { create(:user) }
+ let(:merge_requests) { create_list(:merge_request, 2) }
+ let(:issue) { create(:issue) }
+ let!(:events) do
+ [
+ create(:event, :created, author: user, target: merge_requests.first),
+ create(:event, :created, author: user, target: merge_requests.first),
+ create(:event, :updated, author: user, target: merge_requests.first),
+ create(:event, :created, author: user, target: merge_requests.second),
+ create(:event, :created, author: user, target: issue),
+ create(:event, :created, author: user, target: issue)
+ ]
+ end
+
+ it 'removes duplicated merge request create records' do
+ expect { migration.up }.to change { Event.count }.from(6).to(5)
+ end
+ end
+end
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 86afa856ea7..767f0ad9e65 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -1220,7 +1220,7 @@ describe Ci::Build do
{ key: 'CI_PROJECT_ID', value: project.id.to_s, public: true },
{ key: 'CI_PROJECT_NAME', value: project.path, public: true },
{ key: 'CI_PROJECT_PATH', value: project.full_path, public: true },
- { key: 'CI_PROJECT_PATH_SLUG', value: project.full_path.parameterize, public: true },
+ { key: 'CI_PROJECT_PATH_SLUG', value: project.full_path_slug, public: true },
{ key: 'CI_PROJECT_NAMESPACE', value: project.namespace.full_path, public: true },
{ key: 'CI_PROJECT_URL', value: project.web_url, public: true },
{ key: 'CI_PIPELINE_ID', value: pipeline.id.to_s, public: true },
diff --git a/spec/models/protectable_dropdown_spec.rb b/spec/models/protectable_dropdown_spec.rb
index 5c5dcd9f5c9..d4433a88a15 100644
--- a/spec/models/protectable_dropdown_spec.rb
+++ b/spec/models/protectable_dropdown_spec.rb
@@ -4,6 +4,13 @@ describe ProtectableDropdown do
let(:project) { create(:project, :repository) }
let(:subject) { described_class.new(project, :branches) }
+ describe 'initialize' do
+ it 'raises ArgumentError for invalid ref type' do
+ expect { described_class.new(double, :foo) }
+ .to raise_error(ArgumentError, "invalid ref type `foo`")
+ end
+ end
+
describe '#protectable_ref_names' do
before do
project.protected_branches.create(name: 'master')
diff --git a/spec/requests/api/commits_spec.rb b/spec/requests/api/commits_spec.rb
index 992a6e8d76a..dafe3f466a2 100644
--- a/spec/requests/api/commits_spec.rb
+++ b/spec/requests/api/commits_spec.rb
@@ -16,11 +16,13 @@ describe API::Commits do
end
describe 'GET /projects/:id/repository/commits' do
- context 'authorized user' do
+ let(:route) { "/projects/#{project_id}/repository/commits" }
+
+ shared_examples_for 'project commits' do
it "returns project commits" do
commit = project.repository.commit
- get api("/projects/#{project_id}/repository/commits", user)
+ get api(route, current_user)
expect(response).to have_http_status(200)
expect(response).to match_response_schema('public_api/v4/commits')
@@ -32,7 +34,7 @@ describe API::Commits do
it 'include correct pagination headers' do
commit_count = project.repository.count_commits(ref: 'master').to_s
- get api("/projects/#{project_id}/repository/commits", user)
+ get api(route, current_user)
expect(response).to include_pagination_headers
expect(response.headers['X-Total']).to eq(commit_count)
@@ -40,140 +42,151 @@ describe API::Commits do
end
end
- context "unauthorized user" do
- it "does not return project commits" do
- get api("/projects/#{project_id}/repository/commits")
+ context 'when unauthenticated', 'and project is public' do
+ let(:project) { create(:project, :public, :repository) }
+
+ it_behaves_like 'project commits'
+ end
- expect(response).to have_http_status(404)
+ context 'when unauthenticated', 'and project is private' do
+ it_behaves_like '404 response' do
+ let(:request) { get api(route) }
+ let(:message) { '404 Project Not Found' }
end
end
- context "since optional parameter" do
- it "returns project commits since provided parameter" do
- commits = project.repository.commits("master")
- after = commits.second.created_at
+ context 'when authenticated', 'as a master' do
+ let(:current_user) { user }
- get api("/projects/#{project_id}/repository/commits?since=#{after.utc.iso8601}", user)
+ it_behaves_like 'project commits'
- expect(json_response.size).to eq 2
- expect(json_response.first["id"]).to eq(commits.first.id)
- expect(json_response.second["id"]).to eq(commits.second.id)
- end
+ context "since optional parameter" do
+ it "returns project commits since provided parameter" do
+ commits = project.repository.commits("master")
+ after = commits.second.created_at
- it 'include correct pagination headers' do
- commits = project.repository.commits("master")
- after = commits.second.created_at
- commit_count = project.repository.count_commits(ref: 'master', after: after).to_s
+ get api("/projects/#{project_id}/repository/commits?since=#{after.utc.iso8601}", user)
- get api("/projects/#{project_id}/repository/commits?since=#{after.utc.iso8601}", user)
+ expect(json_response.size).to eq 2
+ expect(json_response.first["id"]).to eq(commits.first.id)
+ expect(json_response.second["id"]).to eq(commits.second.id)
+ end
- expect(response).to include_pagination_headers
- expect(response.headers['X-Total']).to eq(commit_count)
- expect(response.headers['X-Page']).to eql('1')
+ it 'include correct pagination headers' do
+ commits = project.repository.commits("master")
+ after = commits.second.created_at
+ commit_count = project.repository.count_commits(ref: 'master', after: after).to_s
+
+ get api("/projects/#{project_id}/repository/commits?since=#{after.utc.iso8601}", user)
+
+ expect(response).to include_pagination_headers
+ expect(response.headers['X-Total']).to eq(commit_count)
+ expect(response.headers['X-Page']).to eql('1')
+ end
end
- end
- context "until optional parameter" do
- it "returns project commits until provided parameter" do
- commits = project.repository.commits("master")
- before = commits.second.created_at
+ context "until optional parameter" do
+ it "returns project commits until provided parameter" do
+ commits = project.repository.commits("master")
+ before = commits.second.created_at
- get api("/projects/#{project_id}/repository/commits?until=#{before.utc.iso8601}", user)
+ get api("/projects/#{project_id}/repository/commits?until=#{before.utc.iso8601}", user)
- if commits.size >= 20
- expect(json_response.size).to eq(20)
- else
- expect(json_response.size).to eq(commits.size - 1)
- end
+ if commits.size >= 20
+ expect(json_response.size).to eq(20)
+ else
+ expect(json_response.size).to eq(commits.size - 1)
+ end
- expect(json_response.first["id"]).to eq(commits.second.id)
- expect(json_response.second["id"]).to eq(commits.third.id)
- end
+ expect(json_response.first["id"]).to eq(commits.second.id)
+ expect(json_response.second["id"]).to eq(commits.third.id)
+ end
- it 'include correct pagination headers' do
- commits = project.repository.commits("master")
- before = commits.second.created_at
- commit_count = project.repository.count_commits(ref: 'master', before: before).to_s
+ it 'include correct pagination headers' do
+ commits = project.repository.commits("master")
+ before = commits.second.created_at
+ commit_count = project.repository.count_commits(ref: 'master', before: before).to_s
- get api("/projects/#{project_id}/repository/commits?until=#{before.utc.iso8601}", user)
+ get api("/projects/#{project_id}/repository/commits?until=#{before.utc.iso8601}", user)
- expect(response).to include_pagination_headers
- expect(response.headers['X-Total']).to eq(commit_count)
- expect(response.headers['X-Page']).to eql('1')
+ expect(response).to include_pagination_headers
+ expect(response.headers['X-Total']).to eq(commit_count)
+ expect(response.headers['X-Page']).to eql('1')
+ end
end
- end
- context "invalid xmlschema date parameters" do
- it "returns an invalid parameter error message" do
- get api("/projects/#{project_id}/repository/commits?since=invalid-date", user)
+ context "invalid xmlschema date parameters" do
+ it "returns an invalid parameter error message" do
+ get api("/projects/#{project_id}/repository/commits?since=invalid-date", user)
- expect(response).to have_http_status(400)
- expect(json_response['error']).to eq('since is invalid')
+ expect(response).to have_http_status(400)
+ expect(json_response['error']).to eq('since is invalid')
+ end
end
- end
- context "path optional parameter" do
- it "returns project commits matching provided path parameter" do
- path = 'files/ruby/popen.rb'
- commit_count = project.repository.count_commits(ref: 'master', path: path).to_s
+ context "path optional parameter" do
+ it "returns project commits matching provided path parameter" do
+ path = 'files/ruby/popen.rb'
+ commit_count = project.repository.count_commits(ref: 'master', path: path).to_s
- get api("/projects/#{project_id}/repository/commits?path=#{path}", user)
+ get api("/projects/#{project_id}/repository/commits?path=#{path}", user)
- expect(json_response.size).to eq(3)
- expect(json_response.first["id"]).to eq("570e7b2abdd848b95f2f578043fc23bd6f6fd24d")
- expect(response).to include_pagination_headers
- expect(response.headers['X-Total']).to eq(commit_count)
- end
+ expect(json_response.size).to eq(3)
+ expect(json_response.first["id"]).to eq("570e7b2abdd848b95f2f578043fc23bd6f6fd24d")
+ expect(response).to include_pagination_headers
+ expect(response.headers['X-Total']).to eq(commit_count)
+ end
- it 'include correct pagination headers' do
- path = 'files/ruby/popen.rb'
- commit_count = project.repository.count_commits(ref: 'master', path: path).to_s
+ it 'include correct pagination headers' do
+ path = 'files/ruby/popen.rb'
+ commit_count = project.repository.count_commits(ref: 'master', path: path).to_s
- get api("/projects/#{project_id}/repository/commits?path=#{path}", user)
+ get api("/projects/#{project_id}/repository/commits?path=#{path}", user)
- expect(response).to include_pagination_headers
- expect(response.headers['X-Total']).to eq(commit_count)
- expect(response.headers['X-Page']).to eql('1')
+ expect(response).to include_pagination_headers
+ expect(response.headers['X-Total']).to eq(commit_count)
+ expect(response.headers['X-Page']).to eql('1')
+ end
end
- end
- context 'with pagination params' do
- let(:page) { 1 }
- let(:per_page) { 5 }
- let(:ref_name) { 'master' }
- let!(:request) do
- get api("/projects/#{project_id}/repository/commits?page=#{page}&per_page=#{per_page}&ref_name=#{ref_name}", user)
- end
+ context 'with pagination params' do
+ let(:page) { 1 }
+ let(:per_page) { 5 }
+ let(:ref_name) { 'master' }
+ let!(:request) do
+ get api("/projects/#{project_id}/repository/commits?page=#{page}&per_page=#{per_page}&ref_name=#{ref_name}", user)
+ end
- it 'returns correct headers' do
- commit_count = project.repository.count_commits(ref: ref_name).to_s
+ it 'returns correct headers' do
+ commit_count = project.repository.count_commits(ref: ref_name).to_s
- expect(response).to include_pagination_headers
- expect(response.headers['X-Total']).to eq(commit_count)
- expect(response.headers['X-Page']).to eq('1')
- expect(response.headers['Link']).to match(/page=1&per_page=5/)
- expect(response.headers['Link']).to match(/page=2&per_page=5/)
- end
+ expect(response).to include_pagination_headers
+ expect(response.headers['X-Total']).to eq(commit_count)
+ expect(response.headers['X-Page']).to eq('1')
+ expect(response.headers['Link']).to match(/page=1&per_page=5/)
+ expect(response.headers['Link']).to match(/page=2&per_page=5/)
+ end
- context 'viewing the first page' do
- it 'returns the first 5 commits' do
- commit = project.repository.commit
+ context 'viewing the first page' do
+ it 'returns the first 5 commits' do
+ commit = project.repository.commit
- expect(json_response.size).to eq(per_page)
- expect(json_response.first['id']).to eq(commit.id)
- expect(response.headers['X-Page']).to eq('1')
+ expect(json_response.size).to eq(per_page)
+ expect(json_response.first['id']).to eq(commit.id)
+ expect(response.headers['X-Page']).to eq('1')
+ end
end
- end
- context 'viewing the third page' do
- let(:page) { 3 }
+ context 'viewing the third page' do
+ let(:page) { 3 }
- it 'returns the third 5 commits' do
- commit = project.repository.commits('HEAD', offset: (page - 1) * per_page).first
+ it 'returns the third 5 commits' do
+ commit = project.repository.commits('HEAD', offset: (page - 1) * per_page).first
- expect(json_response.size).to eq(per_page)
- expect(json_response.first['id']).to eq(commit.id)
- expect(response.headers['X-Page']).to eq('3')
+ expect(json_response.size).to eq(per_page)
+ expect(json_response.first['id']).to eq(commit.id)
+ expect(response.headers['X-Page']).to eq('3')
+ end
end
end
end
diff --git a/spec/requests/api/protected_branches_spec.rb b/spec/requests/api/protected_branches_spec.rb
index e4f9c47fb33..1aa8a95780e 100644
--- a/spec/requests/api/protected_branches_spec.rb
+++ b/spec/requests/api/protected_branches_spec.rb
@@ -96,7 +96,7 @@ describe API::ProtectedBranches do
describe 'POST /projects/:id/protected_branches' do
let(:branch_name) { 'new_branch' }
- context 'when authenticated as a master' do
+ context 'when authenticated as a master' do
before do
project.add_master(user)
end
@@ -221,7 +221,7 @@ describe API::ProtectedBranches do
context 'when branch has a wildcard in its name' do
let(:protected_name) { 'feature*' }
-
+
it "unprotects a wildcard branch" do
delete api("/projects/#{project.id}/protected_branches/#{branch_name}", user)
diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb
index 97275b80d03..737c028ad53 100644
--- a/spec/requests/api/settings_spec.rb
+++ b/spec/requests/api/settings_spec.rb
@@ -45,7 +45,7 @@ describe API::Settings, 'Settings' do
help_page_hide_commercial_content: true,
help_page_support_url: 'http://example.com/help',
project_export_enabled: false
-
+
expect(response).to have_http_status(200)
expect(json_response['default_projects_limit']).to eq(3)
expect(json_response['password_authentication_enabled']).to be_falsey
diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb
index ebd67eb1e94..7ccba4ba3ec 100644
--- a/spec/requests/ci/api/builds_spec.rb
+++ b/spec/requests/ci/api/builds_spec.rb
@@ -130,7 +130,7 @@ describe Ci::API::Builds do
register_builds info: { platform: :darwin }
expect(response).to have_http_status(201)
-
+
expect(json_response["options"]).to be_empty
end
end
diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb
index 8fef480274d..a1f3bec42cc 100644
--- a/spec/services/merge_requests/create_service_spec.rb
+++ b/spec/services/merge_requests/create_service_spec.rb
@@ -48,6 +48,16 @@ describe MergeRequests::CreateService do
expect(Todo.where(attributes).count).to be_zero
end
+ it 'creates exactly 1 create MR event' do
+ attributes = {
+ action: Event::CREATED,
+ target_id: @merge_request.id,
+ target_type: @merge_request.class.name
+ }
+
+ expect(Event.where(attributes).count).to eq(1)
+ end
+
context 'when merge request is assigned to someone' do
let(:opts) do
{
diff --git a/spec/services/web_hook_service_spec.rb b/spec/services/web_hook_service_spec.rb
index 365cb6b8f09..0726e135b20 100644
--- a/spec/services/web_hook_service_spec.rb
+++ b/spec/services/web_hook_service_spec.rb
@@ -144,7 +144,7 @@ describe WebHookService do
describe '#async_execute' do
let(:system_hook) { create(:system_hook) }
-
+
it 'enqueue WebHookWorker' do
expect(Sidekiq::Client).to receive(:enqueue).with(WebHookWorker, project_hook.id, data, 'push_hooks')
diff --git a/spec/support/filtered_search_helpers.rb b/spec/support/filtered_search_helpers.rb
index d21c4324d9e..99b8b6b7ea4 100644
--- a/spec/support/filtered_search_helpers.rb
+++ b/spec/support/filtered_search_helpers.rb
@@ -54,8 +54,8 @@ module FilteredSearchHelpers
# Iterates through each visual token inside
# .tokens-container to make sure the correct names and values are rendered
def expect_tokens(tokens)
- page.find '.filtered-search-box .tokens-container' do
- page.all(:css, '.tokens-container li').each_with_index do |el, index|
+ page.within '.filtered-search-box .tokens-container' do
+ page.all(:css, '.tokens-container li .selectable').each_with_index do |el, index|
token_name = tokens[index][:name]
token_value = tokens[index][:value]
@@ -67,6 +67,28 @@ module FilteredSearchHelpers
end
end
+ def create_token(token_name, token_value = nil, symbol = nil)
+ { name: token_name, value: "#{symbol}#{token_value}" }
+ end
+
+ def author_token(author_name = nil)
+ create_token('Author', author_name)
+ end
+
+ def assignee_token(assignee_name = nil)
+ create_token('Assignee', assignee_name)
+ end
+
+ def milestone_token(milestone_name = nil, has_symbol = true)
+ symbol = has_symbol ? '%' : nil
+ create_token('Milestone', milestone_name, symbol)
+ end
+
+ def label_token(label_name = nil, has_symbol = true)
+ symbol = has_symbol ? '~' : nil
+ create_token('Label', label_name, symbol)
+ end
+
def default_placeholder
'Search or filter results...'
end
diff --git a/spec/support/generate-seed-repo-rb b/spec/support/generate-seed-repo-rb
index c89389b90ca..ef3c8e7087f 100755
--- a/spec/support/generate-seed-repo-rb
+++ b/spec/support/generate-seed-repo-rb
@@ -1,16 +1,16 @@
#!/usr/bin/env ruby
-#
+#
# # generate-seed-repo-rb
-#
+#
# This script generates the seed_repo.rb file used by lib/gitlab/git
# tests. The seed_repo.rb file needs to be updated anytime there is a
# Git push to https://gitlab.com/gitlab-org/gitlab-git-test.
-#
+#
# Usage:
-#
+#
# ./spec/support/generate-seed-repo-rb > spec/support/seed_repo.rb
-#
-#
+#
+#
require 'erb'
require 'tempfile'
diff --git a/spec/support/matchers/access_matchers_for_controller.rb b/spec/support/matchers/access_matchers_for_controller.rb
index ff60bd0c0ae..bb6b7c63ee9 100644
--- a/spec/support/matchers/access_matchers_for_controller.rb
+++ b/spec/support/matchers/access_matchers_for_controller.rb
@@ -1,6 +1,6 @@
# AccessMatchersForController
#
-# For testing authorize_xxx in controller.
+# For testing authorize_xxx in controller.
module AccessMatchersForController
extend RSpec::Matchers::DSL
include Warden::Test::Helpers
diff --git a/spec/support/stub_configuration.rb b/spec/support/stub_configuration.rb
index 37c89d37aa0..45c10e78789 100644
--- a/spec/support/stub_configuration.rb
+++ b/spec/support/stub_configuration.rb
@@ -39,14 +39,17 @@ module StubConfiguration
end
def stub_storage_settings(messages)
+ # Default storage is always required
+ messages['default'] ||= Gitlab.config.repositories.storages.default
messages.each do |storage_name, storage_settings|
+ storage_settings['path'] ||= TestEnv.repos_path
storage_settings['failure_count_threshold'] ||= 10
storage_settings['failure_wait_time'] ||= 30
storage_settings['failure_reset_time'] ||= 1800
storage_settings['storage_timeout'] ||= 5
end
- allow(Gitlab.config.repositories).to receive(:storages).and_return(messages)
+ allow(Gitlab.config.repositories).to receive(:storages).and_return(Settingslogic.new(messages))
end
private
diff --git a/spec/tasks/gitlab/gitaly_rake_spec.rb b/spec/tasks/gitlab/gitaly_rake_spec.rb
index b29d63c7d67..1e9b20435ec 100644
--- a/spec/tasks/gitlab/gitaly_rake_spec.rb
+++ b/spec/tasks/gitlab/gitaly_rake_spec.rb
@@ -89,7 +89,7 @@ describe 'gitlab:gitaly namespace rake task' do
it 'calls make in the gitaly directory without BUNDLE_PATH' do
expect(main_object).to receive(:run_command!).with(command_preamble + ['make']).and_return(true)
-
+
run_rake_task('gitlab:gitaly:install', clone_path)
end
end