diff options
209 files changed, 1112 insertions, 546 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5a66e04247e..f7b12e17c70 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -30,7 +30,7 @@ _This notice should stay as the first item in the CONTRIBUTING.md file._ - [Type labels](#type-labels) - [Subject labels](#subject-labels) - [Team labels](#team-labels) - - [Milestone labels](#milestone-labels) + - [Release Scoping labels](#release-scoping-labels) - [Bug Priority labels](#bug-priority-labels) - [Bug Severity labels](#bug-severity-labels) - [Severity impact guidance](#severity-impact-guidance) @@ -133,7 +133,7 @@ Most issues will have labels for at least one of the following: - Type: ~"feature proposal", ~bug, ~customer, etc. - Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc. - Team: ~"CI/CD", ~Discussion, ~Quality, ~Platform, etc. -- Milestone: ~Deliverable, ~Stretch, ~"Next Patch Release" +- Release Scoping: ~Deliverable, ~Stretch, ~"Next Patch Release" - Priority: ~P1, ~P2, ~P3, ~P4 - Severity: ~S1, ~S2, ~S3, ~S4 @@ -207,10 +207,10 @@ indicate if an issue needs backend work, frontend work, or both. Team labels are always capitalized so that they show up as the first label for any issue. -### Milestone labels +### Release Scoping labels -Milestone labels help us clearly communicate expectations of the work for the -release. There are three levels of Milestone labels: +Release Scoping labels help us clearly communicate expectations of the work for the +release. There are three levels of Release Scoping labels: - ~Deliverable: Issues that are expected to be delivered in the current milestone. diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index c64d9d48a48..a9a7f3fec01 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -0.105.1 +0.107.0 @@ -299,7 +299,6 @@ gem 'peek-sidekiq', '~> 1.0.3' # Metrics group :metrics do - gem 'allocations', '~> 1.0', require: false, platform: :mri gem 'method_source', '~> 0.8', require: false gem 'influxdb', '~> 0.2', require: false @@ -419,7 +418,7 @@ group :ed25519 do end # Gitaly GRPC client -gem 'gitaly-proto', '~> 0.101.0', require: 'gitaly' +gem 'gitaly-proto', '~> 0.102.0', require: 'gitaly' gem 'grpc', '~> 1.11.0' # Locked until https://github.com/google/protobuf/issues/4210 is closed diff --git a/Gemfile.lock b/Gemfile.lock index 883e580b86b..3c619b2e534 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -49,7 +49,6 @@ GEM public_suffix (>= 2.0.2, < 4.0) aes_key_wrap (1.0.1) akismet (2.0.0) - allocations (1.0.5) arel (6.0.4) asana (0.6.0) faraday (~> 0.9) @@ -283,7 +282,7 @@ GEM gettext_i18n_rails (>= 0.7.1) po_to_json (>= 1.0.0) rails (>= 3.2.0) - gitaly-proto (0.101.0) + gitaly-proto (0.102.0) google-protobuf (~> 3.1) grpc (~> 1.10) github-linguist (5.3.3) @@ -803,7 +802,7 @@ GEM rubyzip (1.2.1) rufus-scheduler (3.4.0) et-orbi (~> 1.0) - rugged (0.27.1) + rugged (0.27.2) safe_yaml (1.0.4) sanitize (2.1.0) nokogiri (>= 1.4.4) @@ -974,7 +973,6 @@ DEPENDENCIES acts-as-taggable-on (~> 5.0) addressable (~> 2.5.2) akismet (~> 2.0) - allocations (~> 1.0) asana (~> 0.6.0) asciidoctor (~> 1.5.6) asciidoctor-plantuml (= 0.0.8) @@ -1039,7 +1037,7 @@ DEPENDENCIES gettext (~> 3.2.2) gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails_js (~> 1.3) - gitaly-proto (~> 0.101.0) + gitaly-proto (~> 0.102.0) github-linguist (~> 5.3.3) gitlab-flowdock-git-hook (~> 1.0.1) gitlab-gollum-lib (~> 4.2) diff --git a/Gemfile.rails5.lock b/Gemfile.rails5.lock index 223717f1818..679318b9be5 100644 --- a/Gemfile.rails5.lock +++ b/Gemfile.rails5.lock @@ -52,7 +52,6 @@ GEM public_suffix (>= 2.0.2, < 4.0) aes_key_wrap (1.0.1) akismet (2.0.0) - allocations (1.0.5) arel (7.1.4) asana (0.6.0) faraday (~> 0.9) @@ -286,7 +285,7 @@ GEM gettext_i18n_rails (>= 0.7.1) po_to_json (>= 1.0.0) rails (>= 3.2.0) - gitaly-proto (0.101.0) + gitaly-proto (0.102.0) google-protobuf (~> 3.1) grpc (~> 1.10) github-linguist (5.3.3) @@ -984,7 +983,6 @@ DEPENDENCIES acts-as-taggable-on (~> 5.0) addressable (~> 2.5.2) akismet (~> 2.0) - allocations (~> 1.0) asana (~> 0.6.0) asciidoctor (~> 1.5.6) asciidoctor-plantuml (= 0.0.8) @@ -1049,7 +1047,7 @@ DEPENDENCIES gettext (~> 3.2.2) gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails_js (~> 1.3) - gitaly-proto (~> 0.101.0) + gitaly-proto (~> 0.102.0) github-linguist (~> 5.3.3) gitlab-flowdock-git-hook (~> 1.0.1) gitlab-gollum-lib (~> 4.2) diff --git a/app/assets/javascripts/activities.js b/app/assets/javascripts/activities.js index c117d080bda..de4566bb119 100644 --- a/app/assets/javascripts/activities.js +++ b/app/assets/javascripts/activities.js @@ -1,4 +1,4 @@ -/* eslint-disable no-param-reassign, class-methods-use-this */ +/* eslint-disable class-methods-use-this */ import $ from 'jquery'; import Cookies from 'js-cookie'; diff --git a/app/assets/javascripts/autosave.js b/app/assets/javascripts/autosave.js index 0da872db7e5..959e6289502 100644 --- a/app/assets/javascripts/autosave.js +++ b/app/assets/javascripts/autosave.js @@ -1,4 +1,4 @@ -/* eslint-disable no-param-reassign, prefer-template, no-var, no-void, consistent-return */ +/* eslint-disable no-param-reassign, prefer-template, no-void, consistent-return */ import AccessorUtilities from './lib/utils/accessor'; diff --git a/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js b/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js index 1ea6dd909e9..9745e37acce 100644 --- a/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js +++ b/app/assets/javascripts/behaviors/markdown/copy_as_gfm.js @@ -1,4 +1,4 @@ -/* eslint-disable class-methods-use-this, object-shorthand, no-unused-vars, no-use-before-define, no-new, max-len, no-restricted-syntax, guard-for-in, no-continue */ +/* eslint-disable object-shorthand, no-unused-vars, no-use-before-define, max-len, no-restricted-syntax, guard-for-in, no-continue */ import $ from 'jquery'; import _ from 'underscore'; diff --git a/app/assets/javascripts/blob/pdf/index.js b/app/assets/javascripts/blob/pdf/index.js index 70136cc4087..7d5f487c4ba 100644 --- a/app/assets/javascripts/blob/pdf/index.js +++ b/app/assets/javascripts/blob/pdf/index.js @@ -1,4 +1,3 @@ -/* eslint-disable no-new */ import Vue from 'vue'; import pdfLab from '../../pdf/index.vue'; diff --git a/app/assets/javascripts/blob_edit/blob_bundle.js b/app/assets/javascripts/blob_edit/blob_bundle.js index 4424232f642..a603d89b84a 100644 --- a/app/assets/javascripts/blob_edit/blob_bundle.js +++ b/app/assets/javascripts/blob_edit/blob_bundle.js @@ -1,5 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, prefer-arrow-callback, no-var, quotes, vars-on-top, no-unused-vars, no-new, max-len */ -/* global EditBlob */ +/* eslint-disable no-new */ import $ from 'jquery'; import NewCommitForm from '../new_commit_form'; diff --git a/app/assets/javascripts/boards/components/board.js b/app/assets/javascripts/boards/components/board.js index 7920e08e4d8..a2355d7fd5c 100644 --- a/app/assets/javascripts/boards/components/board.js +++ b/app/assets/javascripts/boards/components/board.js @@ -1,4 +1,4 @@ -/* eslint-disable comma-dangle, space-before-function-paren, one-var */ +/* eslint-disable comma-dangle */ import Sortable from 'sortablejs'; import Vue from 'vue'; diff --git a/app/assets/javascripts/boards/components/board_delete.js b/app/assets/javascripts/boards/components/board_delete.js index 4dd9aebeed9..c5945e8098d 100644 --- a/app/assets/javascripts/boards/components/board_delete.js +++ b/app/assets/javascripts/boards/components/board_delete.js @@ -1,4 +1,4 @@ -/* eslint-disable comma-dangle, space-before-function-paren, no-alert */ +/* eslint-disable comma-dangle, no-alert */ import $ from 'jquery'; import Vue from 'vue'; diff --git a/app/assets/javascripts/boards/components/board_sidebar.js b/app/assets/javascripts/boards/components/board_sidebar.js index 82fe6b0c5fb..b717c4b0fd4 100644 --- a/app/assets/javascripts/boards/components/board_sidebar.js +++ b/app/assets/javascripts/boards/components/board_sidebar.js @@ -1,4 +1,4 @@ -/* eslint-disable comma-dangle, space-before-function-paren, no-new */ +/* eslint-disable comma-dangle, no-new */ import $ from 'jquery'; import Vue from 'vue'; diff --git a/app/assets/javascripts/boards/components/new_list_dropdown.js b/app/assets/javascripts/boards/components/new_list_dropdown.js index 6dcd4aaec43..448ab9ed135 100644 --- a/app/assets/javascripts/boards/components/new_list_dropdown.js +++ b/app/assets/javascripts/boards/components/new_list_dropdown.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, no-new, space-before-function-paren, one-var, promise/catch-or-return, max-len */ +/* eslint-disable func-names, no-new, promise/catch-or-return */ import $ from 'jquery'; import axios from '~/lib/utils/axios_utils'; diff --git a/app/assets/javascripts/boards/filtered_search_boards.js b/app/assets/javascripts/boards/filtered_search_boards.js index 70367c4f711..46d61ebbf24 100644 --- a/app/assets/javascripts/boards/filtered_search_boards.js +++ b/app/assets/javascripts/boards/filtered_search_boards.js @@ -1,4 +1,3 @@ -/* eslint-disable class-methods-use-this */ import FilteredSearchContainer from '../filtered_search/container'; import FilteredSearchManager from '../filtered_search/filtered_search_manager'; diff --git a/app/assets/javascripts/boards/index.js b/app/assets/javascripts/boards/index.js index cdad8d238e3..2d9141bf71c 100644 --- a/app/assets/javascripts/boards/index.js +++ b/app/assets/javascripts/boards/index.js @@ -1,4 +1,4 @@ -/* eslint-disable one-var, quote-props, comma-dangle, space-before-function-paren */ +/* eslint-disable quote-props, comma-dangle */ import $ from 'jquery'; import _ from 'underscore'; diff --git a/app/assets/javascripts/boards/mixins/sortable_default_options.js b/app/assets/javascripts/boards/mixins/sortable_default_options.js index ac316c31deb..a8df45fc473 100644 --- a/app/assets/javascripts/boards/mixins/sortable_default_options.js +++ b/app/assets/javascripts/boards/mixins/sortable_default_options.js @@ -1,4 +1,3 @@ -/* eslint-disable no-unused-vars, no-mixed-operators, comma-dangle */ /* global DocumentTouch */ import $ from 'jquery'; diff --git a/app/assets/javascripts/boards/models/issue.js b/app/assets/javascripts/boards/models/issue.js index b381d48d625..b85266b6bc3 100644 --- a/app/assets/javascripts/boards/models/issue.js +++ b/app/assets/javascripts/boards/models/issue.js @@ -1,4 +1,4 @@ -/* eslint-disable no-unused-vars, space-before-function-paren, arrow-body-style, arrow-parens, comma-dangle, max-len */ +/* eslint-disable no-unused-vars, comma-dangle */ /* global ListLabel */ /* global ListMilestone */ /* global ListAssignee */ diff --git a/app/assets/javascripts/boards/models/list.js b/app/assets/javascripts/boards/models/list.js index 1f0fe7f9e85..e35f277a865 100644 --- a/app/assets/javascripts/boards/models/list.js +++ b/app/assets/javascripts/boards/models/list.js @@ -1,4 +1,4 @@ -/* eslint-disable space-before-function-paren, no-underscore-dangle, class-methods-use-this, consistent-return, no-shadow, no-param-reassign, max-len, no-unused-vars */ +/* eslint-disable no-underscore-dangle, class-methods-use-this, consistent-return, no-shadow, no-param-reassign, max-len */ /* global ListIssue */ import ListLabel from '~/vue_shared/models/label'; diff --git a/app/assets/javascripts/boards/models/milestone.js b/app/assets/javascripts/boards/models/milestone.js index c867b06d320..17d15278a74 100644 --- a/app/assets/javascripts/boards/models/milestone.js +++ b/app/assets/javascripts/boards/models/milestone.js @@ -1,5 +1,3 @@ -/* eslint-disable no-unused-vars */ - class ListMilestone { constructor(obj) { this.id = obj.id; diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js index ffe86468b12..333338489bc 100644 --- a/app/assets/javascripts/boards/stores/boards_store.js +++ b/app/assets/javascripts/boards/stores/boards_store.js @@ -1,4 +1,4 @@ -/* eslint-disable comma-dangle, space-before-function-paren, one-var, no-shadow, dot-notation, max-len */ +/* eslint-disable comma-dangle, no-shadow */ /* global List */ import $ from 'jquery'; diff --git a/app/assets/javascripts/build_artifacts.js b/app/assets/javascripts/build_artifacts.js index 3fa16517388..e338376fcaa 100644 --- a/app/assets/javascripts/build_artifacts.js +++ b/app/assets/javascripts/build_artifacts.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, prefer-arrow-callback, no-return-assign */ +/* eslint-disable func-names, prefer-arrow-callback */ import $ from 'jquery'; import { visitUrl } from './lib/utils/url_utility'; diff --git a/app/assets/javascripts/commit/image_file.js b/app/assets/javascripts/commit/image_file.js index 7f3d04655a7..2d180e9903a 100644 --- a/app/assets/javascripts/commit/image_file.js +++ b/app/assets/javascripts/commit/image_file.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, no-use-before-define, prefer-arrow-callback, no-else-return, consistent-return, prefer-template, quotes, one-var, one-var-declaration-per-line, no-unused-vars, no-return-assign, comma-dangle, quote-props, no-unused-expressions, no-sequences, object-shorthand, max-len */ +/* eslint-disable func-names, wrap-iife, no-var, prefer-arrow-callback, no-else-return, consistent-return, prefer-template, quotes, one-var, one-var-declaration-per-line, no-unused-vars, no-return-assign, comma-dangle, quote-props, no-unused-expressions, no-sequences, max-len */ import $ from 'jquery'; @@ -95,7 +95,7 @@ export default class ImageFile { }); return [maxWidth, maxHeight]; } - // eslint-disable-next-line + views = { 'two-up': function() { return $('.two-up.view .wrap', this.file).each((function(_this) { diff --git a/app/assets/javascripts/compare_autocomplete.js b/app/assets/javascripts/compare_autocomplete.js index ffe15f02f2e..a252036d657 100644 --- a/app/assets/javascripts/compare_autocomplete.js +++ b/app/assets/javascripts/compare_autocomplete.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, one-var, no-var, one-var-declaration-per-line, object-shorthand, comma-dangle, prefer-arrow-callback, no-else-return, newline-per-chained-call, wrap-iife, max-len */ +/* eslint-disable func-names, one-var, no-var, one-var-declaration-per-line, object-shorthand, no-else-return, max-len */ import $ from 'jquery'; import { __ } from './locale'; diff --git a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js index 2ce4b050763..66b20cc8739 100644 --- a/app/assets/javascripts/diff_notes/components/jump_to_discussion.js +++ b/app/assets/javascripts/diff_notes/components/jump_to_discussion.js @@ -1,11 +1,10 @@ -/* eslint-disable comma-dangle, object-shorthand, func-names, no-else-return, guard-for-in, no-restricted-syntax, one-var, space-before-function-paren, no-lonely-if, no-continue, brace-style, max-len, quotes */ -/* global DiscussionMixins */ +/* eslint-disable comma-dangle, object-shorthand, func-names, no-else-return, guard-for-in, no-restricted-syntax, no-lonely-if, no-continue, brace-style, max-len, quotes */ /* global CommentsStore */ import $ from 'jquery'; import Vue from 'vue'; -import '../mixins/discussion'; +import DiscussionMixins from '../mixins/discussion'; const JumpToDiscussion = Vue.extend({ mixins: [DiscussionMixins], diff --git a/app/assets/javascripts/diff_notes/components/resolve_count.js b/app/assets/javascripts/diff_notes/components/resolve_count.js index 9f613410e81..e2683e09f40 100644 --- a/app/assets/javascripts/diff_notes/components/resolve_count.js +++ b/app/assets/javascripts/diff_notes/components/resolve_count.js @@ -1,10 +1,9 @@ -/* eslint-disable comma-dangle, object-shorthand, func-names, no-param-reassign */ -/* global DiscussionMixins */ +/* eslint-disable comma-dangle, object-shorthand, func-names */ /* global CommentsStore */ import Vue from 'vue'; -import '../mixins/discussion'; +import DiscussionMixins from '../mixins/discussion'; window.ResolveCount = Vue.extend({ mixins: [DiscussionMixins], diff --git a/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js b/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js index 210a00c5fc2..5ed13488788 100644 --- a/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js +++ b/app/assets/javascripts/diff_notes/components/resolve_discussion_btn.js @@ -1,4 +1,4 @@ -/* eslint-disable object-shorthand, func-names, space-before-function-paren, comma-dangle, no-else-return, quotes, max-len */ +/* eslint-disable object-shorthand, func-names, comma-dangle, no-else-return, quotes */ /* global CommentsStore */ /* global ResolveService */ diff --git a/app/assets/javascripts/diff_notes/diff_notes_bundle.js b/app/assets/javascripts/diff_notes/diff_notes_bundle.js index d5161ab7df9..18fceac6368 100644 --- a/app/assets/javascripts/diff_notes/diff_notes_bundle.js +++ b/app/assets/javascripts/diff_notes/diff_notes_bundle.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, comma-dangle, new-cap, no-new, max-len */ +/* eslint-disable func-names, comma-dangle, new-cap, no-new */ /* global ResolveCount */ import $ from 'jquery'; diff --git a/app/assets/javascripts/diff_notes/mixins/discussion.js b/app/assets/javascripts/diff_notes/mixins/discussion.js index 36c4abf02cf..ef35b589e58 100644 --- a/app/assets/javascripts/diff_notes/mixins/discussion.js +++ b/app/assets/javascripts/diff_notes/mixins/discussion.js @@ -1,6 +1,6 @@ -/* eslint-disable object-shorthand, func-names, guard-for-in, no-restricted-syntax, comma-dangle, no-param-reassign, max-len */ +/* eslint-disable object-shorthand, func-names, guard-for-in, no-restricted-syntax, comma-dangle, */ -window.DiscussionMixins = { +const DiscussionMixins = { computed: { discussionCount: function () { return Object.keys(this.discussions).length; @@ -33,3 +33,5 @@ window.DiscussionMixins = { } } }; + +export default DiscussionMixins; diff --git a/app/assets/javascripts/diff_notes/models/discussion.js b/app/assets/javascripts/diff_notes/models/discussion.js index c97c559dd14..787e6d8855f 100644 --- a/app/assets/javascripts/diff_notes/models/discussion.js +++ b/app/assets/javascripts/diff_notes/models/discussion.js @@ -1,4 +1,4 @@ -/* eslint-disable space-before-function-paren, camelcase, guard-for-in, no-restricted-syntax, no-unused-vars, max-len */ +/* eslint-disable camelcase, guard-for-in, no-restricted-syntax */ /* global NoteModel */ import $ from 'jquery'; diff --git a/app/assets/javascripts/diff_notes/models/note.js b/app/assets/javascripts/diff_notes/models/note.js index 04465aa507e..825a69deeec 100644 --- a/app/assets/javascripts/diff_notes/models/note.js +++ b/app/assets/javascripts/diff_notes/models/note.js @@ -1,5 +1,3 @@ -/* eslint-disable camelcase, no-unused-vars */ - class NoteModel { constructor(discussionId, noteObj) { this.discussionId = discussionId; diff --git a/app/assets/javascripts/diff_notes/stores/comments.js b/app/assets/javascripts/diff_notes/stores/comments.js index d802db7d3af..d7da7d974f3 100644 --- a/app/assets/javascripts/diff_notes/stores/comments.js +++ b/app/assets/javascripts/diff_notes/stores/comments.js @@ -1,4 +1,4 @@ -/* eslint-disable object-shorthand, func-names, camelcase, no-restricted-syntax, guard-for-in, comma-dangle, max-len, no-param-reassign */ +/* eslint-disable object-shorthand, func-names, camelcase, no-restricted-syntax, guard-for-in, comma-dangle, max-len */ /* global DiscussionModel */ import Vue from 'vue'; diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js index 72f21f13860..b755458aa4b 100644 --- a/app/assets/javascripts/dispatcher.js +++ b/app/assets/javascripts/dispatcher.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, prefer-arrow-callback, wrap-iife, no-shadow, consistent-return, one-var, one-var-declaration-per-line, camelcase, default-case, no-new, quotes, no-duplicate-case, no-case-declarations, no-fallthrough, max-len */ +/* eslint-disable consistent-return, no-new */ import $ from 'jquery'; import Flash from './flash'; diff --git a/app/assets/javascripts/gl_dropdown.js b/app/assets/javascripts/gl_dropdown.js index 7fbba7e27cb..45889c2d604 100644 --- a/app/assets/javascripts/gl_dropdown.js +++ b/app/assets/javascripts/gl_dropdown.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, no-underscore-dangle, space-before-function-paren, no-var, one-var, one-var-declaration-per-line, prefer-rest-params, max-len, vars-on-top, wrap-iife, no-unused-vars, quotes, no-shadow, no-cond-assign, prefer-arrow-callback, no-return-assign, no-else-return, camelcase, comma-dangle, no-lonely-if, guard-for-in, no-restricted-syntax, consistent-return, prefer-template, no-param-reassign, no-loop-func, no-mixed-operators */ +/* eslint-disable func-names, no-underscore-dangle, no-var, one-var, one-var-declaration-per-line, max-len, vars-on-top, wrap-iife, no-unused-vars, quotes, no-shadow, no-cond-assign, prefer-arrow-callback, no-return-assign, no-else-return, camelcase, comma-dangle, no-lonely-if, guard-for-in, no-restricted-syntax, consistent-return, prefer-template, no-param-reassign, no-loop-func */ /* global fuzzaldrinPlus */ import $ from 'jquery'; diff --git a/app/assets/javascripts/groups/components/app.vue b/app/assets/javascripts/groups/components/app.vue index 1def38bb336..b0765747a36 100644 --- a/app/assets/javascripts/groups/components/app.vue +++ b/app/assets/javascripts/groups/components/app.vue @@ -148,7 +148,6 @@ export default { if (!parentGroup.isOpen) { if (parentGroup.children.length === 0) { parentGroup.isChildrenLoading = true; - // eslint-disable-next-line promise/catch-or-return this.fetchGroups({ parentId: parentGroup.id, }) diff --git a/app/assets/javascripts/ide/components/commit_sidebar/form.vue b/app/assets/javascripts/ide/components/commit_sidebar/form.vue index 955d9280728..14c74687ab4 100644 --- a/app/assets/javascripts/ide/components/commit_sidebar/form.vue +++ b/app/assets/javascripts/ide/components/commit_sidebar/form.vue @@ -117,7 +117,7 @@ export default { class="btn btn-primary btn-sm btn-block" @click="toggleIsSmall" > - {{ __('Commit') }} + {{ __('Commit…') }} </button> <p class="text-center" diff --git a/app/assets/javascripts/integrations/integration_settings_form.js b/app/assets/javascripts/integrations/integration_settings_form.js index cdb75752b4e..bd90d0eaa32 100644 --- a/app/assets/javascripts/integrations/integration_settings_form.js +++ b/app/assets/javascripts/integrations/integration_settings_form.js @@ -91,7 +91,6 @@ export default class IntegrationSettingsForm { } } - /* eslint-disable promise/catch-or-return, no-new */ /** * Test Integration config */ diff --git a/app/assets/javascripts/issuable_bulk_update_actions.js b/app/assets/javascripts/issuable_bulk_update_actions.js index e003fb1d127..35eaf21a836 100644 --- a/app/assets/javascripts/issuable_bulk_update_actions.js +++ b/app/assets/javascripts/issuable_bulk_update_actions.js @@ -1,4 +1,4 @@ -/* eslint-disable comma-dangle, quotes, consistent-return, func-names, array-callback-return, space-before-function-paren, prefer-arrow-callback, max-len, no-unused-expressions, no-sequences, no-underscore-dangle, no-unused-vars, no-param-reassign */ +/* eslint-disable comma-dangle, quotes, consistent-return, func-names, array-callback-return, prefer-arrow-callback, max-len, no-unused-vars */ import $ from 'jquery'; import _ from 'underscore'; diff --git a/app/assets/javascripts/issuable_form.js b/app/assets/javascripts/issuable_form.js index bb8b3d91e40..0140960b367 100644 --- a/app/assets/javascripts/issuable_form.js +++ b/app/assets/javascripts/issuable_form.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, prefer-rest-params, wrap-iife, no-use-before-define, no-useless-escape, no-new, object-shorthand, no-unused-vars, comma-dangle, no-alert, consistent-return, no-else-return, prefer-template, one-var, one-var-declaration-per-line, curly, max-len */ +/* eslint-disable no-new, no-unused-vars, consistent-return, no-else-return */ /* global GitLab */ import $ from 'jquery'; diff --git a/app/assets/javascripts/issue.js b/app/assets/javascripts/issue.js index 5113ac6775d..8c225cd7d91 100644 --- a/app/assets/javascripts/issue.js +++ b/app/assets/javascripts/issue.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, one-var, no-underscore-dangle, one-var-declaration-per-line, object-shorthand, no-unused-vars, no-new, comma-dangle, consistent-return, quotes, dot-notation, quote-props, prefer-arrow-callback, max-len */ +/* eslint-disable no-var, one-var, one-var-declaration-per-line, no-unused-vars, consistent-return, quotes, max-len */ import $ from 'jquery'; import axios from './lib/utils/axios_utils'; diff --git a/app/assets/javascripts/label_manager.js b/app/assets/javascripts/label_manager.js index 8b01024b7d4..c10b1a2b233 100644 --- a/app/assets/javascripts/label_manager.js +++ b/app/assets/javascripts/label_manager.js @@ -1,4 +1,4 @@ -/* eslint-disable comma-dangle, class-methods-use-this, no-underscore-dangle, no-param-reassign, no-unused-vars, consistent-return, func-names, space-before-function-paren, max-len */ +/* eslint-disable class-methods-use-this, no-underscore-dangle, no-param-reassign, no-unused-vars, func-names, max-len */ import $ from 'jquery'; import Sortable from 'sortablejs'; diff --git a/app/assets/javascripts/labels_select.js b/app/assets/javascripts/labels_select.js index 7d0ff53f366..dfc3f7a94c8 100644 --- a/app/assets/javascripts/labels_select.js +++ b/app/assets/javascripts/labels_select.js @@ -1,4 +1,4 @@ -/* eslint-disable no-useless-return, func-names, space-before-function-paren, wrap-iife, no-var, no-underscore-dangle, prefer-arrow-callback, max-len, one-var, no-unused-vars, one-var-declaration-per-line, prefer-template, no-new, consistent-return, object-shorthand, comma-dangle, no-shadow, no-param-reassign, brace-style, vars-on-top, quotes, no-lonely-if, no-else-return, dot-notation, no-empty, no-return-assign, camelcase, prefer-spread */ +/* eslint-disable no-useless-return, func-names, no-var, no-underscore-dangle, prefer-arrow-callback, max-len, one-var, no-unused-vars, one-var-declaration-per-line, prefer-template, no-new, consistent-return, object-shorthand, comma-dangle, no-shadow, no-param-reassign, brace-style, vars-on-top, quotes, no-lonely-if, no-else-return, dot-notation, no-empty */ /* global Issuable */ /* global ListLabel */ diff --git a/app/assets/javascripts/lib/utils/notify.js b/app/assets/javascripts/lib/utils/notify.js index 973d6119158..305ad3e5e26 100644 --- a/app/assets/javascripts/lib/utils/notify.js +++ b/app/assets/javascripts/lib/utils/notify.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, one-var, one-var-declaration-per-line, consistent-return, prefer-arrow-callback, no-return-assign, object-shorthand, comma-dangle, no-param-reassign, max-len */ +/* eslint-disable func-names, no-var, consistent-return, prefer-arrow-callback, no-return-assign, object-shorthand, comma-dangle, max-len */ function notificationGranted(message, opts, onclick) { var notification; diff --git a/app/assets/javascripts/lib/utils/text_markdown.js b/app/assets/javascripts/lib/utils/text_markdown.js index 5a16adea4dc..ce0bc4d40e9 100644 --- a/app/assets/javascripts/lib/utils/text_markdown.js +++ b/app/assets/javascripts/lib/utils/text_markdown.js @@ -1,4 +1,4 @@ -/* eslint-disable import/prefer-default-export, func-names, space-before-function-paren, wrap-iife, no-var, no-param-reassign, no-cond-assign, quotes, one-var, one-var-declaration-per-line, operator-assignment, no-else-return, prefer-template, prefer-arrow-callback, no-empty, max-len, consistent-return, no-unused-vars, no-return-assign, max-len, vars-on-top */ +/* eslint-disable func-names, no-var, no-param-reassign, quotes, one-var, one-var-declaration-per-line, operator-assignment, no-else-return, prefer-template, prefer-arrow-callback, max-len, consistent-return, no-unused-vars, max-len */ import $ from 'jquery'; import { insertText } from '~/lib/utils/common_utils'; diff --git a/app/assets/javascripts/line_highlighter.js b/app/assets/javascripts/line_highlighter.js index 303c5d8a894..815b13f7bf5 100644 --- a/app/assets/javascripts/line_highlighter.js +++ b/app/assets/javascripts/line_highlighter.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, no-use-before-define, no-underscore-dangle, no-param-reassign, prefer-template, quotes, comma-dangle, prefer-arrow-callback, consistent-return, one-var, one-var-declaration-per-line, no-else-return, max-len */ +/* eslint-disable func-names, no-var, no-underscore-dangle, no-param-reassign, prefer-template, quotes, comma-dangle, consistent-return, one-var, one-var-declaration-per-line, no-else-return, max-len */ import $ from 'jquery'; diff --git a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js index e4ed8111824..81950515ab4 100644 --- a/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js +++ b/app/assets/javascripts/merge_conflicts/components/diff_file_editor.js @@ -1,4 +1,4 @@ -/* eslint-disable comma-dangle, quote-props, no-useless-computed-key, object-shorthand, no-new, no-param-reassign, max-len */ +/* eslint-disable comma-dangle, quote-props, no-useless-computed-key, object-shorthand, no-param-reassign, max-len */ /* global ace */ import Vue from 'vue'; diff --git a/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js b/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js index 57e73e38d88..69208ac2d36 100644 --- a/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js +++ b/app/assets/javascripts/merge_conflicts/components/parallel_conflict_lines.js @@ -1,4 +1,4 @@ -/* eslint-disable no-param-reassign, comma-dangle */ +/* eslint-disable no-param-reassign */ import Vue from 'vue'; import actionsMixin from '../mixins/line_conflict_actions'; diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js index d8222ebec63..83decc1d298 100644 --- a/app/assets/javascripts/merge_request.js +++ b/app/assets/javascripts/merge_request.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, quotes, no-underscore-dangle, one-var, one-var-declaration-per-line, consistent-return, dot-notation, quote-props, comma-dangle, object-shorthand, max-len, prefer-arrow-callback */ +/* eslint-disable func-names, no-var, wrap-iife, quotes, no-underscore-dangle, one-var, one-var-declaration-per-line, consistent-return, comma-dangle, max-len, prefer-arrow-callback */ import $ from 'jquery'; import { __ } from '~/locale'; diff --git a/app/assets/javascripts/milestone_select.js b/app/assets/javascripts/milestone_select.js index 334279137d8..77acba6e355 100644 --- a/app/assets/javascripts/milestone_select.js +++ b/app/assets/javascripts/milestone_select.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-underscore-dangle, prefer-arrow-callback, max-len, one-var, one-var-declaration-per-line, no-unused-vars, object-shorthand, comma-dangle, no-else-return, no-self-compare, consistent-return, no-param-reassign, no-shadow */ +/* eslint-disable max-len, one-var, one-var-declaration-per-line, no-unused-vars, object-shorthand, no-else-return, no-self-compare, consistent-return, no-param-reassign, no-shadow */ /* global Issuable */ /* global ListMilestone */ diff --git a/app/assets/javascripts/namespace_select.js b/app/assets/javascripts/namespace_select.js index c7a8aac79df..17370edeb0c 100644 --- a/app/assets/javascripts/namespace_select.js +++ b/app/assets/javascripts/namespace_select.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, comma-dangle, object-shorthand, no-else-return, prefer-template, quotes, prefer-arrow-callback, max-len */ +/* eslint-disable func-names, comma-dangle, object-shorthand, no-else-return, prefer-template, quotes, prefer-arrow-callback, max-len */ import $ from 'jquery'; import Api from './api'; diff --git a/app/assets/javascripts/network/branch_graph.js b/app/assets/javascripts/network/branch_graph.js index e4096ddb00d..7787849f7a8 100644 --- a/app/assets/javascripts/network/branch_graph.js +++ b/app/assets/javascripts/network/branch_graph.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, wrap-iife, quotes, comma-dangle, one-var, one-var-declaration-per-line, no-mixed-operators, no-loop-func, no-floating-decimal, consistent-return, no-unused-vars, prefer-template, prefer-arrow-callback, camelcase, max-len */ +/* eslint-disable func-names, no-var, wrap-iife, quotes, comma-dangle, one-var, one-var-declaration-per-line, no-loop-func, no-floating-decimal, consistent-return, no-unused-vars, prefer-template, prefer-arrow-callback, camelcase, max-len */ import $ from 'jquery'; import { __ } from '../locale'; diff --git a/app/assets/javascripts/new_branch_form.js b/app/assets/javascripts/new_branch_form.js index 40c08ee0ace..41ba5b28a1b 100644 --- a/app/assets/javascripts/new_branch_form.js +++ b/app/assets/javascripts/new_branch_form.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, one-var, prefer-rest-params, max-len, vars-on-top, wrap-iife, consistent-return, comma-dangle, one-var-declaration-per-line, quotes, no-return-assign, prefer-arrow-callback, prefer-template, no-shadow, no-else-return, max-len, object-shorthand */ +/* eslint-disable func-names, no-var, one-var, max-len, wrap-iife, consistent-return, comma-dangle, one-var-declaration-per-line, quotes, no-return-assign, prefer-arrow-callback, prefer-template, no-shadow, no-else-return, max-len */ import $ from 'jquery'; import RefSelectDropdown from './ref_select_dropdown'; diff --git a/app/assets/javascripts/new_commit_form.js b/app/assets/javascripts/new_commit_form.js index a2f0a44863f..17ec20f1cc1 100644 --- a/app/assets/javascripts/new_commit_form.js +++ b/app/assets/javascripts/new_commit_form.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, no-return-assign, max-len */ +/* eslint-disable no-var, no-return-assign */ export default class NewCommitForm { constructor(form) { this.form = form; diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js index 27c5dedcf0b..d23939c00e1 100644 --- a/app/assets/javascripts/notes.js +++ b/app/assets/javascripts/notes.js @@ -1,10 +1,8 @@ -/* eslint-disable no-restricted-properties, func-names, space-before-function-paren, -no-var, prefer-rest-params, wrap-iife, no-use-before-define, camelcase, -no-unused-expressions, quotes, max-len, one-var, one-var-declaration-per-line, -default-case, prefer-template, consistent-return, no-alert, no-return-assign, -no-param-reassign, prefer-arrow-callback, no-else-return, comma-dangle, no-new, -brace-style, no-lonely-if, vars-on-top, no-unused-vars, no-sequences, no-shadow, -newline-per-chained-call, no-useless-escape, class-methods-use-this */ +/* eslint-disable no-restricted-properties, func-names, no-var, wrap-iife, camelcase, +no-unused-expressions, max-len, one-var, one-var-declaration-per-line, default-case, +prefer-template, consistent-return, no-alert, no-return-assign, +no-param-reassign, prefer-arrow-callback, no-else-return, vars-on-top, +no-unused-vars, no-shadow, no-useless-escape, class-methods-use-this */ /* global ResolveService */ /* global mrRefreshWidgetUrl */ @@ -784,6 +782,7 @@ export default class Notes { } updateNoteError($parentTimeline) { + // eslint-disable-next-line no-new new Flash( 'Your comment could not be updated! Please check your network connection and try again.', ); @@ -1411,8 +1410,8 @@ export default class Notes { static renderPlaceholderComponent($container) { const el = $container.find('.js-code-placeholder').get(0); + // eslint-disable-next-line no-new new Vue({ - // eslint-disable-line no-new el, components: { SkeletonLoadingContainer, @@ -1827,7 +1826,6 @@ export default class Notes { $closeBtn.text($closeBtn.data('originalText')); - /* eslint-disable promise/catch-or-return */ // Make request to submit comment on server return axios .post(`${formAction}?html=true`, formData) @@ -1989,7 +1987,6 @@ export default class Notes { '<i class="fa fa-spinner fa-spin" aria-label="Comment is being updated" aria-hidden="true"></i>', ); - /* eslint-disable promise/catch-or-return */ // Make request to update comment on server axios .post(`${formAction}?html=true`, formData) diff --git a/app/assets/javascripts/pages/dashboard/todos/index/todos.js b/app/assets/javascripts/pages/dashboard/todos/index/todos.js index c334eaa90f8..6fc43af2623 100644 --- a/app/assets/javascripts/pages/dashboard/todos/index/todos.js +++ b/app/assets/javascripts/pages/dashboard/todos/index/todos.js @@ -1,4 +1,4 @@ -/* eslint-disable class-methods-use-this, no-unneeded-ternary, quote-props */ +/* eslint-disable class-methods-use-this, no-unneeded-ternary */ import $ from 'jquery'; import { visitUrl } from '~/lib/utils/url_utility'; diff --git a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors.js b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors.js index 37336a8cb69..ae72c8cb4d5 100644 --- a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors.js +++ b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, one-var, camelcase, one-var-declaration-per-line, quotes, no-param-reassign, quote-props, comma-dangle, prefer-template, max-len, no-return-assign, no-shadow */ +/* eslint-disable func-names, wrap-iife, no-var, one-var, camelcase, one-var-declaration-per-line, quotes, no-param-reassign, quote-props, comma-dangle, prefer-template, max-len, no-return-assign */ import $ from 'jquery'; import _ from 'underscore'; diff --git a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js index 5316d3e9f3c..a02ec9e5f00 100644 --- a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js +++ b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, prefer-rest-params, max-len, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, comma-dangle, no-return-assign, prefer-arrow-callback, quotes, prefer-template, newline-per-chained-call, no-else-return, no-shadow */ +/* eslint-disable func-names, max-len, no-restricted-syntax, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, comma-dangle, no-return-assign, prefer-arrow-callback, quotes, prefer-template, newline-per-chained-call, no-else-return, no-shadow */ import $ from 'jquery'; import _ from 'underscore'; diff --git a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js index 165446a4db6..d12249bf612 100644 --- a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js +++ b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, object-shorthand, no-var, one-var, camelcase, one-var-declaration-per-line, comma-dangle, no-param-reassign, no-return-assign, quotes, prefer-arrow-callback, wrap-iife, consistent-return, no-unused-vars, max-len, no-cond-assign, no-else-return, max-len */ +/* eslint-disable func-names, object-shorthand, no-var, one-var, camelcase, one-var-declaration-per-line, comma-dangle, no-param-reassign, no-return-assign, quotes, prefer-arrow-callback, wrap-iife, consistent-return, no-unused-vars, max-len, no-cond-assign, no-else-return, max-len */ import _ from 'underscore'; export default { diff --git a/app/assets/javascripts/pages/projects/init_blob.js b/app/assets/javascripts/pages/projects/init_blob.js index 82143fa875a..56ab3fcdfcb 100644 --- a/app/assets/javascripts/pages/projects/init_blob.js +++ b/app/assets/javascripts/pages/projects/init_blob.js @@ -8,7 +8,8 @@ import initBlobBundle from '~/blob_edit/blob_bundle'; export default () => { new LineHighlighter(); // eslint-disable-line no-new - new BlobLinePermalinkUpdater( // eslint-disable-line no-new + // eslint-disable-next-line no-new + new BlobLinePermalinkUpdater( document.querySelector('#blob-content-holder'), '.diff-line-num[data-line-number]', document.querySelectorAll('.js-data-file-blob-permalink-url, .js-blob-blame-link'), @@ -19,12 +20,13 @@ export default () => { new ShortcutsNavigation(); // eslint-disable-line no-new - new ShortcutsBlob({ // eslint-disable-line no-new + // eslint-disable-next-line no-new + new ShortcutsBlob({ skipResetBindings: true, fileBlobPermalinkUrl, }); - new BlobForkSuggestion({ // eslint-disable-line no-new + new BlobForkSuggestion({ openButtons: document.querySelectorAll('.js-edit-blob-link-fork-toggler'), forkButtons: document.querySelectorAll('.js-fork-suggestion-button'), cancelButtons: document.querySelectorAll('.js-cancel-fork-suggestion-button'), diff --git a/app/assets/javascripts/pages/projects/network/network.js b/app/assets/javascripts/pages/projects/network/network.js index aa50dd4bb25..77368c47451 100644 --- a/app/assets/javascripts/pages/projects/network/network.js +++ b/app/assets/javascripts/pages/projects/network/network.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, quotes, quote-props, prefer-template, comma-dangle, max-len */ +/* eslint-disable func-names, wrap-iife, no-var, quotes, quote-props, prefer-template, comma-dangle, max-len */ import $ from 'jquery'; import BranchGraph from '../../../network/branch_graph'; diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js index c1e3425ec75..a853624e944 100644 --- a/app/assets/javascripts/pages/projects/project.js +++ b/app/assets/javascripts/pages/projects/project.js @@ -1,4 +1,5 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, consistent-return, no-new, prefer-arrow-callback, no-return-assign, one-var, one-var-declaration-per-line, object-shorthand, no-else-return, newline-per-chained-call, no-shadow, vars-on-top, prefer-template, max-len */ +/* eslint-disable func-names, no-var, no-return-assign, one-var, + one-var-declaration-per-line, object-shorthand, vars-on-top */ import $ from 'jquery'; import Cookies from 'js-cookie'; diff --git a/app/assets/javascripts/pages/projects/settings/repository/form.js b/app/assets/javascripts/pages/projects/settings/repository/form.js index a5c17ab322c..a52861c9efa 100644 --- a/app/assets/javascripts/pages/projects/settings/repository/form.js +++ b/app/assets/javascripts/pages/projects/settings/repository/form.js @@ -13,7 +13,7 @@ export default () => { new ProtectedTagEditList(); initDeployKeys(); initSettingsPanels(); - new ProtectedBranchCreate(); // eslint-disable-line no-new - new ProtectedBranchEditList(); // eslint-disable-line no-new + new ProtectedBranchCreate(); + new ProtectedBranchEditList(); new DueDateSelectors(); }; diff --git a/app/assets/javascripts/pages/sessions/new/index.js b/app/assets/javascripts/pages/sessions/new/index.js index 80a7114f94d..07f32210d93 100644 --- a/app/assets/javascripts/pages/sessions/new/index.js +++ b/app/assets/javascripts/pages/sessions/new/index.js @@ -6,7 +6,8 @@ import OAuthRememberMe from './oauth_remember_me'; document.addEventListener('DOMContentLoaded', () => { new UsernameValidator(); // eslint-disable-line no-new new SigninTabsMemoizer(); // eslint-disable-line no-new - new OAuthRememberMe({ // eslint-disable-line no-new + + new OAuthRememberMe({ container: $('.omniauth-container'), }).bindEvents(); }); diff --git a/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js b/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js index 18c7b21cf8c..761618109a4 100644 --- a/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js +++ b/app/assets/javascripts/pages/sessions/new/oauth_remember_me.js @@ -17,7 +17,6 @@ export default class OAuthRememberMe { $('#remember_me', this.container).on('click', this.toggleRememberMe); } - // eslint-disable-next-line class-methods-use-this toggleRememberMe(event) { const rememberMe = $(event.target).is(':checked'); diff --git a/app/assets/javascripts/pages/sessions/new/signin_tabs_memoizer.js b/app/assets/javascripts/pages/sessions/new/signin_tabs_memoizer.js index d321892d2d2..1e7c29aefaa 100644 --- a/app/assets/javascripts/pages/sessions/new/signin_tabs_memoizer.js +++ b/app/assets/javascripts/pages/sessions/new/signin_tabs_memoizer.js @@ -37,6 +37,11 @@ export default class SigninTabsMemoizer { const tab = document.querySelector(`${this.tabSelector} a[href="${anchorName}"]`); if (tab) { tab.click(); + } else { + const firstTab = document.querySelector(`${this.tabSelector} a`); + if (firstTab) { + firstTab.click(); + } } } } diff --git a/app/assets/javascripts/pages/sessions/new/username_validator.js b/app/assets/javascripts/pages/sessions/new/username_validator.js index 87213c94eda..97cf1aeaadc 100644 --- a/app/assets/javascripts/pages/sessions/new/username_validator.js +++ b/app/assets/javascripts/pages/sessions/new/username_validator.js @@ -1,4 +1,4 @@ -/* eslint-disable comma-dangle, consistent-return, class-methods-use-this, arrow-parens, no-param-reassign, max-len */ +/* eslint-disable comma-dangle, consistent-return, class-methods-use-this */ import $ from 'jquery'; import _ from 'underscore'; diff --git a/app/assets/javascripts/preview_markdown.js b/app/assets/javascripts/preview_markdown.js index 246a265ef2b..45670584679 100644 --- a/app/assets/javascripts/preview_markdown.js +++ b/app/assets/javascripts/preview_markdown.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, no-var, object-shorthand, comma-dangle, prefer-arrow-callback */ +/* eslint-disable func-names, no-var, object-shorthand, prefer-arrow-callback */ import $ from 'jquery'; import axios from '~/lib/utils/axios_utils'; diff --git a/app/assets/javascripts/profile/gl_crop.js b/app/assets/javascripts/profile/gl_crop.js index ba120c4bbdf..40ec3208b58 100644 --- a/app/assets/javascripts/profile/gl_crop.js +++ b/app/assets/javascripts/profile/gl_crop.js @@ -1,4 +1,4 @@ -/* eslint-disable no-useless-escape, max-len, quotes, no-var, no-underscore-dangle, func-names, space-before-function-paren, no-unused-vars, no-return-assign, object-shorthand, one-var, one-var-declaration-per-line, comma-dangle, consistent-return, class-methods-use-this, new-parens */ +/* eslint-disable no-useless-escape, max-len, no-var, no-underscore-dangle, func-names, no-unused-vars, no-return-assign, object-shorthand, one-var, one-var-declaration-per-line, comma-dangle, consistent-return, class-methods-use-this, new-parens */ import $ from 'jquery'; import 'cropper'; diff --git a/app/assets/javascripts/profile/profile.js b/app/assets/javascripts/profile/profile.js index 0af34657d72..5d58d968d30 100644 --- a/app/assets/javascripts/profile/profile.js +++ b/app/assets/javascripts/profile/profile.js @@ -1,8 +1,5 @@ -/* eslint-disable comma-dangle, no-unused-vars, class-methods-use-this, quotes, consistent-return, func-names, prefer-arrow-callback, space-before-function-paren, max-len */ - import $ from 'jquery'; import axios from '~/lib/utils/axios_utils'; -import { __ } from '~/locale'; import flash from '../flash'; export default class Profile { diff --git a/app/assets/javascripts/project_find_file.js b/app/assets/javascripts/project_find_file.js index 17497283695..f53c95205af 100644 --- a/app/assets/javascripts/project_find_file.js +++ b/app/assets/javascripts/project_find_file.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, quotes, consistent-return, one-var, one-var-declaration-per-line, no-cond-assign, max-len, object-shorthand, no-param-reassign, comma-dangle, prefer-template, no-unused-vars, no-return-assign */ +/* eslint-disable func-names, no-var, wrap-iife, quotes, consistent-return, one-var, one-var-declaration-per-line, no-cond-assign, max-len, prefer-template, no-unused-vars, no-return-assign */ import $ from 'jquery'; import fuzzaldrinPlus from 'fuzzaldrin-plus'; diff --git a/app/assets/javascripts/project_select.js b/app/assets/javascripts/project_select.js index cb2e6855d1d..240dde56325 100644 --- a/app/assets/javascripts/project_select.js +++ b/app/assets/javascripts/project_select.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, prefer-arrow-callback, no-var, comma-dangle, object-shorthand, one-var, one-var-declaration-per-line, no-else-return, quotes, max-len */ +/* eslint-disable func-names, wrap-iife, no-var, comma-dangle, object-shorthand, one-var, one-var-declaration-per-line, no-else-return, quotes, max-len */ import $ from 'jquery'; import Api from './api'; diff --git a/app/assets/javascripts/right_sidebar.js b/app/assets/javascripts/right_sidebar.js index 2afcf4626b8..b27d635c6ac 100644 --- a/app/assets/javascripts/right_sidebar.js +++ b/app/assets/javascripts/right_sidebar.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, no-unused-vars, consistent-return, one-var, one-var-declaration-per-line, quotes, prefer-template, object-shorthand, comma-dangle, no-else-return, no-param-reassign, max-len */ +/* eslint-disable func-names, no-var, no-unused-vars, consistent-return, one-var, one-var-declaration-per-line, quotes, prefer-template, no-else-return, no-param-reassign, max-len */ import $ from 'jquery'; import _ from 'underscore'; diff --git a/app/assets/javascripts/search_autocomplete.js b/app/assets/javascripts/search_autocomplete.js index ef3c71eeafe..2f4e4881f24 100644 --- a/app/assets/javascripts/search_autocomplete.js +++ b/app/assets/javascripts/search_autocomplete.js @@ -1,4 +1,4 @@ -/* eslint-disable no-return-assign, one-var, no-var, no-underscore-dangle, one-var-declaration-per-line, no-unused-vars, no-cond-assign, consistent-return, object-shorthand, prefer-arrow-callback, func-names, space-before-function-paren, prefer-template, quotes, class-methods-use-this, no-sequences, wrap-iife, no-lonely-if, no-else-return, no-param-reassign, vars-on-top, max-len */ +/* eslint-disable no-return-assign, one-var, no-var, no-underscore-dangle, one-var-declaration-per-line, no-unused-vars, consistent-return, object-shorthand, prefer-template, quotes, class-methods-use-this, no-lonely-if, no-else-return, vars-on-top, max-len */ import $ from 'jquery'; import axios from './lib/utils/axios_utils'; diff --git a/app/assets/javascripts/sidebar/mount_sidebar.js b/app/assets/javascripts/sidebar/mount_sidebar.js index 3086e7d0fc9..655bf9198b7 100644 --- a/app/assets/javascripts/sidebar/mount_sidebar.js +++ b/app/assets/javascripts/sidebar/mount_sidebar.js @@ -75,7 +75,6 @@ function mountLockComponent(mediator) { function mountParticipantsComponent(mediator) { const el = document.querySelector('.js-sidebar-participants-entry-point'); - // eslint-disable-next-line no-new if (!el) return; // eslint-disable-next-line no-new diff --git a/app/assets/javascripts/single_file_diff.js b/app/assets/javascripts/single_file_diff.js index ae27c676fa0..99c93952e2a 100644 --- a/app/assets/javascripts/single_file_diff.js +++ b/app/assets/javascripts/single_file_diff.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, prefer-arrow-callback, space-before-function-paren, no-var, prefer-rest-params, wrap-iife, one-var, one-var-declaration-per-line, consistent-return, no-param-reassign, max-len */ +/* eslint-disable func-names, prefer-arrow-callback, consistent-return, */ import $ from 'jquery'; import { __ } from './locale'; diff --git a/app/assets/javascripts/syntax_highlight.js b/app/assets/javascripts/syntax_highlight.js index f52990ba232..37f3dd4b496 100644 --- a/app/assets/javascripts/syntax_highlight.js +++ b/app/assets/javascripts/syntax_highlight.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, consistent-return, no-var, no-else-return, prefer-arrow-callback, max-len */ +/* eslint-disable consistent-return, no-else-return */ import $ from 'jquery'; diff --git a/app/assets/javascripts/tree.js b/app/assets/javascripts/tree.js index afbb958d058..85123a63a45 100644 --- a/app/assets/javascripts/tree.js +++ b/app/assets/javascripts/tree.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, max-len, quotes, consistent-return, no-var, one-var, one-var-declaration-per-line, no-else-return, prefer-arrow-callback, class-methods-use-this */ +/* eslint-disable func-names, max-len, quotes, consistent-return, no-var, one-var, one-var-declaration-per-line, no-else-return, prefer-arrow-callback, class-methods-use-this */ import $ from 'jquery'; import { visitUrl } from './lib/utils/url_utility'; diff --git a/app/assets/javascripts/users_select.js b/app/assets/javascripts/users_select.js index 349614460e1..277a7656b8e 100644 --- a/app/assets/javascripts/users_select.js +++ b/app/assets/javascripts/users_select.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, one-var, no-var, prefer-rest-params, wrap-iife, quotes, max-len, one-var-declaration-per-line, vars-on-top, prefer-arrow-callback, consistent-return, comma-dangle, object-shorthand, no-shadow, no-unused-vars, no-else-return, no-self-compare, prefer-template, no-unused-expressions, no-lonely-if, yoda, prefer-spread, no-void, camelcase, no-param-reassign */ +/* eslint-disable func-names, one-var, no-var, prefer-rest-params, quotes, max-len, one-var-declaration-per-line, vars-on-top, prefer-arrow-callback, consistent-return, comma-dangle, object-shorthand, no-shadow, no-unused-vars, no-else-return, no-self-compare, prefer-template, no-unused-expressions, yoda, prefer-spread, no-void, camelcase, no-param-reassign */ /* global Issuable */ /* global emitSidebarEvent */ diff --git a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue index bc4ba3d050b..e455c4d2cb5 100644 --- a/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue +++ b/app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue @@ -172,7 +172,7 @@ export default { } }) .catch(() => { - createFlash('Something went wrong while fetching the environments for this merge request. Please try again.'); // eslint-disable-line + createFlash('Something went wrong while fetching the environments for this merge request. Please try again.'); }); }, fetchActionsContent() { diff --git a/app/assets/javascripts/vue_shared/vue_resource_interceptor.js b/app/assets/javascripts/vue_shared/vue_resource_interceptor.js index b9693892f45..73b9131e5ba 100644 --- a/app/assets/javascripts/vue_shared/vue_resource_interceptor.js +++ b/app/assets/javascripts/vue_shared/vue_resource_interceptor.js @@ -28,7 +28,7 @@ Vue.http.interceptors.push((request, next) => { response.headers.forEach((value, key) => { headers[key] = value; }); - // eslint-disable-next-line no-param-reassign + response.headers = headers; }); }); diff --git a/app/assets/javascripts/zen_mode.js b/app/assets/javascripts/zen_mode.js index f68a4f28714..0138c9be803 100644 --- a/app/assets/javascripts/zen_mode.js +++ b/app/assets/javascripts/zen_mode.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, space-before-function-paren, wrap-iife, prefer-arrow-callback, no-unused-vars, consistent-return, camelcase, comma-dangle, max-len, class-methods-use-this */ +/* eslint-disable func-names, wrap-iife, prefer-arrow-callback, no-unused-vars, consistent-return, camelcase, comma-dangle, max-len, class-methods-use-this */ // Zen Mode (full screen) textarea // diff --git a/app/assets/stylesheets/bootstrap_migration.scss b/app/assets/stylesheets/bootstrap_migration.scss index e6303ad4642..0d8e867f41d 100644 --- a/app/assets/stylesheets/bootstrap_migration.scss +++ b/app/assets/stylesheets/bootstrap_migration.scss @@ -89,11 +89,6 @@ a { color: $gl-link-color; } -a:not(.btn):focus, -a:not(.btn):active { - text-decoration: underline; -} - hr { overflow: hidden; } diff --git a/app/assets/stylesheets/framework/contextual_sidebar.scss b/app/assets/stylesheets/framework/contextual_sidebar.scss index cccd1a6d942..9cbaaa5dc8d 100644 --- a/app/assets/stylesheets/framework/contextual_sidebar.scss +++ b/app/assets/stylesheets/framework/contextual_sidebar.scss @@ -193,7 +193,6 @@ &:focus { background: $link-active-background; color: $gl-text-color; - text-decoration: none; } } diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss index db59c91e375..2fa71b23314 100644 --- a/app/assets/stylesheets/framework/header.scss +++ b/app/assets/stylesheets/framework/header.scss @@ -558,7 +558,7 @@ background: $white-light; border-bottom: 1px solid $white-normal; - .center-logo { + .mx-auto { margin: 8px 0; text-align: center; diff --git a/app/controllers/admin/hooks_controller.rb b/app/controllers/admin/hooks_controller.rb index 2b47819303e..fb788c47ef1 100644 --- a/app/controllers/admin/hooks_controller.rb +++ b/app/controllers/admin/hooks_controller.rb @@ -9,7 +9,7 @@ class Admin::HooksController < Admin::ApplicationController end def create - @hook = SystemHook.new(hook_params) + @hook = SystemHook.new(hook_params.to_h) if @hook.save redirect_to admin_hooks_path, notice: 'Hook was successfully created.' diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 68d328fa797..ff133001b84 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -54,7 +54,7 @@ class DashboardController < Dashboard::ApplicationController return unless @no_filters_set respond_to do |format| - format.html + format.html { render } format.atom { head :bad_request } end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index a93b116c6fe..efb30ba4715 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -247,13 +247,13 @@ class ProjectsController < Projects::ApplicationController if find_branches branches = BranchesFinder.new(@repository, params).execute.take(100).map(&:name) - options[s_('RefSwitcher|Branches')] = branches + options['Branches'] = branches end if find_tags && @repository.tag_count.nonzero? tags = TagsFinder.new(@repository, params).execute.take(100).map(&:name) - options[s_('RefSwitcher|Tags')] = tags + options['Tags'] = tags end # If reference is commit id - we should add it to branch/tag selectbox diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index c405e6d117f..be3958c40a4 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -350,11 +350,15 @@ module ProjectsHelper if allowed_protocols_present? enabled_protocol else - if !current_user || current_user.require_ssh_key? - gitlab_config.protocol - else - 'ssh' - end + extra_default_clone_protocol + end + end + + def extra_default_clone_protocol + if !current_user || current_user.require_ssh_key? + gitlab_config.protocol + else + 'ssh' end end @@ -501,4 +505,37 @@ module ProjectsHelper "list-label" end end + + def sidebar_settings_paths + %w[ + projects#edit + project_members#index + integrations#show + services#edit + repository#show + ci_cd#show + badges#index + pages#show + ] + end + + def sidebar_repository_paths + %w[ + tree + blob + blame + edit_tree + new_tree + find_file + commit + commits + compare + projects/repositories + tags + branches + releases + graphs + network + ] + end end diff --git a/app/mailers/emails/merge_requests.rb b/app/mailers/emails/merge_requests.rb index 5ba3a4a322c..70509e9066d 100644 --- a/app/mailers/emails/merge_requests.rb +++ b/app/mailers/emails/merge_requests.rb @@ -59,8 +59,6 @@ module Emails def merge_request_unmergeable_email(recipient_id, merge_request_id, reason = nil) setup_merge_request_mail(merge_request_id, recipient_id) - @reasons = MergeRequestPresenter.new(@merge_request, current_user: current_user).unmergeable_reasons - mail_answer_thread(@merge_request, merge_request_thread_options(@merge_request.author_id, recipient_id, reason)) end diff --git a/app/models/clusters/applications/prometheus.rb b/app/models/clusters/applications/prometheus.rb index c702c4ee807..48137c2ed68 100644 --- a/app/models/clusters/applications/prometheus.rb +++ b/app/models/clusters/applications/prometheus.rb @@ -3,7 +3,7 @@ module Clusters class Prometheus < ActiveRecord::Base include PrometheusAdapter - VERSION = "2.0.0".freeze + VERSION = '6.7.3'.freeze self.table_name = 'clusters_applications_prometheus' @@ -37,6 +37,7 @@ module Clusters Gitlab::Kubernetes::Helm::InstallCommand.new( name, chart: chart, + version: version, values: values ) end diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb index 324065c1162..4b78ba1029f 100644 --- a/app/models/merge_request.rb +++ b/app/models/merge_request.rb @@ -128,8 +128,17 @@ class MergeRequest < ActiveRecord::Base end after_transition unchecked: :cannot_be_merged do |merge_request, transition| - NotificationService.new.merge_request_unmergeable(merge_request) - TodoService.new.merge_request_became_unmergeable(merge_request) + begin + # Merge request can become unmergeable due to many reasons. + # We only notify if it is due to conflict. + unless merge_request.project.repository.can_be_merged?(merge_request.diff_head_sha, merge_request.target_branch) + NotificationService.new.merge_request_unmergeable(merge_request) + TodoService.new.merge_request_became_unmergeable(merge_request) + end + rescue Gitlab::Git::CommandError + # Checking mergeability can trigger exception, e.g. non-utf8 + # We ignore this type of errors. + end end def check_state?(merge_status) diff --git a/app/models/repository.rb b/app/models/repository.rb index c2f62badbcb..3089d0162ee 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -850,7 +850,7 @@ class Repository @root_ref_sha ||= commit(root_ref).sha end - delegate :merged_branch_names, :can_be_merged?, to: :raw_repository + delegate :merged_branch_names, to: :raw_repository def merge_base(first_commit_id, second_commit_id) first_commit_id = commit(first_commit_id).try(:id) || first_commit_id diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index 8ea5435d740..199bcf92b21 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -297,6 +297,7 @@ class ProjectPolicy < BasePolicy prevent(*create_read_update_admin_destroy(:build)) prevent(*create_read_update_admin_destroy(:pipeline_schedule)) prevent(*create_read_update_admin_destroy(:environment)) + prevent(*create_read_update_admin_destroy(:cluster)) prevent(*create_read_update_admin_destroy(:deployment)) end diff --git a/app/presenters/merge_request_presenter.rb b/app/presenters/merge_request_presenter.rb index 8d466c33510..eb54ab2cda6 100644 --- a/app/presenters/merge_request_presenter.rb +++ b/app/presenters/merge_request_presenter.rb @@ -20,17 +20,6 @@ class MergeRequestPresenter < Gitlab::View::Presenter::Delegated end end - def unmergeable_reasons - strong_memoize(:unmergeable_reasons) do - reasons = [] - reasons << "no commits" if merge_request.has_no_commits? - reasons << "source branch is missing" unless merge_request.source_branch_exists? - reasons << "target branch is missing" unless merge_request.target_branch_exists? - reasons << "has merge conflicts" unless merge_request.project.repository.can_be_merged?(merge_request.diff_head_sha, merge_request.target_branch) - reasons - end - end - def cancel_merge_when_pipeline_succeeds_path if can_cancel_merge_when_pipeline_succeeds?(current_user) cancel_merge_when_pipeline_succeeds_project_merge_request_path(project, merge_request) diff --git a/app/views/layouts/nav/sidebar/_project.html.haml b/app/views/layouts/nav/sidebar/_project.html.haml index fdb07ce6fc5..9f8b3b86474 100644 --- a/app/views/layouts/nav/sidebar/_project.html.haml +++ b/app/views/layouts/nav/sidebar/_project.html.haml @@ -34,8 +34,10 @@ = link_to project_cycle_analytics_path(@project), title: _('Cycle Analytics'), class: 'shortcuts-project-cycle-analytics' do %span= _('Cycle Analytics') + = render_if_exists 'projects/sidebar/security_dashboard' + - 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 + = nav_link(controller: sidebar_repository_paths) do = link_to project_tree_path(@project), class: 'shortcuts-tree' do .nav-icon-container = sprite_icon('doc_text') @@ -43,7 +45,7 @@ = _('Repository') %ul.sidebar-sub-level-items - = nav_link(controller: %w(tree blob blame edit_tree new_tree find_file commit commits compare projects/repositories tags branches releases graphs network), html_options: { class: "fly-out-top-item" } ) do + = nav_link(controller: sidebar_repository_paths, html_options: { class: "fly-out-top-item" } ) do = link_to project_tree_path(@project) do %strong.fly-out-top-item-name = _('Repository') @@ -80,6 +82,8 @@ = link_to charts_project_graph_path(@project, current_ref) do = _('Charts') + = render_if_exists 'projects/sidebar/repository_locked_files' + - if project_nav_tab? :issues = nav_link(controller: @project.issues_enabled? ? [:issues, :labels, :milestones, :boards] : :issues) do = link_to project_issues_path(@project), class: 'shortcuts-issues' do @@ -92,7 +96,7 @@ = number_with_delimiter(@project.open_issues_count(current_user)) %ul.sidebar-sub-level-items - = nav_link(controller: :issues, html_options: { class: "fly-out-top-item" } ) do + = nav_link(controller: :issues, action: :index, html_options: { class: "fly-out-top-item" } ) do = link_to project_issues_path(@project) do %strong.fly-out-top-item-name = _('Issues') @@ -115,6 +119,8 @@ %span = _('Labels') + = render_if_exists 'projects/sidebar/issues_service_desk' + = nav_link(controller: :milestones) do = link_to project_milestones_path(@project), title: 'Milestones' do %span @@ -278,7 +284,7 @@ = _('Snippets') - if project_nav_tab? :settings - = nav_link(path: %w[projects#edit project_members#index integrations#show services#edit repository#show ci_cd#show badges#index pages#show]) do + = nav_link(path: sidebar_settings_paths) do = link_to edit_project_path(@project), class: 'shortcuts-tree' do .nav-icon-container = sprite_icon('settings') @@ -288,7 +294,7 @@ %ul.sidebar-sub-level-items - can_edit = can?(current_user, :admin_project, @project) - if can_edit - = nav_link(path: %w[projects#edit project_members#index integrations#show services#edit repository#show ci_cd#show badges#index pages#show], html_options: { class: "fly-out-top-item" } ) do + = nav_link(path: sidebar_settings_paths, html_options: { class: "fly-out-top-item" } ) do = link_to edit_project_path(@project) do %strong.fly-out-top-item-name = _('Settings') @@ -326,6 +332,8 @@ %span = _('Pages') + = render_if_exists 'projects/sidebar/settings_audit_events' + - else = nav_link(controller: :project_members) do = link_to project_settings_members_path(@project), title: 'Members', class: 'shortcuts-tree' do diff --git a/app/views/notify/merge_request_unmergeable_email.html.haml b/app/views/notify/merge_request_unmergeable_email.html.haml index 578fa1fbce7..7ec0c1ef390 100644 --- a/app/views/notify/merge_request_unmergeable_email.html.haml +++ b/app/views/notify/merge_request_unmergeable_email.html.haml @@ -1,6 +1,2 @@ %p - Merge Request #{link_to @merge_request.to_reference, project_merge_request_url(@merge_request.target_project, @merge_request)} can no longer be merged due to the following #{'reason'.pluralize(@reasons.count)}: - - %ul - - @reasons.each do |reason| - %li= reason + Merge Request #{link_to @merge_request.to_reference, project_merge_request_url(@merge_request.target_project, @merge_request)} can no longer be merged due to conflict. diff --git a/app/views/notify/merge_request_unmergeable_email.text.haml b/app/views/notify/merge_request_unmergeable_email.text.haml index e4f9f1bf5e7..dcdd6db69d6 100644 --- a/app/views/notify/merge_request_unmergeable_email.text.haml +++ b/app/views/notify/merge_request_unmergeable_email.text.haml @@ -1,7 +1,4 @@ -Merge Request #{@merge_request.to_reference} can no longer be merged due to the following #{'reason'.pluralize(@reasons.count)}: - -- @reasons.each do |reason| - * #{reason} +Merge Request #{@merge_request.to_reference} can no longer be merged due to conflict. Merge Request url: #{project_merge_request_url(@merge_request.target_project, @merge_request)} diff --git a/app/views/projects/clusters/gcp/login.html.haml b/app/views/projects/clusters/gcp/login.html.haml index 55a42ac4847..96c7a648676 100644 --- a/app/views/projects/clusters/gcp/login.html.haml +++ b/app/views/projects/clusters/gcp/login.html.haml @@ -16,5 +16,6 @@ = _('or') = link_to('create a new Google account', 'https://accounts.google.com/SignUpWithoutGmail?service=cloudconsole&continue=https%3A%2F%2Fconsole.cloud.google.com%2Ffreetrial%3Futm_campaign%3D2018_cpanel%26utm_source%3Dgitlab%26utm_medium%3Dreferral', target: '_blank', rel: 'noopener noreferrer') - else - - link = link_to(s_('ClusterIntegration|properly configured'), help_page_path("integration/google"), target: '_blank', rel: 'noopener noreferrer') - = s_('Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service.').html_safe % { link_to_documentation: link } + .settings-message.text-center + - link = link_to(s_('ClusterIntegration|properly configured'), help_page_path("integration/google"), target: '_blank', rel: 'noopener noreferrer') + = s_('Google authentication is not %{link_to_documentation}. Ask your GitLab administrator if you want to use this service.').html_safe % { link_to_documentation: link } diff --git a/app/views/shared/milestones/_form_dates.html.haml b/app/views/shared/milestones/_form_dates.html.haml index 608dd35182d..922805958a5 100644 --- a/app/views/shared/milestones/_form_dates.html.haml +++ b/app/views/shared/milestones/_form_dates.html.haml @@ -2,10 +2,10 @@ .form-group.row = f.label :start_date, "Start Date", class: "col-form-label col-sm-2" .col-sm-10 - = f.text_field :start_date, class: "datepicker form-control", placeholder: "Select start date" + = f.text_field :start_date, class: "datepicker form-control", placeholder: "Select start date", autocomplete: 'off' %a.inline.float-right.prepend-top-5.js-clear-start-date{ href: "#" } Clear start date .form-group.row = f.label :due_date, "Due Date", class: "col-form-label col-sm-2" .col-sm-10 - = f.text_field :due_date, class: "datepicker form-control", placeholder: "Select due date" + = f.text_field :due_date, class: "datepicker form-control", placeholder: "Select due date", autocomplete: 'off' %a.inline.float-right.prepend-top-5.js-clear-due-date{ href: "#" } Clear due date diff --git a/changelogs/unreleased/47631-operations-kubernetes-option-is-always-visible-when-repository-or-builds-are-disabled.yml b/changelogs/unreleased/47631-operations-kubernetes-option-is-always-visible-when-repository-or-builds-are-disabled.yml new file mode 100644 index 00000000000..5c23b3ef320 --- /dev/null +++ b/changelogs/unreleased/47631-operations-kubernetes-option-is-always-visible-when-repository-or-builds-are-disabled.yml @@ -0,0 +1,5 @@ +--- +title: Omits operartions and kubernetes item from project sidebar when repository or builds are disabled +merge_request: 19835 +author: +type: fixed diff --git a/changelogs/unreleased/48100-fix-branch-not-shown.yml b/changelogs/unreleased/48100-fix-branch-not-shown.yml new file mode 100644 index 00000000000..917c5c23f67 --- /dev/null +++ b/changelogs/unreleased/48100-fix-branch-not-shown.yml @@ -0,0 +1,6 @@ +--- +title: Fix branches are not shown in Merge Request dropdown when preferred language + is not English +merge_request: 20016 +author: Hiroyuki Sato +type: fixed diff --git a/changelogs/unreleased/48126-fix-prometheus-installation.yml b/changelogs/unreleased/48126-fix-prometheus-installation.yml new file mode 100644 index 00000000000..e6ab9c46fbf --- /dev/null +++ b/changelogs/unreleased/48126-fix-prometheus-installation.yml @@ -0,0 +1,5 @@ +--- +title: Specify chart version when installing applications on Clusters +merge_request: 20010 +author: +type: fixed diff --git a/changelogs/unreleased/48153-date-selection-dialog-broken-when-creating-a-new-milestone.yml b/changelogs/unreleased/48153-date-selection-dialog-broken-when-creating-a-new-milestone.yml new file mode 100644 index 00000000000..13ab5b0467d --- /dev/null +++ b/changelogs/unreleased/48153-date-selection-dialog-broken-when-creating-a-new-milestone.yml @@ -0,0 +1,5 @@ +--- +title: Prevent browser autocomplete for milestone date fields +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/blackst0ne-rails5-found-new-routes-that-could-cause-conflicts-with-existing-namespaced-routes.yml b/changelogs/unreleased/blackst0ne-rails5-found-new-routes-that-could-cause-conflicts-with-existing-namespaced-routes.yml new file mode 100644 index 00000000000..c8d916af824 --- /dev/null +++ b/changelogs/unreleased/blackst0ne-rails5-found-new-routes-that-could-cause-conflicts-with-existing-namespaced-routes.yml @@ -0,0 +1,5 @@ +--- +title: "[Rails5] Fix ActionCable '/cable' mountpoint conflict" +merge_request: 20015 +author: "@blackst0ne" +type: fixed diff --git a/changelogs/unreleased/bvl-dont-generate-mo.yml b/changelogs/unreleased/bvl-dont-generate-mo.yml new file mode 100644 index 00000000000..19b8e873849 --- /dev/null +++ b/changelogs/unreleased/bvl-dont-generate-mo.yml @@ -0,0 +1,5 @@ +--- +title: Fix invalid fuzzy translations being generated during installation +merge_request: 20048 +author: +type: fixed diff --git a/changelogs/unreleased/fix-favicon-cross-origin.yml b/changelogs/unreleased/fix-favicon-cross-origin.yml new file mode 100644 index 00000000000..3317781e222 --- /dev/null +++ b/changelogs/unreleased/fix-favicon-cross-origin.yml @@ -0,0 +1,5 @@ +--- +title: Serve favicon image always from the main GitLab domain to avoid issues with CORS +merge_request: 19810 +author: Alexis Reigel +type: fixed diff --git a/changelogs/unreleased/highlight-cluster-settings-message.yml b/changelogs/unreleased/highlight-cluster-settings-message.yml new file mode 100644 index 00000000000..4e029941c51 --- /dev/null +++ b/changelogs/unreleased/highlight-cluster-settings-message.yml @@ -0,0 +1,5 @@ +--- +title: Highlight cluster settings message +merge_request: 19996 +author: George Tsiolis +type: changed diff --git a/changelogs/unreleased/jr-48133-web-ide-commit-ellipsis.yml b/changelogs/unreleased/jr-48133-web-ide-commit-ellipsis.yml new file mode 100644 index 00000000000..ac58eaccaaf --- /dev/null +++ b/changelogs/unreleased/jr-48133-web-ide-commit-ellipsis.yml @@ -0,0 +1,5 @@ +--- +title: Add ellispsis to web ide commit button +merge_request: 20030 +author: +type: other diff --git a/changelogs/unreleased/limit-metrics-content-type.yml b/changelogs/unreleased/limit-metrics-content-type.yml new file mode 100644 index 00000000000..42cb4347771 --- /dev/null +++ b/changelogs/unreleased/limit-metrics-content-type.yml @@ -0,0 +1,5 @@ +--- +title: Limit the action suffixes in transaction metrics +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/rails5-fix-48104.yml b/changelogs/unreleased/rails5-fix-48104.yml new file mode 100644 index 00000000000..6cf519ad791 --- /dev/null +++ b/changelogs/unreleased/rails5-fix-48104.yml @@ -0,0 +1,6 @@ +--- +title: 'Rails5 fix expected: 1 time with arguments: (97, anything, {"squash"=>false}) + received: 0 times' +merge_request: 20004 +author: Jasper Maes +type: fixed diff --git a/changelogs/unreleased/rails5-fix-48141.yml b/changelogs/unreleased/rails5-fix-48141.yml new file mode 100644 index 00000000000..5e2aa23b8fb --- /dev/null +++ b/changelogs/unreleased/rails5-fix-48141.yml @@ -0,0 +1,6 @@ +--- +title: 'Rails5 fix expected: 0 times with any arguments received: 1 time with arguments: + DashboardController' +merge_request: 20018 +author: Jasper Maes +type: fixed diff --git a/changelogs/unreleased/rails5-fix-48142.yml b/changelogs/unreleased/rails5-fix-48142.yml new file mode 100644 index 00000000000..bfd95cfbe8b --- /dev/null +++ b/changelogs/unreleased/rails5-fix-48142.yml @@ -0,0 +1,5 @@ +--- +title: Rails5 fix Admin::HooksController +merge_request: 20017 +author: Jasper Maes +type: fixed diff --git a/changelogs/unreleased/rails5-fix-pages-controller.yml b/changelogs/unreleased/rails5-fix-pages-controller.yml new file mode 100644 index 00000000000..eeb3747c4eb --- /dev/null +++ b/changelogs/unreleased/rails5-fix-pages-controller.yml @@ -0,0 +1,5 @@ +--- +title: Rails5 fix Projects::PagesController spec +merge_request: 20007 +author: Jasper Maes +type: fixed diff --git a/changelogs/unreleased/remove-allocations-gem.yml b/changelogs/unreleased/remove-allocations-gem.yml new file mode 100644 index 00000000000..e809fd26701 --- /dev/null +++ b/changelogs/unreleased/remove-allocations-gem.yml @@ -0,0 +1,5 @@ +--- +title: Remove remaining traces of the Allocations Gem +merge_request: +author: +type: changed diff --git a/changelogs/unreleased/sh-bump-rugged-0-27-2.yml b/changelogs/unreleased/sh-bump-rugged-0-27-2.yml new file mode 100644 index 00000000000..6c519648b51 --- /dev/null +++ b/changelogs/unreleased/sh-bump-rugged-0-27-2.yml @@ -0,0 +1,5 @@ +--- +title: Bump rugged to 0.27.2 +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/use-backup-custom-hooks-gitaly.yml b/changelogs/unreleased/use-backup-custom-hooks-gitaly.yml new file mode 100644 index 00000000000..4b9766332c3 --- /dev/null +++ b/changelogs/unreleased/use-backup-custom-hooks-gitaly.yml @@ -0,0 +1,5 @@ +--- +title: migrate backup rake task to gitaly +merge_request: +author: +type: added diff --git a/config/application.rb b/config/application.rb index 95f6d2c9af1..385eb65e7f4 100644 --- a/config/application.rb +++ b/config/application.rb @@ -57,6 +57,13 @@ module Gitlab # Configure the default encoding used in templates for Ruby 1.9. config.encoding = "utf-8" + # ActionCable mount point. + # The default Rails' mount point is `/cable` which may conflict with existing + # namespaces/users. + # https://github.com/rails/rails/blob/5-0-stable/actioncable/lib/action_cable.rb#L38 + # Please change this value when configuring ActionCable for real usage. + config.action_cable.mount_path = "-" if rails5? + # Configure sensitive parameters which will be filtered from the log file. # # Parameters filtered: diff --git a/doc/api/members.md b/doc/api/members.md index 1a10aa75ac0..8ebe464c359 100644 --- a/doc/api/members.md +++ b/doc/api/members.md @@ -173,3 +173,7 @@ DELETE /projects/:id/members/:user_id curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/groups/:id/members/:user_id curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" https://gitlab.example.com/api/v4/projects/:id/members/:user_id ``` + +## Give a group access to a project + +Look at [share project with group](projects.md#share-project-with-group) diff --git a/doc/api/projects.md b/doc/api/projects.md index d3e95926322..30a41839f28 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -1198,7 +1198,7 @@ POST /projects/:id/share | --------- | ---- | -------- | ----------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) | | `group_id` | integer | yes | The ID of the group to share with | -| `group_access` | integer | yes | The permissions level to grant the group | +| `group_access` | integer | yes | The [permissions level](members.md) to grant the group | | `expires_at` | string | no | Share expiration date in ISO 8601 format: 2016-09-26 | ## Delete a shared project link within a group diff --git a/doc/development/query_recorder.md b/doc/development/query_recorder.md index 61e5e1afede..2167ed57428 100644 --- a/doc/development/query_recorder.md +++ b/doc/development/query_recorder.md @@ -28,6 +28,7 @@ By default, QueryRecorder will ignore cached queries in the count. However, it m all queries to avoid introducing an N+1 query that may be masked by the statement cache. To do this, pass the `skip_cached` variable to `QueryRecorder` and use the `exceed_all_query_limit` matcher: +``` it "avoids N+1 database queries" do control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) { visit_some_page }.count create_list(:issue, 5) diff --git a/doc/development/what_requires_downtime.md b/doc/development/what_requires_downtime.md index b8be8daa157..f502866333e 100644 --- a/doc/development/what_requires_downtime.md +++ b/doc/development/what_requires_downtime.md @@ -252,6 +252,53 @@ Keep in mind that the relation passed to `change_column_type_using_background_migration` _must_ include `EachBatch`, otherwise it will raise a `TypeError`. +This migration then needs to be followed in a separate release (_not_ a patch +release) by a cleanup migration, which should steal from the queue and handle +any remaining rows. For example: + +```ruby +class MigrateRemainingIssuesClosedAt < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + class Issue < ActiveRecord::Base + self.table_name = 'issues' + include EachBatch + end + + def up + Gitlab::BackgroundMigration.steal('CopyColumn') + Gitlab::BackgroundMigration.steal('CleanupConcurrentTypeChange') + + migrate_remaining_rows if migrate_column_type? + end + + def down + # Previous migrations already revert the changes made here. + end + + def migrate_remaining_rows + Issue.where('closed_at_for_type_change IS NULL AND closed_at IS NOT NULL').each_batch do |batch| + batch.update_all('closed_at_for_type_change = closed_at') + end + + cleanup_concurrent_column_type_change(:issues, :closed_at) + end + + def migrate_column_type? + # Some environments may have already executed the previous version of this + # migration, thus we don't need to migrate those environments again. + column_for('issues', 'closed_at').type == :datetime # rubocop:disable Migration/Datetime + end +end +``` + +For more information, see [the documentation on cleaning up background +migrations](background_migrations.md#cleaning-up). + ## Adding Indexes Adding indexes is an expensive process that blocks INSERT and UPDATE queries for diff --git a/doc/install/installation.md b/doc/install/installation.md index 6cd1fb4c2d7..ef415246583 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -154,12 +154,12 @@ page](https://golang.org/dl). # Remove former Go installation folder sudo rm -rf /usr/local/go - - curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz - echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \ - sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz + + curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz + echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \ + sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/ - rm go1.8.3.linux-amd64.tar.gz + rm go1.10.3.linux-amd64.tar.gz ## 4. Node diff --git a/doc/update/10.8-to-11.0.md b/doc/update/10.8-to-11.0.md index 78a47ab939f..f9b6044bd2f 100644 --- a/doc/update/10.8-to-11.0.md +++ b/doc/update/10.8-to-11.0.md @@ -81,8 +81,8 @@ More information can be found on the [yarn website](https://yarnpkg.com/en/docs/ ### 5. Update Go -NOTE: GitLab 9.2 and higher only supports Go 1.8.3 and dropped support for Go -1.5.x through 1.7.x. Be sure to upgrade your installation if necessary. +NOTE: GitLab 11.0 and higher only supports Go 1.9.x and newer, and dropped support for Go +1.5.x through 1.8.x. Be sure to upgrade your installation if necessary. You can check which version you are running with `go version`. @@ -92,11 +92,11 @@ Download and install Go: # Remove former Go installation folder sudo rm -rf /usr/local/go -curl --remote-name --progress https://storage.googleapis.com/golang/go1.8.3.linux-amd64.tar.gz -echo '1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772 go1.8.3.linux-amd64.tar.gz' | shasum -a256 -c - && \ - sudo tar -C /usr/local -xzf go1.8.3.linux-amd64.tar.gz +curl --remote-name --progress https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz +echo 'fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035 go1.10.3.linux-amd64.tar.gz' | shasum -a256 -c - && \ + sudo tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/ -rm go1.8.3.linux-amd64.tar.gz +rm go1.10.3.linux-amd64.tar.gz ``` ### 6. Get latest code diff --git a/doc/user/permissions.md b/doc/user/permissions.md index b36b0b4f757..a35bf48e62d 100644 --- a/doc/user/permissions.md +++ b/doc/user/permissions.md @@ -25,6 +25,9 @@ See our [product handbook on permissions](https://about.gitlab.com/handbook/prod ## Project members permissions +NOTE: **Note:** +In GitLab 11.0, the Master role was renamed to Maintainer. + The following table depicts the various user permission levels in a project. | Action | Guest | Reporter | Developer |Maintainer| Owner | @@ -146,6 +149,9 @@ read through the documentation on [permissions and access to confidential issues ## Group members permissions +NOTE: **Note:** +In GitLab 11.0, the Master role was renamed to Maintainer. + Any user can remove themselves from a group, unless they are the last Owner of the group. The following table depicts the various user permission levels in a group. @@ -223,6 +229,9 @@ which visibility level you select on project settings. ## GitLab CI/CD permissions +NOTE: **Note:** +In GitLab 11.0, the Master role was renamed to Maintainer. + GitLab CI/CD permissions rely on the role the user has in GitLab. There are four permission levels in total: @@ -250,6 +259,9 @@ instance and project. In addition, all admins can use the admin interface under ### Job permissions +NOTE: **Note:** +In GitLab 11.0, the Master role was renamed to Maintainer. + >**Note:** GitLab 8.12 has a completely redesigned job permissions system. Read all about the [new model and its implications][new-mod]. @@ -301,4 +313,4 @@ Read through the documentation on [LDAP users permissions](https://docs.gitlab.c [ce-18994]: https://gitlab.com/gitlab-org/gitlab-ce/issues/18994 [new-mod]: project/new_ci_build_permissions_model.md [ee-998]: https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/998 -[eep]: https://about.gitlab.com/products/
\ No newline at end of file +[eep]: https://about.gitlab.com/products/ diff --git a/doc/user/profile/preferences.md b/doc/user/profile/preferences.md index e028861a419..eb2d731343e 100644 --- a/doc/user/profile/preferences.md +++ b/doc/user/profile/preferences.md @@ -4,19 +4,14 @@ A user's profile preferences page allows the user to customize various aspects of GitLab to their liking. To navigate to your profile's preferences, click your avatar icon in the top -right corner and select **Settings**. From there on, choose the **Preferences** -tab. - -![Profile preferences settings](img/profile_settings_dropdown.png) +right corner, select **Settings** and then choose **Preferences** from the +left sidebar. ## Navigation theme ->**Note:** -Navigation themes have been re-introduced with [GitLab 10.0](https://about.gitlab.com/2017/09/22/gitlab-10-0-released/). - The GitLab navigation theme setting allows you to personalize your GitLab experience. You can choose from several color themes that add unique colors to the top navigation -and left side navigation. +and left side navigation. Using individual color themes might help you differentiate between your different GitLab instances. @@ -33,13 +28,13 @@ The default palette is Indigo. You can choose between 10 different themes: - Dark - Light -![Profile preferences syntax highlighting themes](img/profile-preferences-syntax-themes.png) +![Profile preferences navigation themes](img/profil-preferences-navigation-theme.png) ## Syntax highlighting theme ->**Note:** -GitLab uses the [rouge Ruby library][rouge] for syntax highlighting. For a -list of supported languages visit the rouge website. +NOTE: **Note:** +GitLab uses the [rouge Ruby library](http://rouge.jneen.net/ "Rouge website") +for syntax highlighting. For a list of supported languages visit the rouge website. Changing this setting allows you to customize the color theme when viewing any syntax highlighted code on GitLab. @@ -52,7 +47,7 @@ The default syntax theme is White, and you can choose among 5 different colors: - Solarized dark - Monokai -![Profile preferences navigation themes](img/profil-preferences-navigation-theme.png) +![Profile preferences syntax highlighting themes](img/profile-preferences-syntax-themes.png) ## Behavior @@ -78,7 +73,7 @@ You have 8 options here that you can use for your default dashboard view: - Your projects' activity - Starred projects' activity - Your groups -- Your [Todos] +- Your [Todos](../../workflow/todos.md) - Assigned Issues - Assigned Merge Requests @@ -92,6 +87,3 @@ You can choose between 3 options: - Files and Readme (default) - Readme - Activity - -[rouge]: http://rouge.jneen.net/ "Rouge website" -[todos]: ../../workflow/todos.md diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb index 0119c5d6851..221ba52b490 100644 --- a/lib/backup/repository.rb +++ b/lib/backup/repository.rb @@ -4,7 +4,6 @@ require_relative 'helper' module Backup class Repository include Backup::Helper - # rubocop:disable Metrics/AbcSize attr_reader :progress @@ -18,61 +17,26 @@ module Backup Project.find_each(batch_size: 1000) do |project| progress.print " * #{display_repo_path(project)} ... " - path_to_project_repo = Gitlab::GitalyClient::StorageSettings.allow_disk_access do - path_to_repo(project) - end - path_to_project_bundle = path_to_bundle(project) - - # Create namespace dir or hashed path if missing if project.hashed_storage?(:repository) FileUtils.mkdir_p(File.dirname(File.join(backup_repos_path, project.disk_path))) else FileUtils.mkdir_p(File.join(backup_repos_path, project.namespace.full_path)) if project.namespace end - if empty_repo?(project) - progress.puts "[SKIPPED]".color(:cyan) + if !empty_repo?(project) + backup_project(project) + progress.puts "[DONE]".color(:green) else - in_path(path_to_project_repo) do |dir| - FileUtils.mkdir_p(path_to_tars(project)) - cmd = %W(tar -cf #{path_to_tars(project, dir)} -C #{path_to_project_repo} #{dir}) - output, status = Gitlab::Popen.popen(cmd) - - unless status.zero? - progress_warn(project, cmd.join(' '), output) - end - end - - cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{path_to_project_repo} bundle create #{path_to_project_bundle} --all) - output, status = Gitlab::Popen.popen(cmd) - - if status.zero? - progress.puts "[DONE]".color(:green) - else - progress_warn(project, cmd.join(' '), output) - end + progress.puts "[SKIPPED]".color(:cyan) end wiki = ProjectWiki.new(project) - path_to_wiki_repo = Gitlab::GitalyClient::StorageSettings.allow_disk_access do - path_to_repo(wiki) - end - path_to_wiki_bundle = path_to_bundle(wiki) - if File.exist?(path_to_wiki_repo) - progress.print " * #{display_repo_path(wiki)} ... " - - if empty_repo?(wiki) - progress.puts " [SKIPPED]".color(:cyan) - else - cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{path_to_wiki_repo} bundle create #{path_to_wiki_bundle} --all) - output, status = Gitlab::Popen.popen(cmd) - if status.zero? - progress.puts " [DONE]".color(:green) - else - progress_warn(wiki, cmd.join(' '), output) - end - end + if !empty_repo?(wiki) + backup_project(wiki) + progress.puts "[DONE] Wiki".color(:green) + else + progress.puts "[SKIPPED] Wiki".color(:cyan) end end end @@ -83,6 +47,38 @@ module Backup end end + def backup_project(project) + gitaly_migrate(:repository_backup) do |is_enabled| + if is_enabled + backup_project_gitaly(project) + else + backup_project_local(project) + end + end + + backup_custom_hooks(project) + rescue => e + progress_warn(project, e, 'Failed to backup repo') + end + + def backup_project_gitaly(project) + path_to_project_bundle = path_to_bundle(project) + Gitlab::GitalyClient::RepositoryService.new(project.repository) + .create_bundle(path_to_project_bundle) + end + + def backup_project_local(project) + path_to_project_repo = Gitlab::GitalyClient::StorageSettings.allow_disk_access do + path_to_repo(project) + end + + path_to_project_bundle = path_to_bundle(project) + + cmd = %W(#{Gitlab.config.git.bin_path} --git-dir=#{path_to_project_repo} bundle create #{path_to_project_bundle} --all) + output, status = Gitlab::Popen.popen(cmd) + progress_warn(project, cmd.join(' '), output) unless status.zero? + end + def delete_all_repositories(name, repository_storage) gitaly_migrate(:delete_all_repositories) do |is_enabled| if is_enabled @@ -97,8 +93,6 @@ module Backup path = repository_storage.legacy_disk_path return unless File.exist?(path) - # Move all files in the existing repos directory except . and .. to - # repositories.old.<timestamp> directory bk_repos_path = File.join(Gitlab.config.backup.path, "tmp", "#{name}-repositories.old." + Time.now.to_i.to_s) FileUtils.mkdir_p(bk_repos_path, mode: 0700) files = Dir.glob(File.join(path, "*"), File::FNM_DOTMATCH) - [File.join(path, "."), File.join(path, "..")] @@ -129,13 +123,47 @@ module Backup .restore_custom_hooks(custom_hooks_path) end + def local_backup_custom_hooks(project) + in_path(path_to_tars(project)) do |dir| + path_to_project_repo = Gitlab::GitalyClient::StorageSettings.allow_disk_access do + path_to_repo(project) + end + break unless File.exist?(File.join(path_to_project_repo, dir)) + + FileUtils.mkdir_p(path_to_tars(project)) + cmd = %W(tar -cf #{path_to_tars(project, dir)} -c #{path_to_project_repo} #{dir}) + output, status = Gitlab::Popen.popen(cmd) + + unless status.zero? + progress_warn(project, cmd.join(' '), output) + end + end + end + + def gitaly_backup_custom_hooks(project) + FileUtils.mkdir_p(path_to_tars(project)) + custom_hooks_path = path_to_tars(project, 'custom_hooks') + Gitlab::GitalyClient::RepositoryService.new(project.repository) + .backup_custom_hooks(custom_hooks_path) + end + + def backup_custom_hooks(project) + gitaly_migrate(:backup_custom_hooks) do |is_enabled| + if is_enabled + gitaly_backup_custom_hooks(project) + else + local_backup_custom_hooks(project) + end + end + end + def restore_custom_hooks(project) in_path(path_to_tars(project)) do |dir| gitaly_migrate(:restore_custom_hooks) do |is_enabled| if is_enabled - local_restore_custom_hooks(project, dir) - else gitaly_restore_custom_hooks(project, dir) + else + local_restore_custom_hooks(project, dir) end end end @@ -186,7 +214,6 @@ module Backup end end end - # rubocop:enable Metrics/AbcSize protected @@ -224,9 +251,7 @@ module Backup def prepare FileUtils.rm_rf(backup_repos_path) - # Ensure the parent dir of backup_repos_path exists FileUtils.mkdir_p(Gitlab.config.backup.path) - # Fail if somebody raced to create backup_repos_path before us FileUtils.mkdir(backup_repos_path, mode: 0700) end @@ -242,7 +267,6 @@ module Backup end def empty_repo?(project_or_wiki) - # Protect against stale caches project_or_wiki.repository.expire_emptiness_caches project_or_wiki.repository.empty? end diff --git a/lib/gitlab/favicon.rb b/lib/gitlab/favicon.rb index faf7016d73a..d512fc58e46 100644 --- a/lib/gitlab/favicon.rb +++ b/lib/gitlab/favicon.rb @@ -2,10 +2,10 @@ module Gitlab class Favicon class << self def main - return appearance_favicon.url if appearance_favicon.exists? - image_name = - if Gitlab::Utils.to_boolean(ENV['CANARY']) + if appearance_favicon.exists? + appearance_favicon.url + elsif Gitlab::Utils.to_boolean(ENV['CANARY']) 'favicon-yellow.png' elsif Rails.env.development? 'favicon-blue.png' @@ -13,7 +13,7 @@ module Gitlab 'favicon.png' end - ActionController::Base.helpers.image_path(image_name) + ActionController::Base.helpers.image_path(image_name, host: host) end def status_overlay(status_name) @@ -22,7 +22,7 @@ module Gitlab "#{status_name}.png" ) - ActionController::Base.helpers.image_path(path) + ActionController::Base.helpers.image_path(path, host: host) end def available_status_names @@ -35,6 +35,16 @@ module Gitlab private + # we only want to create full urls when there's a different asset_host + # configured. + def host + if Gitlab::Application.config.asset_host.nil? || Gitlab::Application.config.asset_host == Gitlab.config.gitlab.base_url + nil + else + Gitlab.config.gitlab.base_url + end + end + def appearance RequestStore.store[:appearance] ||= (Appearance.current || Appearance.new) end diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 7ce90ce170f..b7965315eb2 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -1413,12 +1413,10 @@ module Gitlab end def can_be_merged?(source_sha, target_branch) - gitaly_migrate(:can_be_merged) do |is_enabled| - if is_enabled - gitaly_can_be_merged?(source_sha, find_branch(target_branch, true).target) - else - rugged_can_be_merged?(source_sha, target_branch) - end + if target_sha = find_branch(target_branch, true)&.target + !gitaly_conflicts_client(source_sha, target_sha).conflicts? + else + false end end @@ -2232,14 +2230,6 @@ module Gitlab run_git(['fetch', remote_name], env: env).last.zero? end - def gitaly_can_be_merged?(their_commit, our_commit) - !gitaly_conflicts_client(our_commit, their_commit).conflicts? - end - - def rugged_can_be_merged?(their_commit, our_commit) - !rugged.merge_commits(our_commit, their_commit).conflicts? - end - def gitlab_projects_error raise CommandError, @gitlab_projects.output end diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb index 4340f779e53..ca986434221 100644 --- a/lib/gitlab/gitaly_client/repository_service.rb +++ b/lib/gitlab/gitaly_client/repository_service.rb @@ -196,20 +196,21 @@ module Gitlab end def create_bundle(save_path) - request = Gitaly::CreateBundleRequest.new(repository: @gitaly_repo) - response = GitalyClient.call( - @storage, - :repository_service, + gitaly_fetch_stream_to_file( + save_path, :create_bundle, - request, - timeout: GitalyClient.default_timeout + Gitaly::CreateBundleRequest, + GitalyClient.default_timeout ) + end - File.open(save_path, 'wb') do |f| - response.each do |message| - f.write(message.data) - end - end + def backup_custom_hooks(save_path) + gitaly_fetch_stream_to_file( + save_path, + :backup_custom_hooks, + Gitaly::BackupCustomHooksRequest, + GitalyClient.default_timeout + ) end def create_from_bundle(bundle_path) @@ -309,6 +310,25 @@ module Gitlab private + def gitaly_fetch_stream_to_file(save_path, rpc_name, request_class, timeout) + request = request_class.new(repository: @gitaly_repo) + response = GitalyClient.call( + @storage, + :repository_service, + rpc_name, + request, + timeout: timeout + ) + + File.open(save_path, 'wb') do |f| + response.each do |message| + f.write(message.data) + end + end + # If the file is empty means that we recieved an empty stream, we delete the file + FileUtils.rm(save_path) if File.zero?(save_path) + end + def gitaly_repo_stream_request(file_path, rpc_name, request_class, timeout) request = request_class.new(repository: @gitaly_repo) enum = Enumerator.new do |y| diff --git a/lib/gitlab/kubernetes/helm/install_command.rb b/lib/gitlab/kubernetes/helm/install_command.rb index 30af3e97b4a..d2133a6d65b 100644 --- a/lib/gitlab/kubernetes/helm/install_command.rb +++ b/lib/gitlab/kubernetes/helm/install_command.rb @@ -2,11 +2,12 @@ module Gitlab module Kubernetes module Helm class InstallCommand < BaseCommand - attr_reader :name, :chart, :repository, :values + attr_reader :name, :chart, :version, :repository, :values - def initialize(name, chart:, values:, repository: nil) + def initialize(name, chart:, values:, version: nil, repository: nil) @name = name @chart = chart + @version = version @values = values @repository = repository end @@ -39,9 +40,13 @@ module Gitlab def script_command <<~HEREDOC - helm install #{chart} --name #{name} --namespace #{Gitlab::Kubernetes::Helm::NAMESPACE} -f /data/helm/#{name}/config/values.yaml >/dev/null + helm install #{chart} --name #{name}#{optional_version_flag} --namespace #{Gitlab::Kubernetes::Helm::NAMESPACE} -f /data/helm/#{name}/config/values.yaml >/dev/null HEREDOC end + + def optional_version_flag + " --version #{version}" if version + end end end end diff --git a/lib/gitlab/metrics/samplers/influx_sampler.rb b/lib/gitlab/metrics/samplers/influx_sampler.rb index 5a0f7f28fc8..ad97632e4eb 100644 --- a/lib/gitlab/metrics/samplers/influx_sampler.rb +++ b/lib/gitlab/metrics/samplers/influx_sampler.rb @@ -16,12 +16,6 @@ module Gitlab @last_minor_gc = Delta.new(GC.stat[:minor_gc_count]) @last_major_gc = Delta.new(GC.stat[:major_gc_count]) - - if Gitlab::Metrics.mri? - require 'allocations' - - Allocations.start - end end def sample diff --git a/lib/gitlab/metrics/samplers/ruby_sampler.rb b/lib/gitlab/metrics/samplers/ruby_sampler.rb index 4e1ea62351f..a39b3bc158c 100644 --- a/lib/gitlab/metrics/samplers/ruby_sampler.rb +++ b/lib/gitlab/metrics/samplers/ruby_sampler.rb @@ -20,16 +20,6 @@ module Gitlab {} end - def initialize(interval) - super(interval) - - if Metrics.mri? - require 'allocations' - - Allocations.start - end - end - def init_metrics metrics = {} metrics[:sampler_duration] = Metrics.histogram(with_prefix(:sampler_duration, :seconds), 'Sampler time', { worker: nil }) diff --git a/lib/gitlab/metrics/web_transaction.rb b/lib/gitlab/metrics/web_transaction.rb index 3799aaebf1c..723ca576aab 100644 --- a/lib/gitlab/metrics/web_transaction.rb +++ b/lib/gitlab/metrics/web_transaction.rb @@ -3,6 +3,7 @@ module Gitlab class WebTransaction < Transaction CONTROLLER_KEY = 'action_controller.instance'.freeze ENDPOINT_KEY = 'api.endpoint'.freeze + ALLOWED_SUFFIXES = Set.new(%w[json js atom rss xml zip]) def initialize(env) super() @@ -32,9 +33,13 @@ module Gitlab # Devise exposes a method called "request_format" that does the below. # However, this method is not available to all controllers (e.g. certain # Doorkeeper controllers). As such we use the underlying code directly. - suffix = controller.request.format.try(:ref) + suffix = controller.request.format.try(:ref).to_s - if suffix && suffix != :html + # Sometimes the request format is set to silly data such as + # "application/xrds+xml" or actual URLs. To prevent such values from + # increasing the cardinality of our metrics, we limit the number of + # possible suffixes. + if suffix && ALLOWED_SUFFIXES.include?(suffix) action += ".#{suffix}" end diff --git a/lib/gitlab/verify/uploads.rb b/lib/gitlab/verify/uploads.rb index 01f09ab8df7..73fc43cb590 100644 --- a/lib/gitlab/verify/uploads.rb +++ b/lib/gitlab/verify/uploads.rb @@ -12,7 +12,7 @@ module Gitlab private def all_relation - Upload.all + Upload.all.preload(:model) end def local?(upload) diff --git a/lib/tasks/flay.rake b/lib/tasks/flay.rake index 4b4881cecb8..4bec013a141 100644 --- a/lib/tasks/flay.rake +++ b/lib/tasks/flay.rake @@ -1,6 +1,6 @@ desc 'Code duplication analyze via flay' task :flay do - output = `bundle exec flay --mass 35 app/ lib/gitlab/ 2> #{File::NULL}` + output = `bundle exec flay --mass 35 app/ lib/gitlab/ ee/ 2> #{File::NULL}` if output.include?("Similar code found") || output.include?("IDENTICAL code found") puts output diff --git a/lib/tasks/gettext.rake b/lib/tasks/gettext.rake index d52c419d66b..21998dd2f5b 100644 --- a/lib/tasks/gettext.rake +++ b/lib/tasks/gettext.rake @@ -4,7 +4,7 @@ namespace :gettext do # Customize list of translatable files # See: https://github.com/grosser/gettext_i18n_rails#customizing-list-of-translatable-files def files_to_translate - folders = %W(app lib config #{locale_path}).join(',') + folders = %W(ee app lib config #{locale_path}).join(',') exts = %w(rb erb haml slim rhtml js jsx vue handlebars hbs mustache).join(',') Dir.glob( @@ -16,7 +16,6 @@ namespace :gettext do # See: https://gitlab.com/gitlab-org/gitlab-ce/issues/33014#note_31218998 FileUtils.touch(File.join(Rails.root, 'locale/gitlab.pot')) - Rake::Task['gettext:pack'].invoke Rake::Task['gettext:po_to_json'].invoke end @@ -53,25 +52,34 @@ namespace :gettext do task :updated_check do # Removing all pre-translated files speeds up `gettext:find` as the # files don't need to be merged. - `rm locale/*/gitlab.po` + # Having `LC_MESSAGES/gitlab.mo files present also confuses the output. + FileUtils.rm Dir['locale/**/gitlab.*'] + + # Make sure we start out with a clean pot.file + `git checkout -- locale/gitlab.pot` # `gettext:find` writes touches to temp files to `stderr` which would cause - # `static-analysis` to report failures. We can ignore these - silence_stream(STDERR) { Rake::Task['gettext:find'].invoke } + # `static-analysis` to report failures. We can ignore these. + silence_stream($stderr) do + Rake::Task['gettext:find'].invoke + end - changed_files = `git diff --name-only`.lines.map(&:strip) + pot_diff = `git diff -- locale/gitlab.pot`.strip # reset the locale folder for potential next tasks `git checkout -- locale` - if changed_files.include?('locale/gitlab.pot') + if pot_diff.present? raise <<~MSG Newly translated strings found, please add them to `gitlab.pot` by running: - bundle exec rake gettext:find; git checkout -- locale/*/gitlab.po; + rm locale/**/gitlab.*; bin/rake gettext:find; git checkout -- locale/*/gitlab.po Then commit and push the resulting changes to `locale/gitlab.pot`. + The diff was: + + #{pot_diff} MSG end end diff --git a/lib/tasks/lint.rake b/lib/tasks/lint.rake index b5a9cddaacb..006fcdd31a4 100644 --- a/lib/tasks/lint.rake +++ b/lib/tasks/lint.rake @@ -17,13 +17,22 @@ unless Rails.env.production? Rake::Task['eslint'].invoke end + desc "GitLab | lint | Lint HAML files" + task :haml do + begin + Rake::Task['haml_lint'].invoke + rescue RuntimeError # The haml_lint tasks raise a RuntimeError + exit(1) + end + end + desc "GitLab | lint | Run several lint checks" task :all do status = 0 %w[ config_lint - haml_lint + lint:haml scss_lint flay gettext:lint @@ -39,13 +48,12 @@ unless Rails.env.production? $stderr.reopen(wr_err) begin - begin - Rake::Task[task].invoke - rescue RuntimeError # The haml_lint tasks raise a RuntimeError - exit(1) - end + Rake::Task[task].invoke rescue SystemExit => ex - msg = "*** Rake task #{task} failed with the following error(s):" + msg = "*** Rake task #{task} exited:" + raise ex + rescue => ex + msg = "*** Rake task #{task} raised #{ex.class}:" raise ex ensure $stdout.reopen(stdout) diff --git a/package.json b/package.json index cfe347c6eaa..06b07c37d2b 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,8 @@ "scripts": { "clean": "rm -rf public/assets tmp/cache/*-loader", "dev-server": "nodemon -w 'config/webpack.config.js' --exec 'webpack-dev-server --config config/webpack.config.js'", - "eslint": "eslint --max-warnings 0 --ext .js,.vue .", - "eslint-fix": "eslint --max-warnings 0 --ext .js,.vue --fix .", + "eslint": "eslint --max-warnings 0 --report-unused-disable-directives --ext .js,.vue .", + "eslint-fix": "eslint --max-warnings 0 --report-unused-disable-directives --ext .js,.vue --fix .", "eslint-report": "eslint --max-warnings 0 --ext .js,.vue --format html --output-file ./eslint-report.html --no-inline-config .", "karma": "BABEL_ENV=${BABEL_ENV:=karma} karma start --single-run true config/karma.config.js", "karma-coverage": "BABEL_ENV=coverage karma start --single-run true config/karma.config.js", @@ -46,10 +46,13 @@ module QA autoload :Runner, 'qa/factory/resource/runner' autoload :PersonalAccessToken, 'qa/factory/resource/personal_access_token' autoload :KubernetesCluster, 'qa/factory/resource/kubernetes_cluster' + autoload :Wiki, 'qa/factory/resource/wiki' end module Repository autoload :Push, 'qa/factory/repository/push' + autoload :ProjectPush, 'qa/factory/repository/project_push' + autoload :WikiPush, 'qa/factory/repository/wiki_push' end module Settings @@ -165,6 +168,16 @@ module QA autoload :Show, 'qa/page/project/operations/kubernetes/show' end end + + module Wiki + autoload :Edit, 'qa/page/project/wiki/edit' + autoload :New, 'qa/page/project/wiki/new' + autoload :Show, 'qa/page/project/wiki/show' + end + end + + module Shared + autoload :ClonePanel, 'qa/page/shared/clone_panel' end module Profile diff --git a/qa/qa/factory/repository/project_push.rb b/qa/qa/factory/repository/project_push.rb new file mode 100644 index 00000000000..48674c08a8d --- /dev/null +++ b/qa/qa/factory/repository/project_push.rb @@ -0,0 +1,34 @@ +module QA + module Factory + module Repository + class ProjectPush < Factory::Repository::Push + dependency Factory::Resource::Project, as: :project do |project| + project.name = 'project-with-code' + project.description = 'Project with repository' + end + + product :output do |factory| + factory.output + end + + def initialize + @file_name = 'file.txt' + @file_content = '# This is test project' + @commit_message = "This is a test commit" + @branch_name = 'master' + @new_branch = true + end + + def repository_uri + @repository_uri ||= begin + project.visit! + Page::Project::Show.act do + choose_repository_clone_http + repository_location.uri + end + end + end + end + end + end +end diff --git a/qa/qa/factory/repository/push.rb b/qa/qa/factory/repository/push.rb index 7c0d580c5ca..4f97e65b091 100644 --- a/qa/qa/factory/repository/push.rb +++ b/qa/qa/factory/repository/push.rb @@ -5,25 +5,17 @@ module QA module Repository class Push < Factory::Base attr_accessor :file_name, :file_content, :commit_message, - :branch_name, :new_branch, :output + :branch_name, :new_branch, :output, :repository_uri attr_writer :remote_branch - dependency Factory::Resource::Project, as: :project do |project| - project.name = 'project-with-code' - project.description = 'Project with repository' - end - - product :output do |factory| - factory.output - end - def initialize @file_name = 'file.txt' - @file_content = '# This is test project' + @file_content = '# This is test file' @commit_message = "This is a test commit" @branch_name = 'master' @new_branch = true + @repository_uri = "" end def remote_branch @@ -37,14 +29,8 @@ module QA end def fabricate! - project.visit! - Git::Repository.perform do |repository| - repository.uri = Page::Project::Show.act do - choose_repository_clone_http - repository_location.uri - end - + repository.uri = repository_uri repository.use_default_credentials repository.clone repository.configure_identity('GitLab QA', 'root@gitlab.com') diff --git a/qa/qa/factory/repository/wiki_push.rb b/qa/qa/factory/repository/wiki_push.rb new file mode 100644 index 00000000000..fb7c2bb660d --- /dev/null +++ b/qa/qa/factory/repository/wiki_push.rb @@ -0,0 +1,32 @@ +module QA + module Factory + module Repository + class WikiPush < Factory::Repository::Push + dependency Factory::Resource::Wiki, as: :wiki do |wiki| + wiki.title = 'Home' + wiki.content = '# My First Wiki Content' + wiki.message = 'Update home' + end + + def initialize + @file_name = 'Home.md' + @file_content = '# Welcome to My Wiki' + @commit_message = 'Updating Home Page' + @branch_name = 'master' + @new_branch = false + end + + def repository_uri + @repository_uri ||= begin + wiki.visit! + Page::Project::Wiki::Show.act do + go_to_clone_repository + choose_repository_clone_http + repository_location.uri + end + end + end + end + end + end +end diff --git a/qa/qa/factory/resource/branch.rb b/qa/qa/factory/resource/branch.rb index 4cabe7eab45..7fb0633ec90 100644 --- a/qa/qa/factory/resource/branch.rb +++ b/qa/qa/factory/resource/branch.rb @@ -31,13 +31,13 @@ module QA def fabricate! project.visit! - Factory::Repository::Push.fabricate! do |resource| + Factory::Repository::ProjectPush.fabricate! do |resource| resource.project = project resource.file_name = 'kick-off.txt' resource.commit_message = 'First commit' end - branch = Factory::Repository::Push.fabricate! do |resource| + branch = Factory::Repository::ProjectPush.fabricate! do |resource| resource.project = project resource.file_name = 'README.md' resource.commit_message = 'Add readme' diff --git a/qa/qa/factory/resource/merge_request.rb b/qa/qa/factory/resource/merge_request.rb index 7588ac5735d..24d3597d993 100644 --- a/qa/qa/factory/resource/merge_request.rb +++ b/qa/qa/factory/resource/merge_request.rb @@ -21,14 +21,14 @@ module QA project.name = 'project-with-merge-request' end - dependency Factory::Repository::Push, as: :target do |push, factory| + dependency Factory::Repository::ProjectPush, as: :target do |push, factory| factory.project.visit! push.project = factory.project push.branch_name = 'master' push.remote_branch = factory.target_branch end - dependency Factory::Repository::Push, as: :source do |push, factory| + dependency Factory::Repository::ProjectPush, as: :source do |push, factory| push.project = factory.project push.branch_name = factory.target_branch push.remote_branch = factory.source_branch diff --git a/qa/qa/factory/resource/wiki.rb b/qa/qa/factory/resource/wiki.rb new file mode 100644 index 00000000000..cc200a512d5 --- /dev/null +++ b/qa/qa/factory/resource/wiki.rb @@ -0,0 +1,25 @@ +module QA + module Factory + module Resource + class Wiki < Factory::Base + attr_accessor :title, :content, :message + + dependency Factory::Resource::Project, as: :project do |project| + project.name = 'project-for-wikis' + project.description = 'project for adding wikis' + end + + def fabricate! + Page::Menu::Side.act { click_wiki } + Page::Project::Wiki::New.perform do |page| + page.go_to_create_first_page + page.set_title(@title) + page.set_content(@content) + page.set_message(@message) + page.create_new_page + end + end + end + end + end +end diff --git a/qa/qa/page/menu/side.rb b/qa/qa/page/menu/side.rb index 3630b7e8568..6bf4825cf00 100644 --- a/qa/qa/page/menu/side.rb +++ b/qa/qa/page/menu/side.rb @@ -13,6 +13,7 @@ module QA element :top_level_items, '.sidebar-top-level-items' element :operations_section, "class: 'shortcuts-operations'" element :activity_link, "title: 'Activity'" + element :wiki_link_text, "Wiki" end view 'app/assets/javascripts/fly_out_nav.js' do @@ -61,6 +62,12 @@ module QA end end + def click_wiki + within_sidebar do + click_link('Wiki') + end + end + private def hover_settings diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb index 5bbef040330..1406edece17 100644 --- a/qa/qa/page/project/show.rb +++ b/qa/qa/page/project/show.rb @@ -2,11 +2,7 @@ module QA module Page module Project class Show < Page::Base - view 'app/views/shared/_clone_panel.html.haml' do - element :clone_dropdown - element :clone_options_dropdown, '.clone-options-dropdown' - element :project_repository_location, 'text_field_tag :project_clone' - end + include Page::Shared::ClonePanel view 'app/views/projects/_last_push.html.haml' do element :create_merge_request @@ -26,21 +22,6 @@ module QA element :branches_dropdown end - def choose_repository_clone_http - choose_repository_clone('HTTP', 'http') - end - - def choose_repository_clone_ssh - # It's not always beginning with ssh:// so detecting with @ - # would be more reliable because ssh would always contain it. - # We can't use .git because HTTP also contain that part. - choose_repository_clone('SSH', '@') - end - - def repository_location - Git::Location.new(find('#project_clone').value) - end - def project_name find('.qa-project-name').text end @@ -65,31 +46,11 @@ module QA click_element :create_merge_request end - def wait_for_push - sleep 5 - refresh - end - def go_to_new_issue click_element :new_menu_toggle click_link 'New issue' end - - private - - def choose_repository_clone(kind, detect_text) - wait(reload: false) do - click_element :clone_dropdown - - page.within('.clone-options-dropdown') do - click_link(kind) - end - - # Ensure git clone textbox was updated - repository_location.git_uri.include?(detect_text) - end - end end end end diff --git a/qa/qa/page/project/wiki/edit.rb b/qa/qa/page/project/wiki/edit.rb new file mode 100644 index 00000000000..6fa45569cc0 --- /dev/null +++ b/qa/qa/page/project/wiki/edit.rb @@ -0,0 +1,27 @@ +module QA + module Page + module Project + module Wiki + class Edit < Page::Base + view 'app/views/projects/wikis/_main_links.html.haml' do + element :new_page_link, 'New page' + element :page_history_link, 'Page history' + element :edit_page_link, 'Edit' + end + + def go_to_new_page + click_on 'New page' + end + + def got_to_view_history_page + click_on 'Page history' + end + + def go_to_edit_page + click_on 'Edit' + end + end + end + end + end +end diff --git a/qa/qa/page/project/wiki/new.rb b/qa/qa/page/project/wiki/new.rb new file mode 100644 index 00000000000..415b3835538 --- /dev/null +++ b/qa/qa/page/project/wiki/new.rb @@ -0,0 +1,45 @@ +module QA + module Page + module Project + module Wiki + class New < Page::Base + view 'app/views/projects/wikis/_form.html.haml' do + element :wiki_title_textbox, 'text_field :title' + element :wiki_content_textarea, "render 'projects/zen', f: f, attr: :content" + element :wiki_message_textbox, 'text_field :message' + element :save_changes_button, 'submit _("Save changes")' + element :create_page_button, 'submit s_("Wiki|Create page")' + end + + view 'app/views/shared/empty_states/_wikis.html.haml' do + element :create_link, 'Create your first page' + end + + def go_to_create_first_page + click_link 'Create your first page' + end + + def set_title(title) + fill_in 'wiki_title', with: title + end + + def set_content(content) + fill_in 'wiki_content', with: content + end + + def set_message(message) + fill_in 'wiki_message', with: message + end + + def save_changes + click_on 'Save changes' + end + + def create_new_page + click_on 'Create page' + end + end + end + end + end +end diff --git a/qa/qa/page/project/wiki/show.rb b/qa/qa/page/project/wiki/show.rb new file mode 100644 index 00000000000..044e514bab3 --- /dev/null +++ b/qa/qa/page/project/wiki/show.rb @@ -0,0 +1,19 @@ +module QA + module Page + module Project + module Wiki + class Show < Page::Base + include Page::Shared::ClonePanel + + view 'app/views/projects/wikis/pages.html.haml' do + element :clone_repository_link, 'Clone repository' + end + + def go_to_clone_repository + click_on 'Clone repository' + end + end + end + end + end +end diff --git a/qa/qa/page/shared/clone_panel.rb b/qa/qa/page/shared/clone_panel.rb new file mode 100644 index 00000000000..73e3dff956d --- /dev/null +++ b/qa/qa/page/shared/clone_panel.rb @@ -0,0 +1,50 @@ +module QA + module Page + module Shared + module ClonePanel + def self.included(base) + base.view 'app/views/shared/_clone_panel.html.haml' do + element :clone_dropdown + element :clone_options_dropdown, '.clone-options-dropdown' + element :project_repository_location, 'text_field_tag :project_clone' + end + end + + def choose_repository_clone_http + choose_repository_clone('HTTP', 'http') + end + + def choose_repository_clone_ssh + # It's not always beginning with ssh:// so detecting with @ + # would be more reliable because ssh would always contain it. + # We can't use .git because HTTP also contain that part. + choose_repository_clone('SSH', '@') + end + + def repository_location + Git::Location.new(find('#project_clone').value) + end + + def wait_for_push + sleep 5 + refresh + end + + private + + def choose_repository_clone(kind, detect_text) + wait(reload: false) do + click_element :clone_dropdown + + page.within('.clone-options-dropdown') do + click_link(kind) + end + + # Ensure git clone textbox was updated + repository_location.git_uri.include?(detect_text) + end + end + end + end + end +end diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb index 81d00d45753..2126ce6b234 100644 --- a/qa/qa/runtime/env.rb +++ b/qa/qa/runtime/env.rb @@ -3,6 +3,8 @@ module QA module Env extend self + attr_writer :user_type + # set to 'false' to have Chrome run visibly instead of headless def chrome_headless? (ENV['CHROME_HEADLESS'] =~ /^(false|no|0)$/i) != 0 @@ -20,7 +22,9 @@ module QA # By default, "standard" denotes a standard GitLab user login. # Set this to "ldap" if the user should be logged in via LDAP. def user_type - (ENV['GITLAB_USER_TYPE'] || 'standard').tap do |type| + return @user_type if defined?(@user_type) # rubocop:disable Gitlab/ModuleWithInstanceVariables + + ENV.fetch('GITLAB_USER_TYPE', 'standard').tap do |type| unless %w(ldap standard).include?(type) raise ArgumentError.new("Invalid user type '#{type}': must be 'ldap' or 'standard'") end diff --git a/qa/qa/specs/features/login/ldap_spec.rb b/qa/qa/specs/features/login/ldap_spec.rb index ac2bd5a3c39..737f4d10053 100644 --- a/qa/qa/specs/features/login/ldap_spec.rb +++ b/qa/qa/specs/features/login/ldap_spec.rb @@ -1,8 +1,12 @@ module QA feature 'LDAP user login', :ldap do + before do + Runtime::Env.user_type = 'ldap' + end + scenario 'user logs in using LDAP credentials' do Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_ldap_credentials } + Page::Main::Login.act { sign_in_using_credentials } # TODO, since `Signed in successfully` message was removed # this is the only way to tell if user is signed in correctly. diff --git a/qa/qa/specs/features/merge_request/rebase_spec.rb b/qa/qa/specs/features/merge_request/rebase_spec.rb index 2a44d42af6f..6a0ed4592c4 100644 --- a/qa/qa/specs/features/merge_request/rebase_spec.rb +++ b/qa/qa/specs/features/merge_request/rebase_spec.rb @@ -16,7 +16,7 @@ module QA merge_request.title = 'Needs rebasing' end - Factory::Repository::Push.fabricate! do |push| + Factory::Repository::ProjectPush.fabricate! do |push| push.project = project push.file_name = "other.txt" push.file_content = "New file added!" diff --git a/qa/qa/specs/features/merge_request/squash_spec.rb b/qa/qa/specs/features/merge_request/squash_spec.rb index dbbdf852a38..b68704154cf 100644 --- a/qa/qa/specs/features/merge_request/squash_spec.rb +++ b/qa/qa/specs/features/merge_request/squash_spec.rb @@ -13,7 +13,7 @@ module QA merge_request.title = 'Squashing commits' end - Factory::Repository::Push.fabricate! do |push| + Factory::Repository::ProjectPush.fabricate! do |push| push.project = project push.commit_message = 'to be squashed' push.branch_name = merge_request.source_branch diff --git a/qa/qa/specs/features/project/activity_spec.rb b/qa/qa/specs/features/project/activity_spec.rb index ba94ce8cf28..07ac7321aa2 100644 --- a/qa/qa/specs/features/project/activity_spec.rb +++ b/qa/qa/specs/features/project/activity_spec.rb @@ -4,7 +4,7 @@ module QA Runtime::Browser.visit(:gitlab, Page::Main::Login) Page::Main::Login.act { sign_in_using_credentials } - Factory::Repository::Push.fabricate! do |push| + Factory::Repository::ProjectPush.fabricate! do |push| push.file_name = 'README.md' push.file_content = '# This is a test project' push.commit_message = 'Add README.md' diff --git a/qa/qa/specs/features/project/auto_devops_spec.rb b/qa/qa/specs/features/project/auto_devops_spec.rb index 202a847d1a5..c50a13432f5 100644 --- a/qa/qa/specs/features/project/auto_devops_spec.rb +++ b/qa/qa/specs/features/project/auto_devops_spec.rb @@ -16,7 +16,7 @@ module QA end # Create Auto Devops compatible repo - Factory::Repository::Push.fabricate! do |push| + Factory::Repository::ProjectPush.fabricate! do |push| push.project = project push.directory = Pathname .new(__dir__) diff --git a/qa/qa/specs/features/project/deploy_key_clone_spec.rb b/qa/qa/specs/features/project/deploy_key_clone_spec.rb index 46b3e38c1c5..10e4cbb6906 100644 --- a/qa/qa/specs/features/project/deploy_key_clone_spec.rb +++ b/qa/qa/specs/features/project/deploy_key_clone_spec.rb @@ -75,7 +75,7 @@ module QA - docker YAML - Factory::Repository::Push.fabricate! do |resource| + Factory::Repository::ProjectPush.fabricate! do |resource| resource.project = @project resource.file_name = '.gitlab-ci.yml' resource.commit_message = 'Add .gitlab-ci.yml' diff --git a/qa/qa/specs/features/project/pipelines_spec.rb b/qa/qa/specs/features/project/pipelines_spec.rb index 74f6474443d..bdb3d671516 100644 --- a/qa/qa/specs/features/project/pipelines_spec.rb +++ b/qa/qa/specs/features/project/pipelines_spec.rb @@ -40,7 +40,7 @@ module QA runner.tags = %w[qa test] end - Factory::Repository::Push.fabricate! do |push| + Factory::Repository::ProjectPush.fabricate! do |push| push.project = project push.file_name = '.gitlab-ci.yml' push.commit_message = 'Add .gitlab-ci.yml' diff --git a/qa/qa/specs/features/project/wikis_spec.rb b/qa/qa/specs/features/project/wikis_spec.rb new file mode 100644 index 00000000000..49290a1a896 --- /dev/null +++ b/qa/qa/specs/features/project/wikis_spec.rb @@ -0,0 +1,45 @@ +module QA + feature 'Wiki Functionality', :core do + def login + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + end + + def validate_content(content) + expect(page).to have_content('Wiki was successfully updated') + expect(page).to have_content(/#{content}/) + end + + before do + login + end + + scenario 'User creates, edits, clones, and pushes to the wiki' do + wiki = Factory::Resource::Wiki.fabricate! do |resource| + resource.title = 'Home' + resource.content = '# My First Wiki Content' + resource.message = 'Update home' + end + + validate_content('My First Wiki Content') + + Page::Project::Wiki::Edit.act { go_to_edit_page } + Page::Project::Wiki::New.perform do |page| + page.set_content("My Second Wiki Content") + page.save_changes + end + + validate_content('My Second Wiki Content') + + Factory::Repository::WikiPush.fabricate! do |push| + push.wiki = wiki + push.file_name = 'Home.md' + push.file_content = '# My Third Wiki Content' + push.commit_message = 'Update Home.md' + end + Page::Menu::Side.act { click_wiki } + + expect(page).to have_content('My Third Wiki Content') + end + end +end diff --git a/qa/qa/specs/features/repository/protected_branches_spec.rb b/qa/qa/specs/features/repository/protected_branches_spec.rb index 491675875b9..ec3802e7a76 100644 --- a/qa/qa/specs/features/repository/protected_branches_spec.rb +++ b/qa/qa/specs/features/repository/protected_branches_spec.rb @@ -56,7 +56,7 @@ module QA end def push_new_file(branch) - Factory::Repository::Push.fabricate! do |resource| + Factory::Repository::ProjectPush.fabricate! do |resource| resource.project = project resource.file_name = 'new_file.md' resource.file_content = '# This is a new file' diff --git a/qa/qa/specs/features/repository/push_spec.rb b/qa/qa/specs/features/repository/push_spec.rb index 51d9c2c7fd2..16aaa2e6762 100644 --- a/qa/qa/specs/features/repository/push_spec.rb +++ b/qa/qa/specs/features/repository/push_spec.rb @@ -5,7 +5,7 @@ module QA Runtime::Browser.visit(:gitlab, Page::Main::Login) Page::Main::Login.act { sign_in_using_credentials } - Factory::Repository::Push.fabricate! do |push| + Factory::Repository::ProjectPush.fabricate! do |push| push.file_name = 'README.md' push.file_content = '# This is a test project' push.commit_message = 'Add README.md' diff --git a/scripts/trigger-build b/scripts/trigger-build index 526f5164ede..798bf1e82b7 100755 --- a/scripts/trigger-build +++ b/scripts/trigger-build @@ -165,6 +165,10 @@ module Trigger end JSON.parse(res.body)['status'].to_s.to_sym + rescue JSON::ParserError + # Ignore GitLab API hiccups. If GitLab is really down, we'll hit the job + # timeout anyway. + :running end end end diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index a412e74581d..7f5f0b76c51 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -337,7 +337,12 @@ describe Projects::MergeRequestsController do context 'when the sha parameter matches the source SHA' do def merge_with_sha(params = {}) - post :merge, base_params.merge(sha: merge_request.diff_head_sha).merge(params) + post_params = base_params.merge(sha: merge_request.diff_head_sha).merge(params) + if Gitlab.rails5? + post :merge, params: post_params, as: :json + else + post :merge, post_params + end end it 'returns :success' do diff --git a/spec/controllers/projects/pages_controller_spec.rb b/spec/controllers/projects/pages_controller_spec.rb index 11f54eef531..8d2fa6a1740 100644 --- a/spec/controllers/projects/pages_controller_spec.rb +++ b/spec/controllers/projects/pages_controller_spec.rb @@ -71,7 +71,7 @@ describe Projects::PagesController do { namespace_id: project.namespace, project_id: project, - project: { pages_https_only: false } + project: { pages_https_only: 'false' } } end @@ -96,7 +96,7 @@ describe Projects::PagesController do it 'calls the update service' do expect(Projects::UpdateService) .to receive(:new) - .with(project, user, request_params[:project]) + .with(project, user, ActionController::Parameters.new(request_params[:project]).permit!) .and_return(update_service) patch :update, request_params diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 705b30f0130..90e698925b6 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -597,6 +597,22 @@ describe ProjectsController do expect(parsed_body["Tags"]).to include("v1.0.0") expect(parsed_body["Commits"]).to include("123456") end + + context "when preferred language is Japanese" do + before do + user.update!(preferred_language: 'ja') + sign_in(user) + end + + it "gets a list of branches, tags and commits" do + get :refs, namespace_id: public_project.namespace, id: public_project, ref: "123456" + + parsed_body = JSON.parse(response.body) + expect(parsed_body["Branches"]).to include("master") + expect(parsed_body["Tags"]).to include("v1.0.0") + expect(parsed_body["Commits"]).to include("123456") + end + end end describe 'POST #preview_markdown' do diff --git a/spec/javascripts/.eslintrc.yml b/spec/javascripts/.eslintrc.yml index 8bceb2c50fc..78e2f3b521f 100644 --- a/spec/javascripts/.eslintrc.yml +++ b/spec/javascripts/.eslintrc.yml @@ -32,3 +32,7 @@ rules: - branch no-console: off prefer-arrow-callback: off + import/no-unresolved: + - error + - ignore: + - 'fixtures/blob' diff --git a/spec/javascripts/activities_spec.js b/spec/javascripts/activities_spec.js index 5dbdcd24296..068b8eb65bc 100644 --- a/spec/javascripts/activities_spec.js +++ b/spec/javascripts/activities_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable no-unused-expressions, no-prototype-builtins, no-new, no-shadow, max-len */ +/* eslint-disable no-unused-expressions, no-prototype-builtins, no-new, no-shadow */ import $ from 'jquery'; import 'vendor/jquery.endless-scroll'; diff --git a/spec/javascripts/awards_handler_spec.js b/spec/javascripts/awards_handler_spec.js index e81055bc08f..ff6020c8fdd 100644 --- a/spec/javascripts/awards_handler_spec.js +++ b/spec/javascripts/awards_handler_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, no-unused-expressions, comma-dangle, new-parens, no-unused-vars, quotes, jasmine/no-spec-dupes, prefer-template, max-len */ +/* eslint-disable no-var, one-var, one-var-declaration-per-line, no-unused-expressions, comma-dangle, no-unused-vars, quotes, prefer-template, max-len */ import $ from 'jquery'; import Cookies from 'js-cookie'; diff --git a/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js b/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js index acd0aaf2a86..c726fa8e428 100644 --- a/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js +++ b/spec/javascripts/blob/balsamiq/balsamiq_viewer_integration_spec.js @@ -1,5 +1,3 @@ -/* eslint-disable import/no-unresolved */ - import BalsamiqViewer from '~/blob/balsamiq/balsamiq_viewer'; import bmprPath from '../../fixtures/blob/balsamiq/test.bmpr'; diff --git a/spec/javascripts/blob/pdf/index_spec.js b/spec/javascripts/blob/pdf/index_spec.js index 51bf3086627..bbe2500f8e3 100644 --- a/spec/javascripts/blob/pdf/index_spec.js +++ b/spec/javascripts/blob/pdf/index_spec.js @@ -1,5 +1,3 @@ -/* eslint-disable import/no-unresolved */ - import renderPDF from '~/blob/pdf'; import testPDF from '../../fixtures/blob/pdf/test.pdf'; diff --git a/spec/javascripts/boards/boards_store_spec.js b/spec/javascripts/boards/boards_store_spec.js index 3f5ed4f3d07..f7af099b3bf 100644 --- a/spec/javascripts/boards/boards_store_spec.js +++ b/spec/javascripts/boards/boards_store_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable comma-dangle, one-var, no-unused-vars */ +/* eslint-disable comma-dangle, no-unused-vars */ /* global ListIssue */ import Vue from 'vue'; diff --git a/spec/javascripts/bootstrap_jquery_spec.js b/spec/javascripts/bootstrap_jquery_spec.js index 0fd6f9dc810..052465d8d88 100644 --- a/spec/javascripts/bootstrap_jquery_spec.js +++ b/spec/javascripts/bootstrap_jquery_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable space-before-function-paren, no-var */ +/* eslint-disable no-var */ import $ from 'jquery'; import '~/commons/bootstrap'; diff --git a/spec/javascripts/gl_dropdown_spec.js b/spec/javascripts/gl_dropdown_spec.js index 175f386b60e..af58dff7da7 100644 --- a/spec/javascripts/gl_dropdown_spec.js +++ b/spec/javascripts/gl_dropdown_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable comma-dangle, no-param-reassign, no-unused-expressions, max-len */ +/* eslint-disable comma-dangle, no-param-reassign */ import $ from 'jquery'; import GLDropdown from '~/gl_dropdown'; diff --git a/spec/javascripts/gl_field_errors_spec.js b/spec/javascripts/gl_field_errors_spec.js index 108e0064c47..2839020b2ca 100644 --- a/spec/javascripts/gl_field_errors_spec.js +++ b/spec/javascripts/gl_field_errors_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable space-before-function-paren, arrow-body-style */ +/* eslint-disable arrow-body-style */ import $ from 'jquery'; import GlFieldErrors from '~/gl_field_errors'; diff --git a/spec/javascripts/helpers/vue_resource_helper.js b/spec/javascripts/helpers/vue_resource_helper.js index 0d1bf5e2e80..70b7ec4e574 100644 --- a/spec/javascripts/helpers/vue_resource_helper.js +++ b/spec/javascripts/helpers/vue_resource_helper.js @@ -5,7 +5,6 @@ export const headersInterceptor = (request, next) => { response.headers.forEach((value, key) => { headers[key] = value; }); - // eslint-disable-next-line no-param-reassign response.headers = headers; }); }; diff --git a/spec/javascripts/issuable_time_tracker_spec.js b/spec/javascripts/issuable_time_tracker_spec.js index ba9040524b1..5add150f874 100644 --- a/spec/javascripts/issuable_time_tracker_spec.js +++ b/spec/javascripts/issuable_time_tracker_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable no-unused-vars, space-before-function-paren, func-call-spacing, no-spaced-func, semi, max-len, quotes, space-infix-ops, padded-blocks */ +/* eslint-disable no-unused-vars, func-call-spacing, no-spaced-func, semi, quotes, space-infix-ops, max-len */ import $ from 'jquery'; import Vue from 'vue'; diff --git a/spec/javascripts/issue_spec.js b/spec/javascripts/issue_spec.js index 047ecab27db..e12419b835d 100644 --- a/spec/javascripts/issue_spec.js +++ b/spec/javascripts/issue_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable space-before-function-paren, one-var, one-var-declaration-per-line, no-use-before-define, comma-dangle, max-len */ +/* eslint-disable one-var, one-var-declaration-per-line, no-use-before-define, comma-dangle */ import $ from 'jquery'; import MockAdapter from 'axios-mock-adapter'; diff --git a/spec/javascripts/job_spec.js b/spec/javascripts/job_spec.js index da00b615c9b..79e375aa02e 100644 --- a/spec/javascripts/job_spec.js +++ b/spec/javascripts/job_spec.js @@ -304,7 +304,6 @@ describe('Job', () => { describe('getBuildTrace', () => { it('should request build trace with state parameter', (done) => { spyOn(axios, 'get').and.callThrough(); - // eslint-disable-next-line no-new job = new Job(); setTimeout(() => { diff --git a/spec/javascripts/line_highlighter_spec.js b/spec/javascripts/line_highlighter_spec.js index d2bdc9e160c..8cf0017f4d8 100644 --- a/spec/javascripts/line_highlighter_spec.js +++ b/spec/javascripts/line_highlighter_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable space-before-function-paren, no-var, no-param-reassign, quotes, prefer-template, no-else-return, new-cap, dot-notation, no-return-assign, comma-dangle, no-new, one-var, one-var-declaration-per-line, jasmine/no-spec-dupes, no-underscore-dangle, max-len */ +/* eslint-disable no-var, quotes, prefer-template, no-else-return, dot-notation, no-return-assign, comma-dangle, no-new, one-var, one-var-declaration-per-line, no-underscore-dangle, max-len */ import $ from 'jquery'; import LineHighlighter from '~/line_highlighter'; diff --git a/spec/javascripts/merge_request_spec.js b/spec/javascripts/merge_request_spec.js index 74ceff76d37..22eb0ad7143 100644 --- a/spec/javascripts/merge_request_spec.js +++ b/spec/javascripts/merge_request_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable space-before-function-paren, no-return-assign */ +/* eslint-disable no-return-assign */ import $ from 'jquery'; import MockAdapter from 'axios-mock-adapter'; diff --git a/spec/javascripts/mini_pipeline_graph_dropdown_spec.js b/spec/javascripts/mini_pipeline_graph_dropdown_spec.js index 009b3fd75b7..1879424c629 100644 --- a/spec/javascripts/mini_pipeline_graph_dropdown_spec.js +++ b/spec/javascripts/mini_pipeline_graph_dropdown_spec.js @@ -1,5 +1,3 @@ -/* eslint-disable no-new */ - import $ from 'jquery'; import MockAdapter from 'axios-mock-adapter'; import axios from '~/lib/utils/axios_utils'; diff --git a/spec/javascripts/monitoring/mock_data.js b/spec/javascripts/monitoring/mock_data.js index 50da6da2e07..799d03f6b57 100644 --- a/spec/javascripts/monitoring/mock_data.js +++ b/spec/javascripts/monitoring/mock_data.js @@ -1,5 +1,3 @@ -/* eslint-disable quote-props, indent, comma-dangle */ - export const mockApiEndpoint = `${gl.TEST_HOST}/monitoring/mock`; export const metricsGroupsAPIResponse = { diff --git a/spec/javascripts/new_branch_spec.js b/spec/javascripts/new_branch_spec.js index 5e5d8f8f34f..122e5bc58b2 100644 --- a/spec/javascripts/new_branch_spec.js +++ b/spec/javascripts/new_branch_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable space-before-function-paren, one-var, no-var, one-var-declaration-per-line, no-return-assign, quotes, max-len */ +/* eslint-disable one-var, no-var, one-var-declaration-per-line, no-return-assign, quotes, max-len */ import $ from 'jquery'; import NewBranchForm from '~/new_branch_form'; diff --git a/spec/javascripts/notes_spec.js b/spec/javascripts/notes_spec.js index acbf23e2007..2854263a25a 100644 --- a/spec/javascripts/notes_spec.js +++ b/spec/javascripts/notes_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable space-before-function-paren, no-unused-expressions, no-var, object-shorthand, comma-dangle, max-len */ +/* eslint-disable no-unused-expressions, no-var, object-shorthand */ import $ from 'jquery'; import _ from 'underscore'; import MockAdapter from 'axios-mock-adapter'; diff --git a/spec/javascripts/pdf/index_spec.js b/spec/javascripts/pdf/index_spec.js index bebed432f91..69230bb0937 100644 --- a/spec/javascripts/pdf/index_spec.js +++ b/spec/javascripts/pdf/index_spec.js @@ -1,5 +1,3 @@ -/* eslint-disable import/no-unresolved */ - import Vue from 'vue'; import { PDFJS } from 'vendor/pdf'; import workerSrc from 'vendor/pdf.worker.min'; diff --git a/spec/javascripts/pdf/page_spec.js b/spec/javascripts/pdf/page_spec.js index ac5b21e8f6c..9c686748c10 100644 --- a/spec/javascripts/pdf/page_spec.js +++ b/spec/javascripts/pdf/page_spec.js @@ -1,5 +1,3 @@ -/* eslint-disable import/no-unresolved */ - import Vue from 'vue'; import pdfjsLib from 'vendor/pdf'; import workerSrc from 'vendor/pdf.worker.min'; diff --git a/spec/javascripts/right_sidebar_spec.js b/spec/javascripts/right_sidebar_spec.js index e264b16335f..6d49536a712 100644 --- a/spec/javascripts/right_sidebar_spec.js +++ b/spec/javascripts/right_sidebar_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable space-before-function-paren, no-var, one-var, one-var-declaration-per-line, new-parens, no-return-assign, new-cap, vars-on-top, max-len */ +/* eslint-disable no-var, one-var, one-var-declaration-per-line, no-return-assign, vars-on-top, max-len */ import $ from 'jquery'; import MockAdapter from 'axios-mock-adapter'; diff --git a/spec/javascripts/search_autocomplete_spec.js b/spec/javascripts/search_autocomplete_spec.js index 4f515f98a7e..86c001678c5 100644 --- a/spec/javascripts/search_autocomplete_spec.js +++ b/spec/javascripts/search_autocomplete_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable space-before-function-paren, max-len, no-var, one-var, one-var-declaration-per-line, no-unused-expressions, consistent-return, no-param-reassign, default-case, no-return-assign, comma-dangle, object-shorthand, prefer-template, quotes, new-parens, vars-on-top, new-cap, max-len */ +/* eslint-disable max-len, no-var, one-var, one-var-declaration-per-line, no-unused-expressions, consistent-return, no-param-reassign, default-case, no-return-assign, object-shorthand, prefer-template, vars-on-top, max-len */ import $ from 'jquery'; import '~/gl_dropdown'; diff --git a/spec/javascripts/signin_tabs_memoizer_spec.js b/spec/javascripts/signin_tabs_memoizer_spec.js index 423432c9e5d..9d3905fa1d8 100644 --- a/spec/javascripts/signin_tabs_memoizer_spec.js +++ b/spec/javascripts/signin_tabs_memoizer_spec.js @@ -45,6 +45,21 @@ import SigninTabsMemoizer from '~/pages/sessions/new/signin_tabs_memoizer'; expect(fakeTab.click).toHaveBeenCalled(); }); + it('clicks the first tab if value in local storage is bad', () => { + createMemoizer().saveData('#bogus'); + const fakeTab = { + click: () => {}, + }; + spyOn(document, 'querySelector').and.callFake(selector => (selector === `${tabSelector} a[href="#bogus"]` ? null : fakeTab)); + spyOn(fakeTab, 'click'); + + memo.bootstrap(); + + // verify that triggers click on stored selector and fallback + expect(document.querySelector.calls.allArgs()).toEqual([['ul.new-session-tabs a[href="#bogus"]'], ['ul.new-session-tabs a']]); + expect(fakeTab.click).toHaveBeenCalled(); + }); + it('saves last selected tab on change', () => { createMemoizer(); diff --git a/spec/javascripts/syntax_highlight_spec.js b/spec/javascripts/syntax_highlight_spec.js index 0d1fa680e00..1c3dac3584e 100644 --- a/spec/javascripts/syntax_highlight_spec.js +++ b/spec/javascripts/syntax_highlight_spec.js @@ -1,4 +1,4 @@ -/* eslint-disable space-before-function-paren, no-var, no-return-assign, quotes */ +/* eslint-disable no-var, no-return-assign, quotes */ import $ from 'jquery'; import syntaxHighlight from '~/syntax_highlight'; diff --git a/spec/javascripts/u2f/mock_u2f_device.js b/spec/javascripts/u2f/mock_u2f_device.js index 8fec6ae3fa4..012a1cefbbf 100644 --- a/spec/javascripts/u2f/mock_u2f_device.js +++ b/spec/javascripts/u2f/mock_u2f_device.js @@ -1,5 +1,4 @@ -/* eslint-disable prefer-rest-params, wrap-iife, -no-unused-expressions, no-return-assign, no-param-reassign */ +/* eslint-disable wrap-iife, no-unused-expressions, no-return-assign, no-param-reassign */ export default class MockU2FDevice { constructor() { diff --git a/spec/lib/gitlab/favicon_spec.rb b/spec/lib/gitlab/favicon_spec.rb index f36111a4946..122dcd9634c 100644 --- a/spec/lib/gitlab/favicon_spec.rb +++ b/spec/lib/gitlab/favicon_spec.rb @@ -21,6 +21,21 @@ RSpec.describe Gitlab::Favicon, :request_store do create :appearance, favicon: fixture_file_upload('spec/fixtures/dk.png') expect(described_class.main).to match %r{/uploads/-/system/appearance/favicon/\d+/dk.png} end + + context 'asset host' do + before do + allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new('production')) + end + + it 'returns a relative url when the asset host is not configured' do + expect(described_class.main).to match %r{^/assets/favicon-(?:\h+).png$} + end + + it 'returns a full url when the asset host is configured' do + allow(Gitlab::Application.config).to receive(:asset_host).and_return('http://assets.local') + expect(described_class.main).to match %r{^http://localhost/assets/favicon-(?:\h+).png$} + end + end end describe '.status_overlay' do diff --git a/spec/lib/gitlab/kubernetes/helm/api_spec.rb b/spec/lib/gitlab/kubernetes/helm/api_spec.rb index 740466ea5cb..aa7e43dfb16 100644 --- a/spec/lib/gitlab/kubernetes/helm/api_spec.rb +++ b/spec/lib/gitlab/kubernetes/helm/api_spec.rb @@ -7,13 +7,7 @@ describe Gitlab::Kubernetes::Helm::Api do let(:namespace) { Gitlab::Kubernetes::Namespace.new(gitlab_namespace, client) } let(:application) { create(:clusters_applications_prometheus) } - let(:command) do - Gitlab::Kubernetes::Helm::InstallCommand.new( - application.name, - chart: application.chart, - values: application.values - ) - end + let(:command) { application.install_command } subject { helm } diff --git a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb index 547f3f1752c..25c6fa3b9a3 100644 --- a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb +++ b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb @@ -3,44 +3,60 @@ require 'rails_helper' describe Gitlab::Kubernetes::Helm::InstallCommand do let(:application) { create(:clusters_applications_prometheus) } let(:namespace) { Gitlab::Kubernetes::Helm::NAMESPACE } - - let(:install_command) do - described_class.new( - application.name, - chart: application.chart, - values: application.values - ) - end + let(:install_command) { application.install_command } subject { install_command } - it_behaves_like 'helm commands' do - let(:commands) do - <<~EOS + context 'for ingress' do + let(:application) { create(:clusters_applications_ingress) } + + it_behaves_like 'helm commands' do + let(:commands) do + <<~EOS helm init --client-only >/dev/null helm install #{application.chart} --name #{application.name} --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null - EOS + EOS + end + end + end + + context 'for prometheus' do + let(:application) { create(:clusters_applications_prometheus) } + + it_behaves_like 'helm commands' do + let(:commands) do + <<~EOS + helm init --client-only >/dev/null + helm install #{application.chart} --name #{application.name} --version #{application.version} --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null + EOS + end end end - context 'with an application with a repository' do + context 'for runner' do let(:ci_runner) { create(:ci_runner) } let(:application) { create(:clusters_applications_runner, runner: ci_runner) } - let(:install_command) do - described_class.new( - application.name, - chart: application.chart, - values: application.values, - repository: application.repository - ) + + it_behaves_like 'helm commands' do + let(:commands) do + <<~EOS + helm init --client-only >/dev/null + helm repo add #{application.name} #{application.repository} + helm install #{application.chart} --name #{application.name} --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null + EOS + end end + end + + context 'for jupyter' do + let(:application) { create(:clusters_applications_jupyter) } it_behaves_like 'helm commands' do let(:commands) do <<~EOS - helm init --client-only >/dev/null - helm repo add #{application.name} #{application.repository} - helm install #{application.chart} --name #{application.name} --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null + helm init --client-only >/dev/null + helm repo add #{application.name} #{application.repository} + helm install #{application.chart} --name #{application.name} --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null EOS end end diff --git a/spec/lib/gitlab/metrics/samplers/influx_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/influx_sampler_spec.rb index f66451c5188..81954fcf8c5 100644 --- a/spec/lib/gitlab/metrics/samplers/influx_sampler_spec.rb +++ b/spec/lib/gitlab/metrics/samplers/influx_sampler_spec.rb @@ -3,10 +3,6 @@ require 'spec_helper' describe Gitlab::Metrics::Samplers::InfluxSampler do let(:sampler) { described_class.new(5) } - after do - Allocations.stop if Gitlab::Metrics.mri? - end - describe '#start' do it 'runs once and gathers a sample at a given interval' do expect(sampler).to receive(:sleep).with(a_kind_of(Numeric)).twice diff --git a/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb b/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb index 54781dd52fc..091645ee86f 100644 --- a/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb +++ b/spec/lib/gitlab/metrics/samplers/ruby_sampler_spec.rb @@ -8,10 +8,6 @@ describe Gitlab::Metrics::Samplers::RubySampler do allow(Gitlab::Metrics::NullMetric).to receive(:instance).and_return(null_metric) end - after do - Allocations.stop if Gitlab::Metrics.mri? - end - describe '#sample' do it 'samples various statistics' do expect(Gitlab::Metrics::System).to receive(:memory_usage) diff --git a/spec/lib/gitlab/metrics/web_transaction_spec.rb b/spec/lib/gitlab/metrics/web_transaction_spec.rb index 6eb0600f49e..0b3b23e930f 100644 --- a/spec/lib/gitlab/metrics/web_transaction_spec.rb +++ b/spec/lib/gitlab/metrics/web_transaction_spec.rb @@ -194,7 +194,7 @@ describe Gitlab::Metrics::WebTransaction do expect(transaction.action).to eq('TestController#show') end - context 'when the response content type is not :html' do + context 'when the request content type is not :html' do let(:request) { double(:request, format: double(:format, ref: :json)) } it 'appends the mime type to the transaction action' do @@ -202,6 +202,15 @@ describe Gitlab::Metrics::WebTransaction do expect(transaction.action).to eq('TestController#show.json') end end + + context 'when the request content type is not' do + let(:request) { double(:request, format: double(:format, ref: 'http://example.com')) } + + it 'does not append the MIME type to the transaction action' do + expect(transaction.labels).to eq({ controller: 'TestController', action: 'show' }) + expect(transaction.action).to eq('TestController#show') + end + end end it 'returns no labels when no route information is present in env' do diff --git a/spec/lib/gitlab/verify/uploads_spec.rb b/spec/lib/gitlab/verify/uploads_spec.rb index 296866d3319..38c30fab1ba 100644 --- a/spec/lib/gitlab/verify/uploads_spec.rb +++ b/spec/lib/gitlab/verify/uploads_spec.rb @@ -47,20 +47,49 @@ describe Gitlab::Verify::Uploads do before do stub_uploads_object_storage(AvatarUploader) upload.update!(store: ObjectStorage::Store::REMOTE) - expect(CarrierWave::Storage::Fog::File).to receive(:new).and_return(file) end - it 'passes uploads in object storage that exist' do - expect(file).to receive(:exists?).and_return(true) + describe 'returned hash object' do + before do + expect(CarrierWave::Storage::Fog::File).to receive(:new).and_return(file) + end - expect(failures).to eq({}) + it 'passes uploads in object storage that exist' do + expect(file).to receive(:exists?).and_return(true) + + expect(failures).to eq({}) + end + + it 'fails uploads in object storage that do not exist' do + expect(file).to receive(:exists?).and_return(false) + + expect(failures.keys).to contain_exactly(upload) + expect(failure).to include('Remote object does not exist') + end end - it 'fails uploads in object storage that do not exist' do - expect(file).to receive(:exists?).and_return(false) + describe 'performance' do + before do + allow(file).to receive(:exists?) + allow(CarrierWave::Storage::Fog::File).to receive(:new).and_return(file) + end + + it "avoids N+1 queries" do + control_count = ActiveRecord::QueryRecorder.new { perform_task } + + # Create additional uploads in object storage + projects = create_list(:project, 3, :with_avatar) + uploads = projects.flat_map(&:uploads) + uploads.each do |upload| + upload.update!(store: ObjectStorage::Store::REMOTE) + end + + expect { perform_task }.not_to exceed_query_limit(control_count) + end - expect(failures.keys).to contain_exactly(upload) - expect(failure).to include('Remote object does not exist') + def perform_task + described_class.new(batch_size: 100).run_batches { } + end end end end diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index 775ca4ba0eb..a9a45367b4a 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -416,16 +416,10 @@ describe Notify do end it 'has the correct subject and body' do - reasons = %w[foo bar] - - allow_any_instance_of(MergeRequestPresenter).to receive(:unmergeable_reasons).and_return(reasons) aggregate_failures do is_expected.to have_referable_subject(merge_request, reply: true) is_expected.to have_body_text(project_merge_request_path(project, merge_request)) - is_expected.to have_body_text('following reasons:') - reasons.each do |reason| - is_expected.to have_body_text(reason) - end + is_expected.to have_body_text('due to conflict.') end end end diff --git a/spec/models/clusters/applications/ingress_spec.rb b/spec/models/clusters/applications/ingress_spec.rb index a47a07d908d..bb5b2ef3a47 100644 --- a/spec/models/clusters/applications/ingress_spec.rb +++ b/spec/models/clusters/applications/ingress_spec.rb @@ -73,6 +73,7 @@ describe Clusters::Applications::Ingress do it 'should be initialized with ingress arguments' do expect(subject.name).to eq('ingress') expect(subject.chart).to eq('stable/nginx-ingress') + expect(subject.version).to be_nil expect(subject.values).to eq(ingress.values) end end diff --git a/spec/models/clusters/applications/jupyter_spec.rb b/spec/models/clusters/applications/jupyter_spec.rb index ca48a1d8072..65750141e65 100644 --- a/spec/models/clusters/applications/jupyter_spec.rb +++ b/spec/models/clusters/applications/jupyter_spec.rb @@ -36,6 +36,7 @@ describe Clusters::Applications::Jupyter do it 'should be initialized with 4 arguments' do expect(subject.name).to eq('jupyter') expect(subject.chart).to eq('jupyter/jupyterhub') + expect(subject.version).to be_nil expect(subject.repository).to eq('https://jupyterhub.github.io/helm-chart/') expect(subject.values).to eq(jupyter.values) end diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb index d2302583ac8..efd57040005 100644 --- a/spec/models/clusters/applications/prometheus_spec.rb +++ b/spec/models/clusters/applications/prometheus_spec.rb @@ -109,6 +109,7 @@ describe Clusters::Applications::Prometheus do it 'should be initialized with 3 arguments' do expect(subject.name).to eq('prometheus') expect(subject.chart).to eq('stable/prometheus') + expect(subject.version).to eq('6.7.3') expect(subject.values).to eq(prometheus.values) end end diff --git a/spec/models/clusters/applications/runner_spec.rb b/spec/models/clusters/applications/runner_spec.rb index 3ef59457c5f..b12500d0acd 100644 --- a/spec/models/clusters/applications/runner_spec.rb +++ b/spec/models/clusters/applications/runner_spec.rb @@ -31,6 +31,7 @@ describe Clusters::Applications::Runner do it 'should be initialized with 4 arguments' do expect(subject.name).to eq('runner') expect(subject.chart).to eq('runner/gitlab-runner') + expect(subject.version).to be_nil expect(subject.repository).to eq('https://charts.gitlab.io') expect(subject.values).to eq(gitlab_runner.values) end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 3f028b3bd5c..7ae70c3afb4 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -1324,6 +1324,7 @@ describe MergeRequest do context 'when broken' do before do allow(subject).to receive(:broken?) { true } + allow(project.repository).to receive(:can_be_merged?).and_return(false) end it 'becomes unmergeable' do @@ -2150,9 +2151,11 @@ describe MergeRequest do before do allow(NotificationService).to receive(:new).and_return(notification_service) allow(TodoService).to receive(:new).and_return(todo_service) + + allow(subject.project.repository).to receive(:can_be_merged?).and_return(false) end - it 'notifies, but does not notify again if rechecking still results in cannot_be_merged' do + it 'notifies conflict, but does not notify again if rechecking still results in cannot_be_merged' do expect(notification_service).to receive(:merge_request_unmergeable).with(subject).once expect(todo_service).to receive(:merge_request_became_unmergeable).with(subject).once @@ -2161,7 +2164,7 @@ describe MergeRequest do subject.mark_as_unmergeable end - it 'notifies whenever merge request is newly unmergeable' do + it 'notifies conflict, whenever newly unmergeable' do expect(notification_service).to receive(:merge_request_unmergeable).with(subject).twice expect(todo_service).to receive(:merge_request_became_unmergeable).with(subject).twice @@ -2171,6 +2174,15 @@ describe MergeRequest do subject.mark_as_unchecked subject.mark_as_unmergeable end + + it 'does not notify whenever merge request is newly unmergeable due to other reasons' do + allow(subject.project.repository).to receive(:can_be_merged?).and_return(true) + + expect(notification_service).not_to receive(:merge_request_unmergeable) + expect(todo_service).not_to receive(:merge_request_became_unmergeable) + + subject.mark_as_unmergeable + end end describe 'check_state?' do diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index b6df048d4ca..d817a8376f4 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -434,44 +434,34 @@ describe Repository do end describe '#can_be_merged?' do - shared_examples 'can be merged' do - context 'mergeable branches' do - subject { repository.can_be_merged?('0b4bc9a49b562e85de7cc9e834518ea6828729b9', 'master') } + context 'mergeable branches' do + subject { repository.can_be_merged?('0b4bc9a49b562e85de7cc9e834518ea6828729b9', 'master') } - it { is_expected.to be_truthy } - end - - context 'non-mergeable branches without conflict sides missing' do - subject { repository.can_be_merged?('bb5206fee213d983da88c47f9cf4cc6caf9c66dc', 'feature') } - - it { is_expected.to be_falsey } - end + it { is_expected.to be_truthy } + end - context 'non-mergeable branches with conflict sides missing' do - subject { repository.can_be_merged?('conflict-missing-side', 'conflict-start') } + context 'non-mergeable branches without conflict sides missing' do + subject { repository.can_be_merged?('bb5206fee213d983da88c47f9cf4cc6caf9c66dc', 'feature') } - it { is_expected.to be_falsey } - end + it { is_expected.to be_falsey } + end - context 'non merged branch' do - subject { repository.merged_to_root_ref?('fix') } + context 'non-mergeable branches with conflict sides missing' do + subject { repository.can_be_merged?('conflict-missing-side', 'conflict-start') } - it { is_expected.to be_falsey } - end + it { is_expected.to be_falsey } + end - context 'non existent branch' do - subject { repository.merged_to_root_ref?('non_existent_branch') } + context 'non merged branch' do + subject { repository.merged_to_root_ref?('fix') } - it { is_expected.to be_nil } - end + it { is_expected.to be_falsey } end - context 'when Gitaly can_be_merged feature is enabled' do - it_behaves_like 'can be merged' - end + context 'non existent branch' do + subject { repository.merged_to_root_ref?('non_existent_branch') } - context 'when Gitaly can_be_merged feature is disabled', :disable_gitaly do - it_behaves_like 'can be merged' + it { is_expected.to be_nil } end end diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb index 6ac151f92f3..6d4676c25a5 100644 --- a/spec/policies/project_policy_spec.rb +++ b/spec/policies/project_policy_spec.rb @@ -151,6 +151,44 @@ describe ProjectPolicy do end end + context 'builds feature' do + subject { described_class.new(owner, project) } + + it 'disallows all permissions when the feature is disabled' do + project.project_feature.update(builds_access_level: ProjectFeature::DISABLED) + + builds_permissions = [ + :create_pipeline, :update_pipeline, :admin_pipeline, :destroy_pipeline, + :create_build, :read_build, :update_build, :admin_build, :destroy_build, + :create_pipeline_schedule, :read_pipeline_schedule, :update_pipeline_schedule, :admin_pipeline_schedule, :destroy_pipeline_schedule, + :create_environment, :read_environment, :update_environment, :admin_environment, :destroy_environment, + :create_cluster, :read_cluster, :update_cluster, :admin_cluster, :destroy_cluster, + :create_deployment, :read_deployment, :update_deployment, :admin_deployment, :destroy_deployment + ] + + expect_disallowed(*builds_permissions) + end + end + + context 'repository feature' do + subject { described_class.new(owner, project) } + + it 'disallows all permissions when the feature is disabled' do + project.project_feature.update(repository_access_level: ProjectFeature::DISABLED) + + repository_permissions = [ + :create_pipeline, :update_pipeline, :admin_pipeline, :destroy_pipeline, + :create_build, :read_build, :update_build, :admin_build, :destroy_build, + :create_pipeline_schedule, :read_pipeline_schedule, :update_pipeline_schedule, :admin_pipeline_schedule, :destroy_pipeline_schedule, + :create_environment, :read_environment, :update_environment, :admin_environment, :destroy_environment, + :create_cluster, :read_cluster, :update_cluster, :admin_cluster, :destroy_cluster, + :create_deployment, :read_deployment, :update_deployment, :admin_deployment, :destroy_deployment + ] + + expect_disallowed(*repository_permissions) + end + end + shared_examples 'archived project policies' do let(:feature_write_abilities) do described_class::READONLY_FEATURES_WHEN_ARCHIVED.flat_map do |feature| diff --git a/spec/presenters/merge_request_presenter_spec.rb b/spec/presenters/merge_request_presenter_spec.rb index d5fb4a7742c..e3b37739e8e 100644 --- a/spec/presenters/merge_request_presenter_spec.rb +++ b/spec/presenters/merge_request_presenter_spec.rb @@ -70,41 +70,6 @@ describe MergeRequestPresenter do end end - describe "#unmergeable_reasons" do - let(:presenter) { described_class.new(resource, current_user: user) } - - before do - # Mergeable base state - allow(resource).to receive(:has_no_commits?).and_return(false) - allow(resource).to receive(:source_branch_exists?).and_return(true) - allow(resource).to receive(:target_branch_exists?).and_return(true) - allow(resource.project.repository).to receive(:can_be_merged?).and_return(true) - end - - it "handles mergeable request" do - expect(presenter.unmergeable_reasons).to eq([]) - end - - it "handles no commit" do - allow(resource).to receive(:has_no_commits?).and_return(true) - - expect(presenter.unmergeable_reasons).to eq(["no commits"]) - end - - it "handles branches missing" do - allow(resource).to receive(:source_branch_exists?).and_return(false) - allow(resource).to receive(:target_branch_exists?).and_return(false) - - expect(presenter.unmergeable_reasons).to eq(["source branch is missing", "target branch is missing"]) - end - - it "handles merge conflict" do - allow(resource.project.repository).to receive(:can_be_merged?).and_return(false) - - expect(presenter.unmergeable_reasons).to eq(["has merge conflicts"]) - end - end - describe '#conflict_resolution_path' do let(:project) { create :project } let(:user) { create :user } diff --git a/spec/support/helpers/login_helpers.rb b/spec/support/helpers/login_helpers.rb index f7b71bf42e3..329f18cd288 100644 --- a/spec/support/helpers/login_helpers.rb +++ b/spec/support/helpers/login_helpers.rb @@ -152,8 +152,13 @@ module LoginHelpers end def stub_saml_authorize_path_helpers - allow_any_instance_of(Object).to receive(:user_saml_omniauth_authorize_path).and_return('/users/auth/saml') - allow_any_instance_of(Object).to receive(:omniauth_authorize_path).with(:user, "saml").and_return('/users/auth/saml') + allow_any_instance_of(ActionDispatch::Routing::RoutesProxy) + .to receive(:user_saml_omniauth_authorize_path) + .and_return('/users/auth/saml') + allow(Devise::OmniAuth::UrlHelpers) + .to receive(:omniauth_authorize_path) + .with(:user, "saml") + .and_return('/users/auth/saml') end def stub_omniauth_config(messages) |