diff options
134 files changed, 969 insertions, 353 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 267a954d0eb..ba0c5074839 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -394,7 +394,11 @@ compile-assets: - date - yarn install --frozen-lockfile --cache-folder .yarn-cache - date + - free -m - bundle exec rake gitlab:assets:compile + variables: + # we override the max_old_space_size to prevent OOM errors + NODE_OPTIONS: --max_old_space_size=3584 artifacts: expire_in: 7d paths: @@ -658,10 +662,13 @@ gitlab:assets:compile: SKIP_STORAGE_VALIDATION: "true" WEBPACK_REPORT: "true" NO_COMPRESSION: "true" + # we override the max_old_space_size to prevent OOM errors + NODE_OPTIONS: --max_old_space_size=3584 script: - date - yarn install --frozen-lockfile --production --cache-folder .yarn-cache - date + - free -m - bundle exec rake gitlab:assets:compile artifacts: name: webpack-report @@ -134,7 +134,7 @@ gem 'seed-fu', '~> 2.3.7' # Markdown and HTML processing gem 'html-pipeline', '~> 2.7.1' gem 'deckar01-task_list', '2.0.0' -gem 'gitlab-markup', '~> 1.6.2' +gem 'gitlab-markup', '~> 1.6.4' gem 'redcarpet', '~> 3.4' gem 'commonmarker', '~> 0.17' gem 'RedCloth', '~> 4.3.2' @@ -333,7 +333,7 @@ group :development, :test do gem 'database_cleaner', '~> 1.5.0' gem 'factory_bot_rails', '~> 4.8.2' - gem 'rspec-rails', '~> 3.6.0' + gem 'rspec-rails', '~> 3.7.0' gem 'rspec-retry', '~> 0.4.5' gem 'rspec_profiling', '~> 0.0.5' gem 'rspec-set', '~> 0.1.3' diff --git a/Gemfile.lock b/Gemfile.lock index 0a4dbdc0581..4fc5af40ce6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -312,7 +312,7 @@ GEM diff-lcs (~> 1.1) mime-types (>= 1.16) posix-spawn (~> 0.3) - gitlab-markup (1.6.3) + gitlab-markup (1.6.4) gitlab-styles (2.3.2) rubocop (~> 0.51) rubocop-gitlab-security (~> 0.1.0) @@ -742,36 +742,36 @@ GEM chunky_png rqrcode-rails3 (0.1.7) rqrcode (>= 0.4.2) - rspec (3.6.0) - rspec-core (~> 3.6.0) - rspec-expectations (~> 3.6.0) - rspec-mocks (~> 3.6.0) - rspec-core (3.6.0) - rspec-support (~> 3.6.0) - rspec-expectations (3.6.0) + rspec (3.7.0) + rspec-core (~> 3.7.0) + rspec-expectations (~> 3.7.0) + rspec-mocks (~> 3.7.0) + rspec-core (3.7.1) + rspec-support (~> 3.7.0) + rspec-expectations (3.7.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.6.0) - rspec-mocks (3.6.0) + rspec-support (~> 3.7.0) + rspec-mocks (3.7.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.6.0) + rspec-support (~> 3.7.0) rspec-parameterized (0.4.0) binding_of_caller parser proc_to_ast rspec (>= 2.13, < 4) unparser - rspec-rails (3.6.0) + rspec-rails (3.7.2) actionpack (>= 3.0) activesupport (>= 3.0) railties (>= 3.0) - rspec-core (~> 3.6.0) - rspec-expectations (~> 3.6.0) - rspec-mocks (~> 3.6.0) - rspec-support (~> 3.6.0) + rspec-core (~> 3.7.0) + rspec-expectations (~> 3.7.0) + rspec-mocks (~> 3.7.0) + rspec-support (~> 3.7.0) rspec-retry (0.4.5) rspec-core rspec-set (0.1.3) - rspec-support (3.6.0) + rspec-support (3.7.1) rspec_profiling (0.0.5) activerecord pg @@ -1044,7 +1044,7 @@ DEPENDENCIES gitlab-flowdock-git-hook (~> 1.0.1) gitlab-gollum-lib (~> 4.2) gitlab-gollum-rugged_adapter (~> 0.4.4) - gitlab-markup (~> 1.6.2) + gitlab-markup (~> 1.6.4) gitlab-styles (~> 2.3) gitlab_omniauth-ldap (~> 2.0.4) gon (~> 6.2) @@ -1141,7 +1141,7 @@ DEPENDENCIES rouge (~> 3.1) rqrcode-rails3 (~> 0.1.7) rspec-parameterized - rspec-rails (~> 3.6.0) + rspec-rails (~> 3.7.0) rspec-retry (~> 0.4.5) rspec-set (~> 0.1.3) rspec_profiling (~> 0.0.5) diff --git a/app/assets/javascripts/clusters/stores/clusters_store.js b/app/assets/javascripts/clusters/stores/clusters_store.js index 3a4ac09f67c..d90db7b103c 100644 --- a/app/assets/javascripts/clusters/stores/clusters_store.js +++ b/app/assets/javascripts/clusters/stores/clusters_store.js @@ -95,7 +95,7 @@ export default class ClusterStore { this.state.applications.jupyter.hostname = serverAppEntry.hostname || (this.state.applications.ingress.externalIp - ? `jupyter.${this.state.applications.ingress.externalIp}.xip.io` + ? `jupyter.${this.state.applications.ingress.externalIp}.nip.io` : ''); } }); diff --git a/app/assets/javascripts/ide/stores/modules/merge_requests/actions.js b/app/assets/javascripts/ide/stores/modules/merge_requests/actions.js index 5beb8fac71f..4e1df80b3a2 100644 --- a/app/assets/javascripts/ide/stores/modules/merge_requests/actions.js +++ b/app/assets/javascripts/ide/stores/modules/merge_requests/actions.js @@ -31,10 +31,15 @@ export const openMergeRequest = ({ commit, dispatch }, { projectPath, id }) => { commit(rootTypes.CLEAR_PROJECTS, null, { root: true }); commit(rootTypes.SET_CURRENT_MERGE_REQUEST, `${id}`, { root: true }); commit(rootTypes.RESET_OPEN_FILES, null, { root: true }); - dispatch('pipelines/stopPipelinePolling', null, { root: true }); - dispatch('pipelines/clearEtagPoll', null, { root: true }); dispatch('pipelines/resetLatestPipeline', null, { root: true }); dispatch('setCurrentBranchId', '', { root: true }); + dispatch('pipelines/stopPipelinePolling', null, { root: true }) + .then(() => { + dispatch('pipelines/clearEtagPoll', null, { root: true }); + }) + .catch(e => { + throw e; + }); router.push(`/project/${projectPath}/merge_requests/${id}`); }; diff --git a/app/assets/javascripts/ide/stores/modules/pipelines/actions.js b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js index 0a4ea80c4c1..6718f7eae4e 100644 --- a/app/assets/javascripts/ide/stores/modules/pipelines/actions.js +++ b/app/assets/javascripts/ide/stores/modules/pipelines/actions.js @@ -12,8 +12,12 @@ let eTagPoll; export const clearEtagPoll = () => { eTagPoll = null; }; -export const stopPipelinePolling = () => eTagPoll && eTagPoll.stop(); -export const restartPipelinePolling = () => eTagPoll && eTagPoll.restart(); +export const stopPipelinePolling = () => { + if (eTagPoll) eTagPoll.stop(); +}; +export const restartPipelinePolling = () => { + if (eTagPoll) eTagPoll.restart(); +}; export const requestLatestPipeline = ({ commit }) => commit(types.REQUEST_LATEST_PIPELINE); export const receiveLatestPipelineError = ({ commit, dispatch }) => { @@ -51,9 +55,9 @@ export const fetchLatestPipeline = ({ dispatch, rootGetters }) => { Visibility.change(() => { if (!Visibility.hidden()) { - eTagPoll.restart(); + dispatch('restartPipelinePolling'); } else { - eTagPoll.stop(); + dispatch('stopPipelinePolling'); } }); }; diff --git a/app/assets/javascripts/lib/utils/http_status.js b/app/assets/javascripts/lib/utils/http_status.js index bb151929431..229d53b18b0 100644 --- a/app/assets/javascripts/lib/utils/http_status.js +++ b/app/assets/javascripts/lib/utils/http_status.js @@ -8,4 +8,5 @@ export default { OK: 200, MULTIPLE_CHOICES: 300, BAD_REQUEST: 400, + NOT_FOUND: 404, }; diff --git a/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue b/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue index 6f79310b1cc..0e139cd7f5e 100644 --- a/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue +++ b/app/assets/javascripts/sidebar/components/time_tracking/comparison_pane.vue @@ -1,8 +1,12 @@ <script> import { parseSeconds, stringifyTime } from '../../../lib/utils/pretty_time'; +import tooltip from '../../../vue_shared/directives/tooltip'; export default { name: 'TimeTrackingComparisonPane', + directives: { + tooltip, + }, props: { timeSpent: { type: Number, @@ -51,17 +55,12 @@ export default { <div class="time-tracking-comparison-pane"> <div class="compare-meter" - data-toggle="tooltip" - data-placement="top" - role="timeRemainingDisplay" - :aria-valuenow="timeRemainingTooltip" :title="timeRemainingTooltip" - :data-original-title="timeRemainingTooltip" + v-tooltip :class="timeRemainingStatusClass" > <div class="meter-container" - role="timeSpentPercent" :aria-valuenow="timeRemainingPercent" > <div diff --git a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author_time.vue b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author_time.vue index 644e4b7d81a..a9868486e83 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author_time.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/mr_widget_author_time.vue @@ -1,11 +1,15 @@ <script> + import tooltip from '~/vue_shared/directives/tooltip'; import MrWidgetAuthor from './mr_widget_author.vue'; export default { - name: 'MRWidgetAuthorTime', + name: 'MrWidgetAuthorTime', components: { MrWidgetAuthor, }, + directives: { + tooltip, + }, props: { actionText: { type: String, @@ -32,8 +36,7 @@ <mr-widget-author :author="author" /> <time :title="dateTitle" - data-toggle="tooltip" - data-placement="top" + v-tooltip data-container="body" > {{ dateReadable }} diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue index 68b691fc914..25a57e520ee 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_closed.vue @@ -1,11 +1,11 @@ <script> - import mrWidgetAuthorTime from '../../components/mr_widget_author_time.vue'; + import MrWidgetAuthorTime from '../../components/mr_widget_author_time.vue'; import statusIcon from '../mr_widget_status_icon.vue'; export default { name: 'MRWidgetClosed', components: { - mrWidgetAuthorTime, + MrWidgetAuthorTime, statusIcon, }, props: { diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue index eb581b807a2..bc95706f47d 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue @@ -4,7 +4,7 @@ import loadingIcon from '~/vue_shared/components/loading_icon.vue'; import { s__, __ } from '~/locale'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; - import mrWidgetAuthorTime from '../../components/mr_widget_author_time.vue'; + import MrWidgetAuthorTime from '../../components/mr_widget_author_time.vue'; import statusIcon from '../mr_widget_status_icon.vue'; import eventHub from '../../event_hub'; @@ -14,7 +14,7 @@ tooltip, }, components: { - mrWidgetAuthorTime, + MrWidgetAuthorTime, loadingIcon, statusIcon, ClipboardButton, diff --git a/app/assets/stylesheets/framework/pagination.scss b/app/assets/stylesheets/framework/pagination.scss index 50a1b1c446d..61d02511ff4 100644 --- a/app/assets/stylesheets/framework/pagination.scss +++ b/app/assets/stylesheets/framework/pagination.scss @@ -4,3 +4,11 @@ text-decoration: none; } } + +.page-item { + &.active { + .page-link { + z-index: 3; + } + } +} diff --git a/app/assets/stylesheets/framework/tables.scss b/app/assets/stylesheets/framework/tables.scss index 6e1758d7677..ba9de6941ac 100644 --- a/app/assets/stylesheets/framework/tables.scss +++ b/app/assets/stylesheets/framework/tables.scss @@ -58,8 +58,13 @@ table { display: none; } + table, + tbody, td { display: block; + } + + td { color: $gl-text-color-secondary; } diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss index 497261f938f..63328b34edc 100644 --- a/app/assets/stylesheets/framework/variables.scss +++ b/app/assets/stylesheets/framework/variables.scss @@ -435,6 +435,22 @@ $badge-bg: rgba(0, 0, 0, 0.07); $badge-color: $gl-text-color-secondary; /* +* Pagination +*/ +$pagination-padding-y: 6px; +$pagination-padding-x: 16px; +$pagination-line-height: 20px; +$pagination-border-color: $border-color; +$pagination-active-bg: $blue-600; +$pagination-active-border-color: $blue-600; +$pagination-hover-bg: $blue-50; +$pagination-hover-border-color: $border-color; +$pagination-hover-color: $gl-text-color; +$pagination-disabled-color: #cdcdcd; +$pagination-disabled-bg: $gray-light; +$pagination-disabled-border-color: $border-color; + +/* * Status icons */ $status-icon-size: 22px; diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index eecd86349e4..0878356e87a 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -8,6 +8,7 @@ module Ci include Gitlab::OptimisticLocking include Gitlab::Utils::StrongMemoize include AtomicInternalId + include EnumWithNil belongs_to :project, inverse_of: :pipelines belongs_to :user @@ -54,7 +55,7 @@ module Ci after_create :keep_around_commits, unless: :importing? - enum source: { + enum_with_nil source: { unknown: nil, push: 1, web: 2, @@ -64,7 +65,7 @@ module Ci external: 6 } - enum config_source: { + enum_with_nil config_source: { unknown_source: nil, repository_source: 1, auto_devops_source: 2 @@ -599,17 +600,6 @@ module Ci @latest_builds_with_artifacts ||= builds.latest.with_artifacts_archive.to_a end - # Rails 5.0 autogenerated question mark enum methods return wrong result if enum value is nil. - # They always return `false`. - # These methods overwrite autogenerated ones to return correct results. - def unknown? - Gitlab.rails5? ? source.nil? : super - end - - def unknown_source? - Gitlab.rails5? ? config_source.nil? : super - end - private def ci_yaml_from_repo diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index a7d05722287..97516079b66 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -3,6 +3,7 @@ class CommitStatus < ActiveRecord::Base include Importable include AfterCommitQueue include Presentable + include EnumWithNil self.table_name = 'ci_builds' @@ -39,7 +40,7 @@ class CommitStatus < ActiveRecord::Base scope :retried_ordered, -> { retried.ordered.includes(project: :namespace) } scope :after_stage, -> (index) { where('stage_idx > ?', index) } - enum failure_reason: { + enum_with_nil failure_reason: { unknown_failure: nil, script_failure: 1, api_failure: 2, @@ -190,11 +191,4 @@ class CommitStatus < ActiveRecord::Base v =~ /\d+/ ? v.to_i : v end end - - # Rails 5.0 autogenerated question mark enum methods return wrong result if enum value is nil. - # They always return `false`. - # This method overwrites the autogenerated one to return correct result. - def unknown_failure? - Gitlab.rails5? ? failure_reason.nil? : super - end end diff --git a/app/models/concerns/enum_with_nil.rb b/app/models/concerns/enum_with_nil.rb new file mode 100644 index 00000000000..6b37903da20 --- /dev/null +++ b/app/models/concerns/enum_with_nil.rb @@ -0,0 +1,33 @@ +module EnumWithNil + extend ActiveSupport::Concern + + included do + def self.enum_with_nil(definitions) + # use original `enum` to auto-define all methods + enum(definitions) + + # override auto-defined methods only for the + # key which uses nil value + definitions.each do |name, values| + next unless key_with_nil = values.key(nil) + + # E.g. for enum_with_nil failure_reason: { unknown_failure: nil } + # this overrides auto-generated method `unknown_failure?` + define_method("#{key_with_nil}?") do + Gitlab.rails5? ? self[name].nil? : super() + end + + # E.g. for enum_with_nil failure_reason: { unknown_failure: nil } + # this overrides auto-generated method `failure_reason` + define_method(name) do + orig = super() + + return orig unless Gitlab.rails5? + return orig unless orig.nil? + + self.class.public_send(name.to_s.pluralize).key(nil) # rubocop:disable GitlabSecurity/PublicSend + end + end + end + end +end diff --git a/app/models/project.rb b/app/models/project.rb index 60cd13b371f..fe1e0c598d2 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -292,6 +292,7 @@ class Project < ActiveRecord::Base validates :name, uniqueness: { scope: :namespace_id } validates :import_url, url: { protocols: %w(http https ssh git), allow_localhost: false, + enforce_user: true, ports: VALID_IMPORT_PORTS }, if: [:external_import?, :import_url_changed?] validates :star_count, numericality: { greater_than_or_equal_to: 0 } validate :check_limit, on: :create @@ -1615,6 +1616,7 @@ class Project < ActiveRecord::Base def after_import repository.after_import + wiki.repository.after_import import_finish remove_import_jid update_project_counter_caches diff --git a/app/models/remote_mirror.rb b/app/models/remote_mirror.rb index 5cd222e18a4..c4b5dd2dc96 100644 --- a/app/models/remote_mirror.rb +++ b/app/models/remote_mirror.rb @@ -16,7 +16,7 @@ class RemoteMirror < ActiveRecord::Base belongs_to :project, inverse_of: :remote_mirrors - validates :url, presence: true, url: { protocols: %w(ssh git http https), allow_blank: true } + validates :url, presence: true, url: { protocols: %w(ssh git http https), allow_blank: true, enforce_user: true } before_save :set_new_remote_name, if: :mirror_url_changed? diff --git a/app/services/commits/create_service.rb b/app/services/commits/create_service.rb index f96f2931508..4d0578becbe 100644 --- a/app/services/commits/create_service.rb +++ b/app/services/commits/create_service.rb @@ -17,7 +17,7 @@ module Commits new_commit = create_commit! success(result: new_commit) - rescue ValidationError, ChangeError, Gitlab::Git::Index::IndexError, Gitlab::Git::CommitError, Gitlab::Git::HooksService::PreReceiveError => ex + rescue ValidationError, ChangeError, Gitlab::Git::Index::IndexError, Gitlab::Git::CommitError, Gitlab::Git::PreReceiveError => ex error(ex.message) end diff --git a/app/services/create_branch_service.rb b/app/services/create_branch_service.rb index 0ba6a0ac6b5..9b1a4d960e2 100644 --- a/app/services/create_branch_service.rb +++ b/app/services/create_branch_service.rb @@ -14,7 +14,7 @@ class CreateBranchService < BaseService else error('Invalid reference name') end - rescue Gitlab::Git::HooksService::PreReceiveError => ex + rescue Gitlab::Git::PreReceiveError => ex error(ex.message) end diff --git a/app/services/delete_branch_service.rb b/app/services/delete_branch_service.rb index 1f059c31944..e1499dcee64 100644 --- a/app/services/delete_branch_service.rb +++ b/app/services/delete_branch_service.rb @@ -16,7 +16,7 @@ class DeleteBranchService < BaseService else error('Failed to remove branch') end - rescue Gitlab::Git::HooksService::PreReceiveError => ex + rescue Gitlab::Git::PreReceiveError => ex error(ex.message) end diff --git a/app/services/merge_requests/ff_merge_service.rb b/app/services/merge_requests/ff_merge_service.rb index ba6853b835a..bffc09c34f0 100644 --- a/app/services/merge_requests/ff_merge_service.rb +++ b/app/services/merge_requests/ff_merge_service.rb @@ -13,7 +13,7 @@ module MergeRequests source, merge_request.target_branch, merge_request: merge_request) - rescue Gitlab::Git::HooksService::PreReceiveError => e + rescue Gitlab::Git::PreReceiveError => e raise MergeError, e.message rescue StandardError => e raise MergeError, "Something went wrong during merge: #{e.message}" diff --git a/app/services/merge_requests/merge_service.rb b/app/services/merge_requests/merge_service.rb index 126da891c78..3d587f97906 100644 --- a/app/services/merge_requests/merge_service.rb +++ b/app/services/merge_requests/merge_service.rb @@ -79,7 +79,7 @@ module MergeRequests message = params[:commit_message] || merge_request.merge_commit_message repository.merge(current_user, source, merge_request, message) - rescue Gitlab::Git::HooksService::PreReceiveError => e + rescue Gitlab::Git::PreReceiveError => e handle_merge_error(log_message: e.message) raise MergeError, 'Something went wrong during merge pre-receive hook' rescue => e diff --git a/app/services/tags/create_service.rb b/app/services/tags/create_service.rb index cc76d0df3a1..3cc88d77ba1 100644 --- a/app/services/tags/create_service.rb +++ b/app/services/tags/create_service.rb @@ -13,7 +13,7 @@ module Tags new_tag = repository.add_tag(current_user, tag_name, target, message) rescue Gitlab::Git::Repository::TagExistsError return error("Tag #{tag_name} already exists") - rescue Gitlab::Git::HooksService::PreReceiveError => ex + rescue Gitlab::Git::PreReceiveError => ex return error(ex.message) end diff --git a/app/services/tags/destroy_service.rb b/app/services/tags/destroy_service.rb index d3d46064729..b84b061e460 100644 --- a/app/services/tags/destroy_service.rb +++ b/app/services/tags/destroy_service.rb @@ -21,7 +21,7 @@ module Tags else error('Failed to remove tag') end - rescue Gitlab::Git::HooksService::PreReceiveError => ex + rescue Gitlab::Git::PreReceiveError => ex error(ex.message) end diff --git a/app/services/validate_new_branch_service.rb b/app/services/validate_new_branch_service.rb index 7d1ed768ee8..643f2ce1481 100644 --- a/app/services/validate_new_branch_service.rb +++ b/app/services/validate_new_branch_service.rb @@ -13,7 +13,7 @@ class ValidateNewBranchService < BaseService end success - rescue Gitlab::Git::HooksService::PreReceiveError => ex + rescue Gitlab::Git::PreReceiveError => ex error(ex.message) end end diff --git a/app/uploaders/object_storage.rb b/app/uploaders/object_storage.rb index 5aa1bc7227c..23b3dcf84c0 100644 --- a/app/uploaders/object_storage.rb +++ b/app/uploaders/object_storage.rb @@ -22,10 +22,10 @@ module ObjectStorage module RecordsUploads extend ActiveSupport::Concern - def prepended(base) + prepended do |base| raise "#{base} must include ObjectStorage::Concern to use extensions." unless base < Concern - base.include(RecordsUploads::Concern) + base.include(::RecordsUploads::Concern) end def retrieve_from_store!(identifier) diff --git a/app/validators/url_validator.rb b/app/validators/url_validator.rb index 8648c4c75e3..6854fec582e 100644 --- a/app/validators/url_validator.rb +++ b/app/validators/url_validator.rb @@ -18,6 +18,13 @@ # This validator can also block urls pointing to localhost or the local network to # protect against Server-side Request Forgery (SSRF), or check for the right port. # +# The available options are: +# - protocols: Allowed protocols. Default: http and https +# - allow_localhost: Allow urls pointing to localhost. Default: true +# - allow_local_network: Allow urls pointing to private network addresses. Default: true +# - ports: Allowed ports. Default: all. +# - enforce_user: Validate user format. Default: false +# # Example: # class User < ActiveRecord::Base # validates :personal_url, url: { allow_localhost: false, allow_local_network: false} @@ -35,7 +42,7 @@ class UrlValidator < ActiveModel::EachValidator if value.present? value.strip! else - record.errors.add(attribute, "must be a valid URL") + record.errors.add(attribute, 'must be a valid URL') end Gitlab::UrlBlocker.validate!(value, blocker_args) @@ -51,7 +58,8 @@ class UrlValidator < ActiveModel::EachValidator protocols: DEFAULT_PROTOCOLS, ports: [], allow_localhost: true, - allow_local_network: true + allow_local_network: true, + enforce_user: false } end @@ -64,7 +72,7 @@ class UrlValidator < ActiveModel::EachValidator end def blocker_args - current_options.slice(:allow_localhost, :allow_local_network, :protocols, :ports).tap do |args| + current_options.slice(*default_options.keys).tap do |args| if allow_setting_local_requests? args[:allow_localhost] = args[:allow_local_network] = true end diff --git a/app/views/admin/gitaly_servers/index.html.haml b/app/views/admin/gitaly_servers/index.html.haml index d0cf5761726..9b24f411a75 100644 --- a/app/views/admin/gitaly_servers/index.html.haml +++ b/app/views/admin/gitaly_servers/index.html.haml @@ -6,10 +6,10 @@ - if @gitaly_servers.any? .table-holder %table.table.responsive-table - %thead.d-none.d-sm-none.d-md-block + %thead %tr %th= _("Storage") - %th= n_("Gitaly|Address") + %th= s_("Gitaly|Address") %th= _("Server version") %th= _("Git version") %th= _("Up to date") diff --git a/app/views/search/results/_blob_data.html.haml b/app/views/search/results/_blob_data.html.haml index 0115be41ff1..143e9f91ca3 100644 --- a/app/views/search/results/_blob_data.html.haml +++ b/app/views/search/results/_blob_data.html.haml @@ -3,7 +3,8 @@ .js-file-title.file-title = link_to blob_link do %i.fa.fa-file - = search_blob_title(project, file_name) + %strong + = search_blob_title(project, file_name) - if blob.data .file-content.code.term = render 'shared/file_highlight', blob: blob, first_line_number: blob.startline diff --git a/app/views/search/results/_commit.html.haml b/app/views/search/results/_commit.html.haml index f34eaf89027..ed5a3badf11 100644 --- a/app/views/search/results/_commit.html.haml +++ b/app/views/search/results/_commit.html.haml @@ -1 +1 @@ -= render 'projects/commits/commit', project: @project, commit: commit, ref: nil += render 'projects/commits/commit', project: commit.project, commit: commit, ref: nil, show_project_name: @project.nil? diff --git a/changelogs/unreleased/47679-fix-failed-jobs-tab-ie11.yml b/changelogs/unreleased/47679-fix-failed-jobs-tab-ie11.yml new file mode 100644 index 00000000000..48f3bc87eee --- /dev/null +++ b/changelogs/unreleased/47679-fix-failed-jobs-tab-ie11.yml @@ -0,0 +1,5 @@ +--- +title: Fix overflowing Failed Jobs table in sm viewports on IE11 +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/fj-relax-url-validator-rules-for-user.yml b/changelogs/unreleased/fj-relax-url-validator-rules-for-user.yml new file mode 100644 index 00000000000..4c72e4c5c1c --- /dev/null +++ b/changelogs/unreleased/fj-relax-url-validator-rules-for-user.yml @@ -0,0 +1,5 @@ +--- +title: Avoid checking the user format in every url validation +merge_request: 19575 +author: +type: changed diff --git a/changelogs/unreleased/gitaly-commit-count-opt-out.yml b/changelogs/unreleased/gitaly-commit-count-opt-out.yml new file mode 100644 index 00000000000..fd8298b1d7b --- /dev/null +++ b/changelogs/unreleased/gitaly-commit-count-opt-out.yml @@ -0,0 +1,5 @@ +--- +title: Move some Gitaly RPC's to opt-out +merge_request: 19591 +author: +type: other diff --git a/changelogs/unreleased/sh-expire-content-cache-after-import.yml b/changelogs/unreleased/sh-expire-content-cache-after-import.yml new file mode 100644 index 00000000000..8876a487b86 --- /dev/null +++ b/changelogs/unreleased/sh-expire-content-cache-after-import.yml @@ -0,0 +1,5 @@ +--- +title: Expire Wiki content cache after importing a repository +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/unify-views-search-results.yml b/changelogs/unreleased/unify-views-search-results.yml new file mode 100644 index 00000000000..81ad3616648 --- /dev/null +++ b/changelogs/unreleased/unify-views-search-results.yml @@ -0,0 +1,5 @@ +--- +title: Hide project name if searching against a project +merge_request: 19595 +author: +type: changed diff --git a/changelogs/unreleased/upgrade-gitlab-markup.yml b/changelogs/unreleased/upgrade-gitlab-markup.yml new file mode 100644 index 00000000000..9b0eaa7068d --- /dev/null +++ b/changelogs/unreleased/upgrade-gitlab-markup.yml @@ -0,0 +1,5 @@ +--- +title: Fix extra blank line at start of rendered reStructuredText code block +merge_request: 19596 +author: +type: fixed diff --git a/changelogs/unreleased/use-tooltip-component-in-mr-widget-author-time-component.yml b/changelogs/unreleased/use-tooltip-component-in-mr-widget-author-time-component.yml new file mode 100644 index 00000000000..4ab9b6dadc0 --- /dev/null +++ b/changelogs/unreleased/use-tooltip-component-in-mr-widget-author-time-component.yml @@ -0,0 +1,5 @@ +--- +title: Use Tooltip component in MrWidgetAuthorTime vue comonent +merge_request: 19635 +author: George Tsiolis +type: performance diff --git a/config/initializers/postgresql_opclasses_support.rb b/config/initializers/postgresql_opclasses_support.rb index 03bda44a630..7b8afc78817 100644 --- a/config/initializers/postgresql_opclasses_support.rb +++ b/config/initializers/postgresql_opclasses_support.rb @@ -41,7 +41,12 @@ module ActiveRecord # Abstract representation of an index definition on a table. Instances of # this type are typically created and returned by methods in database # adapters. e.g. ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter#indexes - class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders, :where, :type, :using, :opclasses) #:nodoc: + attrs = [:table, :name, :unique, :columns, :lengths, :orders, :where, :type, :using, :opclasses] + + # In Rails 5 the second last attribute is newly `:comment` + attrs.insert(-2, :comment) if Gitlab.rails5? + + class IndexDefinition < Struct.new(*attrs) #:nodoc: end end end diff --git a/config/webpack.config.js b/config/webpack.config.js index e760ce1cb8c..b1e378f6c27 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -1,4 +1,3 @@ -const fs = require('fs'); const path = require('path'); const glob = require('glob'); const webpack = require('webpack'); diff --git a/doc/install/installation.md b/doc/install/installation.md index 34268c67140..6cd1fb4c2d7 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -301,9 +301,9 @@ sudo usermod -aG redis git ### Clone the Source # Clone GitLab repository - sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 10-8-stable gitlab + sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 11-0-stable gitlab -**Note:** You can change `10-8-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! +**Note:** You can change `11-0-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server! ### Configure It diff --git a/doc/university/glossary/README.md b/doc/university/glossary/README.md index 945d6a578b0..89516dba60b 100644 --- a/doc/university/glossary/README.md +++ b/doc/university/glossary/README.md @@ -557,10 +557,6 @@ Software that is hosted centrally and accessed on-demand (i.e. whenever you want This term is often used by people when they mean "Version Control." -#### SCLAU - -Abbreviation for SQO Count [Large And Up](https://about.gitlab.com/handbook/sales/#market-segmentation). This is the number of opportunities in large and strategic organizations passed from marketing to sales. - ### Scrum An Agile [framework](https://www.scrum.org/Resources/What-is-Scrum) designed to typically help complete complex software projects. It's made up of several parts: product requirements backlog, sprint planning, sprint (development), sprint review, and retrospec (analyzing the sprint). The goal is to end up with potentially shippable products. diff --git a/doc/update/10.8-to-11.0.md b/doc/update/10.8-to-11.0.md new file mode 100644 index 00000000000..78a47ab939f --- /dev/null +++ b/doc/update/10.8-to-11.0.md @@ -0,0 +1,362 @@ +--- +comments: false +--- + +# From 10.8 to 11.0 + +Make sure you view this update guide from the tag (version) of GitLab you would +like to install. In most cases this should be the highest numbered production +tag (without rc in it). You can select the tag in the version dropdown at the +top left corner of GitLab (below the menu bar). + +If the highest number stable branch is unclear please check the +[GitLab Blog](https://about.gitlab.com/blog/archives.html) for installation +guide links by version. + +### 1. Stop server + +```bash +sudo service gitlab stop +``` + +### 2. Backup + +NOTE: If you installed GitLab from source, make sure `rsync` is installed. + +```bash +cd /home/git/gitlab + +sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production +``` + +### 3. Update Ruby + +NOTE: GitLab 11.0 and higher only support Ruby 2.4.x and dropped support for Ruby 2.3.x. Be +sure to upgrade your interpreter if necessary. + +You can check which version you are running with `ruby -v`. + +Download Ruby and compile it: + +```bash +mkdir /tmp/ruby && cd /tmp/ruby +curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.4/ruby-2.4.4.tar.gz +echo 'ec82b0d53bd0adad9b19e6b45e44d54e9ec3f10c ruby-2.4.4.tar.gz' | shasum -c - && tar xzf ruby-2.4.4.tar.gz +cd ruby-2.4.4 + +./configure --disable-install-rdoc +make +sudo make install +``` + +Install Bundler: + +```bash +sudo gem install bundler --no-ri --no-rdoc +``` + +### 4. Update Node + +GitLab utilizes [webpack](http://webpack.js.org) to compile frontend assets. +This requires a minimum version of node v6.0.0. + +You can check which version you are running with `node -v`. If you are running +a version older than `v6.0.0` you will need to update to a newer version. You +can find instructions to install from community maintained packages or compile +from source at the nodejs.org website. + +<https://nodejs.org/en/download/> + +GitLab also requires the use of yarn `>= v1.2.0` to manage JavaScript +dependencies. + +```bash +curl --silent --show-error https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - +echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list +sudo apt-get update +sudo apt-get install yarn +``` + +More information can be found on the [yarn website](https://yarnpkg.com/en/docs/install). + +### 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. + +You can check which version you are running with `go version`. + +Download and install Go: + +```bash +# 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 +sudo ln -sf /usr/local/go/bin/{go,godoc,gofmt} /usr/local/bin/ +rm go1.8.3.linux-amd64.tar.gz +``` + +### 6. Get latest code + +```bash +cd /home/git/gitlab + +sudo -u git -H git fetch --all --prune +sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically +sudo -u git -H git checkout -- locale +``` + +For GitLab Community Edition: + +```bash +cd /home/git/gitlab + +sudo -u git -H git checkout 11-0-stable +``` + +OR + +For GitLab Enterprise Edition: + +```bash +cd /home/git/gitlab + +sudo -u git -H git checkout 11-0-stable-ee +``` + +### 7. Update gitlab-shell + +```bash +cd /home/git/gitlab-shell + +sudo -u git -H git fetch --all --tags --prune +sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_SHELL_VERSION) +sudo -u git -H bin/compile +``` + +### 8. Update gitlab-workhorse + +Install and compile gitlab-workhorse. GitLab-Workhorse uses +[GNU Make](https://www.gnu.org/software/make/). +If you are not using Linux you may have to run `gmake` instead of +`make` below. + +```bash +cd /home/git/gitlab-workhorse + +sudo -u git -H git fetch --all --tags --prune +sudo -u git -H git checkout v$(</home/git/gitlab/GITLAB_WORKHORSE_VERSION) +sudo -u git -H make +``` + +### 9. Update Gitaly + +#### New Gitaly configuration options required + +In order to function Gitaly needs some additional configuration information. Below we assume you installed Gitaly in `/home/git/gitaly` and GitLab Shell in `/home/git/gitlab-shell`. + +```shell +echo ' +[gitaly-ruby] +dir = "/home/git/gitaly/ruby" + +[gitlab-shell] +dir = "/home/git/gitlab-shell" +' | sudo -u git tee -a /home/git/gitaly/config.toml +``` + +#### Check Gitaly configuration + +Due to a bug in the `rake gitlab:gitaly:install` script your Gitaly +configuration file may contain syntax errors. The block name +`[[storages]]`, which may occur more than once in your `config.toml` +file, should be `[[storage]]` instead. + +```shell +sudo -u git -H sed -i.pre-10.1 's/\[\[storages\]\]/[[storage]]/' /home/git/gitaly/config.toml +``` + +#### Compile Gitaly + +```shell +cd /home/git/gitaly +sudo -u git -H git fetch --all --tags --prune +sudo -u git -H git checkout v$(</home/git/gitlab/GITALY_SERVER_VERSION) +sudo -u git -H make +``` + +### 10. Update MySQL permissions + +If you are using MySQL you need to grant the GitLab user the necessary +permissions on the database: + +```bash +mysql -u root -p -e "GRANT TRIGGER ON \`gitlabhq_production\`.* TO 'git'@'localhost';" +``` + +If you use MySQL with replication, or just have MySQL configured with binary logging, +you will need to also run the following on all of your MySQL servers: + +```bash +mysql -u root -p -e "SET GLOBAL log_bin_trust_function_creators = 1;" +``` + +You can make this setting permanent by adding it to your `my.cnf`: + +``` +log_bin_trust_function_creators=1 +``` + +### 11. Update configuration files + +#### New configuration options for `gitlab.yml` + +There might be configuration options available for [`gitlab.yml`][yaml]. View them with the command below and apply them manually to your current `gitlab.yml`: + +```sh +cd /home/git/gitlab + +git diff origin/10-8-stable:config/gitlab.yml.example origin/11-0-stable:config/gitlab.yml.example +``` + +#### Nginx configuration + +Ensure you're still up-to-date with the latest NGINX configuration changes: + +```sh +cd /home/git/gitlab + +# For HTTPS configurations +git diff origin/10-8-stable:lib/support/nginx/gitlab-ssl origin/11-0-stable:lib/support/nginx/gitlab-ssl + +# For HTTP configurations +git diff origin/10-8-stable:lib/support/nginx/gitlab origin/11-0-stable:lib/support/nginx/gitlab +``` + +If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx +configuration as GitLab application no longer handles setting it. + +If you are using Apache instead of NGINX please see the updated [Apache templates]. +Also note that because Apache does not support upstreams behind Unix sockets you +will need to let gitlab-workhorse listen on a TCP port. You can do this +via [/etc/default/gitlab]. + +[Apache templates]: https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache +[/etc/default/gitlab]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-0-stable/lib/support/init.d/gitlab.default.example#L38 + +#### SMTP configuration + +If you're installing from source and use SMTP to deliver mail, you will need to add the following line +to config/initializers/smtp_settings.rb: + +```ruby +ActionMailer::Base.delivery_method = :smtp +``` + +See [smtp_settings.rb.sample] as an example. + +[smtp_settings.rb.sample]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-0-stable/config/initializers/smtp_settings.rb.sample#L13 + +#### Init script + +There might be new configuration options available for [`gitlab.default.example`][gl-example]. View them with the command below and apply them manually to your current `/etc/default/gitlab`: + +```sh +cd /home/git/gitlab + +git diff origin/10-8-stable:lib/support/init.d/gitlab.default.example origin/11-0-stable:lib/support/init.d/gitlab.default.example +``` + +Ensure you're still up-to-date with the latest init script changes: + +```bash +cd /home/git/gitlab + +sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab +``` + +For Ubuntu 16.04.1 LTS: + +```bash +sudo systemctl daemon-reload +``` + +### 12. Install libs, migrations, etc. + +```bash +cd /home/git/gitlab + +# MySQL installations (note: the line below states '--without postgres') +sudo -u git -H bundle install --without postgres development test --deployment + +# PostgreSQL installations (note: the line below states '--without mysql') +sudo -u git -H bundle install --without mysql development test --deployment + +# Optional: clean up old gems +sudo -u git -H bundle clean + +# Run database migrations +sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production + +# Compile GetText PO files + +sudo -u git -H bundle exec rake gettext:compile RAILS_ENV=production + +# Update node dependencies and recompile assets +sudo -u git -H bundle exec rake yarn:install gitlab:assets:clean gitlab:assets:compile RAILS_ENV=production NODE_ENV=production + +# Clean up cache +sudo -u git -H bundle exec rake cache:clear RAILS_ENV=production +``` + +**MySQL installations**: Run through the `MySQL strings limits` and `Tables and data conversion to utf8mb4` [tasks](../install/database_mysql.md). + +### 13. Start application + +```bash +sudo service gitlab start +sudo service nginx restart +``` + +### 14. Check application status + +Check if GitLab and its environment are configured correctly: + +```bash +cd /home/git/gitlab + +sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production +``` + +To make sure you didn't miss anything run a more thorough check: + +```bash +cd /home/git/gitlab + +sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production +``` + +If all items are green, then congratulations, the upgrade is complete! + +## Things went south? Revert to previous version (10.8) + +### 1. Revert the code to the previous version + +Follow the [upgrade guide from 10.7 to 10.8](10.7-to-10.8.md), except for the +database migration (the backup is already migrated to the previous version). + +### 2. Restore from the backup + +```bash +cd /home/git/gitlab + +sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production +``` + +If you have more than one backup `*.tar` file(s) please add `BACKUP=timestamp_of_backup` to the command above. + +[yaml]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-0-stable/config/gitlab.yml.example +[gl-example]: https://gitlab.com/gitlab-org/gitlab-ce/blob/11-0-stable/lib/support/init.d/gitlab.default.example diff --git a/lib/gitlab/cycle_analytics/summary/commit.rb b/lib/gitlab/cycle_analytics/summary/commit.rb index 0a88e052f60..550c1755a71 100644 --- a/lib/gitlab/cycle_analytics/summary/commit.rb +++ b/lib/gitlab/cycle_analytics/summary/commit.rb @@ -7,9 +7,7 @@ module Gitlab end def value - Gitlab::GitalyClient::StorageSettings.allow_disk_access do - @value ||= count_commits - end + @value ||= count_commits end private @@ -21,19 +19,11 @@ module Gitlab def count_commits return unless ref - repository = @project.repository.raw_repository - sha = @project.repository.commit(ref).sha - - cmd = %W(git --git-dir=#{repository.path} log) - cmd << '--format=%H' - cmd << "--after=#{@from.iso8601}" - cmd << sha - - output, status = Gitlab::Popen.popen(cmd) - - raise IOError, output unless status.zero? + gitaly_commit_client.commit_count(ref, after: @from) + end - output.lines.count + def gitaly_commit_client + Gitlab::GitalyClient::CommitService.new(@project.repository.raw_repository) end def ref diff --git a/lib/gitlab/git/blame.rb b/lib/gitlab/git/blame.rb index 4158d50cd9e..40b65f6c0da 100644 --- a/lib/gitlab/git/blame.rb +++ b/lib/gitlab/git/blame.rb @@ -22,7 +22,7 @@ module Gitlab private def load_blame - raw_output = @repo.gitaly_migrate(:blame) do |is_enabled| + raw_output = @repo.gitaly_migrate(:blame, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled| if is_enabled load_blame_by_gitaly else diff --git a/lib/gitlab/git/committer_with_hooks.rb b/lib/gitlab/git/committer_with_hooks.rb index a8a59f998cd..4198be7c9c9 100644 --- a/lib/gitlab/git/committer_with_hooks.rb +++ b/lib/gitlab/git/committer_with_hooks.rb @@ -20,7 +20,7 @@ module Gitlab end result[:newrev] - rescue Gitlab::Git::HooksService::PreReceiveError => e + rescue Gitlab::Git::PreReceiveError => e message = "Custom Hook failed: #{e.message}" raise Gitlab::Git::Wiki::OperationError, message end diff --git a/lib/gitlab/git/hook.rb b/lib/gitlab/git/hook.rb index 7c201c6169b..94ff5b4980a 100644 --- a/lib/gitlab/git/hook.rb +++ b/lib/gitlab/git/hook.rb @@ -11,7 +11,7 @@ module Gitlab def initialize(name, repository) @name = name @repository = repository - @path = File.join(repo_path.strip, 'hooks', name) + @path = File.join(repo_path, 'hooks', name) end def repo_path @@ -95,13 +95,13 @@ module Gitlab args = [ref, oldrev, newrev] stdout, stderr, status = Open3.capture3(env, path, *args, options) - [status.success?, Gitlab::Utils.nlbr(stderr.presence || stdout)] + [status.success?, stderr.presence || stdout] end def retrieve_error_message(stderr, stdout) err_message = stderr.read err_message = err_message.blank? ? stdout.read : err_message - Gitlab::Utils.nlbr(err_message) + err_message end end end diff --git a/lib/gitlab/git/hooks_service.rb b/lib/gitlab/git/hooks_service.rb index f302b852b35..e67cacdb95a 100644 --- a/lib/gitlab/git/hooks_service.rb +++ b/lib/gitlab/git/hooks_service.rb @@ -1,8 +1,6 @@ module Gitlab module Git class HooksService - PreReceiveError = Class.new(StandardError) - attr_accessor :oldrev, :newrev, :ref def execute(pusher, repository, oldrev, newrev, ref) diff --git a/lib/gitlab/git/pre_receive_error.rb b/lib/gitlab/git/pre_receive_error.rb new file mode 100644 index 00000000000..ac1ab7c39d5 --- /dev/null +++ b/lib/gitlab/git/pre_receive_error.rb @@ -0,0 +1,21 @@ +module Gitlab + module Git + # + # PreReceiveError is special because its message gets displayed to users + # in the web UI. To prevent XSS we sanitize the message on + # initialization. + class PreReceiveError < StandardError + def initialize(msg = '') + super(nlbr(msg)) + end + + private + + # In gitaly-ruby we override this method to do nothing, so that + # sanitization happens in gitlab-rails only. + def nlbr(str) + Gitlab::Utils.nlbr(str) + end + end + end +end diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 93f9adaf1f1..63e1102f686 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -533,7 +533,7 @@ module Gitlab def count_commits(options) count_commits_options = process_count_commits_options(options) - gitaly_migrate(:count_commits) do |is_enabled| + gitaly_migrate(:count_commits, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled| if is_enabled count_commits_by_gitaly(count_commits_options) else @@ -738,7 +738,7 @@ module Gitlab # # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/330 def commit_count(ref) - gitaly_migrate(:commit_count) do |is_enabled| + gitaly_migrate(:commit_count, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT) do |is_enabled| if is_enabled gitaly_commit_client.commit_count(ref) else diff --git a/lib/gitlab/gitaly_client/operation_service.rb b/lib/gitlab/gitaly_client/operation_service.rb index 44b0e517bf0..e9d4bb4c4b6 100644 --- a/lib/gitlab/gitaly_client/operation_service.rb +++ b/lib/gitlab/gitaly_client/operation_service.rb @@ -20,7 +20,7 @@ module Gitlab response = GitalyClient.call(@repository.storage, :operation_service, :user_delete_tag, request) if pre_receive_error = response.pre_receive_error.presence - raise Gitlab::Git::HooksService::PreReceiveError, pre_receive_error + raise Gitlab::Git::PreReceiveError, pre_receive_error end end @@ -35,7 +35,7 @@ module Gitlab response = GitalyClient.call(@repository.storage, :operation_service, :user_create_tag, request) if pre_receive_error = response.pre_receive_error.presence - raise Gitlab::Git::HooksService::PreReceiveError, pre_receive_error + raise Gitlab::Git::PreReceiveError, pre_receive_error elsif response.exists raise Gitlab::Git::Repository::TagExistsError end @@ -56,7 +56,7 @@ module Gitlab :user_create_branch, request) if response.pre_receive_error.present? - raise Gitlab::Git::HooksService::PreReceiveError.new(response.pre_receive_error) + raise Gitlab::Git::PreReceiveError.new(response.pre_receive_error) end branch = response.branch @@ -76,7 +76,7 @@ module Gitlab response = GitalyClient.call(@repository.storage, :operation_service, :user_delete_branch, request) if pre_receive_error = response.pre_receive_error.presence - raise Gitlab::Git::HooksService::PreReceiveError, pre_receive_error + raise Gitlab::Git::PreReceiveError, pre_receive_error end end @@ -106,7 +106,7 @@ module Gitlab second_response = response_enum.next if second_response.pre_receive_error.present? - raise Gitlab::Git::HooksService::PreReceiveError, second_response.pre_receive_error + raise Gitlab::Git::PreReceiveError, second_response.pre_receive_error end branch_update = second_response.branch_update @@ -175,7 +175,7 @@ module Gitlab ) if response.pre_receive_error.presence - raise Gitlab::Git::HooksService::PreReceiveError, response.pre_receive_error + raise Gitlab::Git::PreReceiveError, response.pre_receive_error elsif response.git_error.presence raise Gitlab::Git::Repository::GitError, response.git_error else @@ -242,7 +242,7 @@ module Gitlab :user_commit_files, req_enum, remote_storage: start_repository.storage) if (pre_receive_error = response.pre_receive_error.presence) - raise Gitlab::Git::HooksService::PreReceiveError, pre_receive_error + raise Gitlab::Git::PreReceiveError, pre_receive_error end if (index_error = response.index_error.presence) @@ -280,7 +280,7 @@ module Gitlab def handle_cherry_pick_or_revert_response(response) if response.pre_receive_error.presence - raise Gitlab::Git::HooksService::PreReceiveError, response.pre_receive_error + raise Gitlab::Git::PreReceiveError, response.pre_receive_error elsif response.commit_error.presence raise Gitlab::Git::CommitError, response.commit_error elsif response.create_tree_error.presence diff --git a/lib/gitlab/github_import/sequential_importer.rb b/lib/gitlab/github_import/sequential_importer.rb index 3cad919b4eb..6a181caf65d 100644 --- a/lib/gitlab/github_import/sequential_importer.rb +++ b/lib/gitlab/github_import/sequential_importer.rb @@ -42,8 +42,6 @@ module Gitlab klass.new(project, client, parallel: false).execute end - project.repository.after_import - true end end diff --git a/lib/gitlab/url_blocker.rb b/lib/gitlab/url_blocker.rb index 20be193ea0c..38be75b7482 100644 --- a/lib/gitlab/url_blocker.rb +++ b/lib/gitlab/url_blocker.rb @@ -5,7 +5,7 @@ module Gitlab BlockedUrlError = Class.new(StandardError) class << self - def validate!(url, allow_localhost: false, allow_local_network: true, ports: [], protocols: []) + def validate!(url, allow_localhost: false, allow_local_network: true, enforce_user: false, ports: [], protocols: []) return true if url.nil? begin @@ -20,7 +20,7 @@ module Gitlab port = uri.port || uri.default_port validate_protocol!(uri.scheme, protocols) validate_port!(port, ports) if ports.any? - validate_user!(uri.user) + validate_user!(uri.user) if enforce_user validate_hostname!(uri.hostname) begin diff --git a/lib/tasks/import.rake b/lib/tasks/import.rake index 1f185dae6fc..fc59b3f937d 100644 --- a/lib/tasks/import.rake +++ b/lib/tasks/import.rake @@ -53,7 +53,7 @@ class GithubImport end if import_success - @project.import_finish + @project.after_import puts "Import finished. Timings: #{timings}".color(:green) else puts "Import was not successful. Errors were as follows:" diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 946669068cd..058a02833b1 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -2249,6 +2249,9 @@ msgstr "" msgid "Gitaly" msgstr "" +msgid "Gitaly|Address" +msgstr "" + msgid "Gitaly Servers" msgstr "" diff --git a/qa/qa/factory/repository/push.rb b/qa/qa/factory/repository/push.rb index 28711c12701..7bb808652da 100644 --- a/qa/qa/factory/repository/push.rb +++ b/qa/qa/factory/repository/push.rb @@ -3,7 +3,7 @@ module QA module Repository class Push < Factory::Base attr_accessor :file_name, :file_content, :commit_message, - :branch_name, :new_branch + :branch_name, :new_branch, :output attr_writer :remote_branch @@ -12,6 +12,10 @@ module QA 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' @@ -58,7 +62,7 @@ module QA end repository.commit(commit_message) - repository.push_changes("#{branch_name}:#{remote_branch}") + @output = repository.push_changes("#{branch_name}:#{remote_branch}") end end end diff --git a/qa/qa/factory/resource/branch.rb b/qa/qa/factory/resource/branch.rb index 1785441f5a8..4cabe7eab45 100644 --- a/qa/qa/factory/resource/branch.rb +++ b/qa/qa/factory/resource/branch.rb @@ -46,7 +46,9 @@ module QA resource.remote_branch = @branch_name end - Page::Project::Show.act { wait_for_push } + Page::Project::Show.perform do |page| + page.wait { page.has_content?(branch_name) } + end # The upcoming process will make it access the Protected Branches page, # select the already created branch and protect it according @@ -62,13 +64,13 @@ module QA page.select_branch(branch_name) if allow_to_push - page.allow_devs_and_masters_to_push + page.allow_devs_and_maintainers_to_push else page.allow_no_one_to_push end if allow_to_merge - page.allow_devs_and_masters_to_merge + page.allow_devs_and_maintainers_to_merge else page.allow_no_one_to_merge end @@ -79,9 +81,13 @@ module QA page.protect_branch - # Wait for page load, which resets the expanded sections - page.wait(reload: false) do - !page.has_content?('Collapse') + # Avoid Selenium::WebDriver::Error::StaleElementReferenceError + # without sleeping. I.e. this completes fast on fast machines. + page.refresh + + # It is possible for the protected branch row to "disappear" at first + page.wait do + page.has_content?(branch_name) end end end diff --git a/qa/qa/git/repository.rb b/qa/qa/git/repository.rb index 5bc4ffbb036..fc753554fc4 100644 --- a/qa/qa/git/repository.rb +++ b/qa/qa/git/repository.rb @@ -7,8 +7,6 @@ module QA class Repository include Scenario::Actable - attr_reader :push_output - def self.perform(*args) Dir.mktmpdir do |dir| Dir.chdir(dir) { super } @@ -71,7 +69,9 @@ module QA end def push_changes(branch = 'master') - @push_output, _ = run_and_redact_credentials("git push #{@uri} #{branch}") + output, _ = run_and_redact_credentials("git push #{@uri} #{branch}") + + output end def commits diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb index 0a69af88570..30e35bf7abb 100644 --- a/qa/qa/page/base.rb +++ b/qa/qa/page/base.rb @@ -13,7 +13,7 @@ module QA visit current_url end - def wait(max: 60, time: 1, reload: true) + def wait(max: 60, time: 0.1, reload: true) start = Time.now while Time.now - start < max diff --git a/qa/qa/page/group/show.rb b/qa/qa/page/group/show.rb index 89125bd2e59..3e0eaa392f5 100644 --- a/qa/qa/page/group/show.rb +++ b/qa/qa/page/group/show.rb @@ -28,11 +28,9 @@ module QA def has_subgroup?(name) filter_by_name(name) - wait(reload: false) do - break false if page.has_content?('Sorry, no groups or projects matched your search') + page.has_text?(/#{name}|Sorry, no groups or projects matched your search/, wait: 60) - page.has_link?(name) - end + page.has_text?(name, wait: 0) end def go_to_new_subgroup diff --git a/qa/qa/page/project/job/show.rb b/qa/qa/page/project/job/show.rb index f1a859fd8ee..228ffd9d381 100644 --- a/qa/qa/page/project/job/show.rb +++ b/qa/qa/page/project/job/show.rb @@ -6,6 +6,7 @@ module QA::Page view 'app/views/shared/builds/_build_output.html.haml' do element :build_output, '.js-build-output' + element :loading_animation, '.js-build-refresh' end view 'app/assets/javascripts/vue_shared/components/ci_badge_link.vue' do @@ -20,6 +21,10 @@ module QA::Page find('.ci-status').text == PASSED_STATUS end + def trace_loading? + has_css?('.js-build-refresh') + end + # Reminder: You may wish to wait for a particular job status before checking output def output find('.js-build-output').text diff --git a/qa/qa/page/project/settings/protected_branches.rb b/qa/qa/page/project/settings/protected_branches.rb index a0903c3c4dc..0bd031e96b5 100644 --- a/qa/qa/page/project/settings/protected_branches.rb +++ b/qa/qa/page/project/settings/protected_branches.rb @@ -40,7 +40,7 @@ module QA click_allow(:push, 'No one') end - def allow_devs_and_masters_to_push + def allow_devs_and_maintainers_to_push click_allow(:push, 'Developers + Maintainers') end @@ -48,7 +48,7 @@ module QA click_allow(:merge, 'No one') end - def allow_devs_and_masters_to_merge + def allow_devs_and_maintainers_to_merge click_allow(:merge, 'Developers + Maintainers') end @@ -75,10 +75,6 @@ module QA within_element(:"allowed_to_#{action}_dropdown") do click_on text - - wait(reload: false) do - has_css?('.is-active') - end end end end 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 442ac312b4d..46b3e38c1c5 100644 --- a/qa/qa/specs/features/project/deploy_key_clone_spec.rb +++ b/qa/qa/specs/features/project/deploy_key_clone_spec.rb @@ -92,7 +92,9 @@ module QA Page::Project::Pipeline::Show.act { go_to_first_job } Page::Project::Job::Show.perform do |job| - job.wait(reload: false) { job.completed? } + job.wait(reload: false) do + job.completed? && !job.trace_loading? + end expect(job.passed?).to be_truthy, "Job status did not become \"passed\"." expect(job.output).to include(sha1sum) diff --git a/qa/qa/specs/features/repository/protected_branches_spec.rb b/qa/qa/specs/features/repository/protected_branches_spec.rb index efe7863dc87..491675875b9 100644 --- a/qa/qa/specs/features/repository/protected_branches_spec.rb +++ b/qa/qa/specs/features/repository/protected_branches_spec.rb @@ -7,12 +7,6 @@ module QA resource.name = 'protected-branch-project' end end - given(:location) do - Page::Project::Show.act do - choose_repository_clone_http - repository_location - end - end before do Runtime::Browser.visit(:gitlab, Page::Main::Login) @@ -26,44 +20,49 @@ module QA Capybara.execute_script 'localStorage.clear()' end - scenario 'user is able to protect a branch' do - protected_branch = Factory::Resource::Branch.fabricate! do |resource| - resource.branch_name = branch_name - resource.project = project - resource.allow_to_push = true - resource.protected = true + context 'when developers and maintainers are allowed to push to a protected branch' do + let!(:protected_branch) { create_protected_branch(allow_to_push: true) } + + scenario 'user with push rights successfully pushes to the protected branch' do + expect(protected_branch.name).to have_content(branch_name) + expect(protected_branch.push_allowance).to have_content('Developers + Maintainers') + + push = push_new_file(branch_name) + + expect(push.output).to match(/remote: To create a merge request for protected-branch, visit/) end + end + + context 'when developers and maintainers are not allowed to push to a protected branch' do + scenario 'user without push rights fails to push to the protected branch' do + create_protected_branch(allow_to_push: false) + + push = push_new_file(branch_name) - expect(protected_branch.name).to have_content(branch_name) - expect(protected_branch.push_allowance).to have_content('Developers + Maintainers') + expect(push.output) + .to match(/remote\: GitLab\: You are not allowed to push code to protected branches on this project/) + expect(push.output) + .to match(/\[remote rejected\] #{branch_name} -> #{branch_name} \(pre-receive hook declined\)/) + end end - scenario 'users without authorization cannot push to protected branch' do + def create_protected_branch(allow_to_push:) Factory::Resource::Branch.fabricate! do |resource| resource.branch_name = branch_name resource.project = project - resource.allow_to_push = false + resource.allow_to_push = allow_to_push resource.protected = true end + end - project.visit! - - Git::Repository.perform do |repository| - repository.uri = location.uri - repository.use_default_credentials - - repository.act do - clone - configure_identity('GitLab QA', 'root@gitlab.com') - checkout('protected-branch') - commit_file('README.md', 'readme content', 'Add a readme') - push_changes('protected-branch') - end - - expect(repository.push_output) - .to match(/remote\: GitLab\: You are not allowed to push code to protected branches on this project/) - expect(repository.push_output) - .to match(/\[remote rejected\] #{branch_name} -> #{branch_name} \(pre-receive hook declined\)/) + def push_new_file(branch) + Factory::Repository::Push.fabricate! do |resource| + resource.project = project + resource.file_name = 'new_file.md' + resource.file_content = '# This is a new file' + resource.commit_message = 'Add new_file.md' + resource.branch_name = branch_name + resource.new_branch = false end end end diff --git a/qa/spec/support/stub_env.rb b/qa/spec/support/stub_env.rb index bc8f3a5e22e..044804cd599 100644 --- a/qa/spec/support/stub_env.rb +++ b/qa/spec/support/stub_env.rb @@ -32,6 +32,8 @@ module Support allow(ENV).to receive(:[]).and_call_original allow(ENV).to receive(:key?).and_call_original allow(ENV).to receive(:fetch).and_call_original + # Prevent secrets from leaking in CI + allow(ENV).to receive(:inspect).and_return([]) add_stubbed_value(STUBBED_KEY, true) end end diff --git a/spec/controllers/boards/issues_controller_spec.rb b/spec/controllers/boards/issues_controller_spec.rb index dcb0faffbd4..e47ff8661a2 100644 --- a/spec/controllers/boards/issues_controller_spec.rb +++ b/spec/controllers/boards/issues_controller_spec.rb @@ -18,7 +18,7 @@ describe Boards::IssuesController do end describe 'GET index', :request_store do - let(:johndoe) { create(:user, avatar: fixture_file_upload(File.join(Rails.root, 'spec/fixtures/dk.png'))) } + let(:johndoe) { create(:user, avatar: fixture_file_upload(File.join('spec/fixtures/dk.png'))) } context 'with invalid board id' do it 'returns a not found 404 response' do diff --git a/spec/controllers/boards/lists_controller_spec.rb b/spec/controllers/boards/lists_controller_spec.rb index 71d45a22d91..57ccbf1d6b5 100644 --- a/spec/controllers/boards/lists_controller_spec.rb +++ b/spec/controllers/boards/lists_controller_spec.rb @@ -156,12 +156,18 @@ describe Boards::ListsController do def move(user:, board:, list:, position:) sign_in(user) - patch :update, namespace_id: project.namespace.to_param, - project_id: project, - board_id: board.to_param, - id: list.to_param, - list: { position: position }, - format: :json + params = { namespace_id: project.namespace.to_param, + project_id: project, + board_id: board.to_param, + id: list.to_param, + list: { position: position }, + format: :json } + + if Gitlab.rails5? + patch :update, params: params, as: :json + else + patch :update, params + end end end diff --git a/spec/controllers/groups/avatars_controller_spec.rb b/spec/controllers/groups/avatars_controller_spec.rb index 506aeee7d2a..7feecd0c380 100644 --- a/spec/controllers/groups/avatars_controller_spec.rb +++ b/spec/controllers/groups/avatars_controller_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe Groups::AvatarsController do let(:user) { create(:user) } - let(:group) { create(:group, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) } + let(:group) { create(:group, avatar: fixture_file_upload("spec/fixtures/dk.png", "image/png")) } before do group.add_owner(user) diff --git a/spec/controllers/import/gitlab_projects_controller_spec.rb b/spec/controllers/import/gitlab_projects_controller_spec.rb index 8759d3c0b97..d624659bce9 100644 --- a/spec/controllers/import/gitlab_projects_controller_spec.rb +++ b/spec/controllers/import/gitlab_projects_controller_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Import::GitlabProjectsController do set(:namespace) { create(:namespace) } set(:user) { namespace.owner } - let(:file) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') } + let(:file) { fixture_file_upload('spec/fixtures/doc_sample.txt', 'text/plain') } before do sign_in(user) diff --git a/spec/controllers/import/google_code_controller_spec.rb b/spec/controllers/import/google_code_controller_spec.rb index 4241db6e771..0763492d88a 100644 --- a/spec/controllers/import/google_code_controller_spec.rb +++ b/spec/controllers/import/google_code_controller_spec.rb @@ -4,7 +4,7 @@ describe Import::GoogleCodeController do include ImportSpecHelper let(:user) { create(:user) } - let(:dump_file) { fixture_file_upload(Rails.root + 'spec/fixtures/GoogleCodeProjectHosting.json', 'application/json') } + let(:dump_file) { fixture_file_upload('spec/fixtures/GoogleCodeProjectHosting.json', 'application/json') } before do sign_in(user) diff --git a/spec/controllers/profiles/avatars_controller_spec.rb b/spec/controllers/profiles/avatars_controller_spec.rb index 4fa0462ccdf..909709e1103 100644 --- a/spec/controllers/profiles/avatars_controller_spec.rb +++ b/spec/controllers/profiles/avatars_controller_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Profiles::AvatarsController do - let(:user) { create(:user, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png")) } + let(:user) { create(:user, avatar: fixture_file_upload("spec/fixtures/dk.png")) } before do sign_in(user) diff --git a/spec/controllers/projects/avatars_controller_spec.rb b/spec/controllers/projects/avatars_controller_spec.rb index 6a41c4d23ea..acfa2730d94 100644 --- a/spec/controllers/projects/avatars_controller_spec.rb +++ b/spec/controllers/projects/avatars_controller_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe Projects::AvatarsController do - let(:project) { create(:project, :repository, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) } + let(:project) { create(:project, :repository, avatar: fixture_file_upload("spec/fixtures/dk.png", "image/png")) } let(:user) { create(:user) } before do diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb index 994da3cd159..5bd22ea803c 100644 --- a/spec/controllers/projects_controller_spec.rb +++ b/spec/controllers/projects_controller_spec.rb @@ -6,8 +6,8 @@ describe ProjectsController do let(:project) { create(:project) } let(:public_project) { create(:project, :public) } let(:user) { create(:user) } - let(:jpg) { fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') } - let(:txt) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') } + let(:jpg) { fixture_file_upload('spec/fixtures/rails_sample.jpg', 'image/jpg') } + let(:txt) { fixture_file_upload('spec/fixtures/doc_sample.txt', 'text/plain') } describe 'GET new' do context 'with an authenticated user' do diff --git a/spec/controllers/uploads_controller_spec.rb b/spec/controllers/uploads_controller_spec.rb index 912aa82526a..1df2c954893 100644 --- a/spec/controllers/uploads_controller_spec.rb +++ b/spec/controllers/uploads_controller_spec.rb @@ -6,13 +6,13 @@ shared_examples 'content not cached without revalidation' do end describe UploadsController do - let!(:user) { create(:user, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) } + let!(:user) { create(:user, avatar: fixture_file_upload("spec/fixtures/dk.png", "image/png")) } describe 'POST create' do let(:model) { 'personal_snippet' } let(:snippet) { create(:personal_snippet, :public) } - let(:jpg) { fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') } - let(:txt) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') } + let(:jpg) { fixture_file_upload('spec/fixtures/rails_sample.jpg', 'image/jpg') } + let(:txt) { fixture_file_upload('spec/fixtures/doc_sample.txt', 'text/plain') } context 'when a user does not have permissions to upload a file' do it "returns 401 when the user is not logged in" do @@ -205,7 +205,7 @@ describe UploadsController do end context "when viewing a project avatar" do - let!(:project) { create(:project, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) } + let!(:project) { create(:project, avatar: fixture_file_upload("spec/fixtures/dk.png", "image/png")) } context "when the project is public" do before do @@ -314,7 +314,7 @@ describe UploadsController do end context "when viewing a group avatar" do - let!(:group) { create(:group, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) } + let!(:group) { create(:group, avatar: fixture_file_upload("spec/fixtures/dk.png", "image/png")) } context "when the group is public" do context "when not signed in" do @@ -521,7 +521,7 @@ describe UploadsController do context 'Appearance' do context 'when viewing a custom header logo' do - let!(:appearance) { create :appearance, header_logo: fixture_file_upload(Rails.root.join('spec/fixtures/dk.png'), 'image/png') } + let!(:appearance) { create :appearance, header_logo: fixture_file_upload('spec/fixtures/dk.png', 'image/png') } context 'when not signed in' do it 'responds with status 200' do @@ -541,7 +541,7 @@ describe UploadsController do end context 'when viewing a custom logo' do - let!(:appearance) { create :appearance, logo: fixture_file_upload(Rails.root.join('spec/fixtures/dk.png'), 'image/png') } + let!(:appearance) { create :appearance, logo: fixture_file_upload('spec/fixtures/dk.png', 'image/png') } context 'when not signed in' do it 'responds with status 200' do @@ -562,7 +562,7 @@ describe UploadsController do end context 'original filename or a version filename must match' do - let!(:appearance) { create :appearance, favicon: fixture_file_upload(Rails.root.join('spec/fixtures/dk.png'), 'image/png') } + let!(:appearance) { create :appearance, favicon: fixture_file_upload('spec/fixtures/dk.png', 'image/png') } context 'has a valid filename on the original file' do it 'successfully returns the file' do diff --git a/spec/factories/lfs_objects.rb b/spec/factories/lfs_objects.rb index eaf3a4ed497..c909471bb55 100644 --- a/spec/factories/lfs_objects.rb +++ b/spec/factories/lfs_objects.rb @@ -7,7 +7,7 @@ FactoryBot.define do end trait :with_file do - file { fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "`/png") } + file { fixture_file_upload("spec/fixtures/dk.png", "`/png") } end # The uniqueness constraint means we can't use the correct OID for all LFS diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb index 40f3fa7d69b..9fdc3e616a6 100644 --- a/spec/factories/notes.rb +++ b/spec/factories/notes.rb @@ -130,11 +130,11 @@ FactoryBot.define do end trait :with_attachment do - attachment { fixture_file_upload(Rails.root.join( "spec/fixtures/dk.png"), "image/png") } + attachment { fixture_file_upload("spec/fixtures/dk.png", "image/png") } end trait :with_svg_attachment do - attachment { fixture_file_upload(Rails.root.join("spec/fixtures/unsanitized.svg"), "image/svg+xml") } + attachment { fixture_file_upload("spec/fixtures/unsanitized.svg", "image/svg+xml") } end transient do diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb index 62a2ec55b00..87fa3f60826 100644 --- a/spec/features/commits_spec.rb +++ b/spec/features/commits_spec.rb @@ -47,7 +47,7 @@ describe 'Commits' do context 'commit status is Ci Build' do let!(:build) { create(:ci_build, pipeline: pipeline) } - let(:artifacts_file) { fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') } + let(:artifacts_file) { fixture_file_upload('spec/fixtures/banana_sample.gif', 'image/gif') } context 'when logged as developer' do before do diff --git a/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb b/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb index fd1629746ef..d3104b448e0 100644 --- a/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb +++ b/spec/features/merge_request/user_sees_mini_pipeline_graph_spec.rb @@ -23,8 +23,8 @@ describe 'Merge request < User sees mini pipeline graph', :js do end context 'as json' do - let(:artifacts_file1) { fixture_file_upload(Rails.root.join('spec/fixtures/banana_sample.gif'), 'image/gif') } - let(:artifacts_file2) { fixture_file_upload(Rails.root.join('spec/fixtures/dk.png'), 'image/png') } + let(:artifacts_file1) { fixture_file_upload(File.join('spec/fixtures/banana_sample.gif'), 'image/gif') } + let(:artifacts_file2) { fixture_file_upload(File.join('spec/fixtures/dk.png'), 'image/png') } before do create(:ci_build, :success, :trace_artifact, pipeline: pipeline, legacy_artifacts_file: artifacts_file1) diff --git a/spec/features/projects/jobs/permissions_spec.rb b/spec/features/projects/jobs/permissions_spec.rb index 31abadf9bd6..e9588daf37d 100644 --- a/spec/features/projects/jobs/permissions_spec.rb +++ b/spec/features/projects/jobs/permissions_spec.rb @@ -88,8 +88,7 @@ describe 'Project Jobs Permissions' do describe 'artifacts page' do context 'when recent job has artifacts available' do before do - artifacts = Rails.root.join('spec/fixtures/ci_build_artifacts.zip') - archive = fixture_file_upload(artifacts, 'application/zip') + archive = fixture_file_upload('spec/fixtures/ci_build_artifacts.zip') job.update_attributes(legacy_artifacts_file: archive) end diff --git a/spec/features/projects/jobs_spec.rb b/spec/features/projects/jobs_spec.rb index 9d1c4cbad8b..d2aaf60e72c 100644 --- a/spec/features/projects/jobs_spec.rb +++ b/spec/features/projects/jobs_spec.rb @@ -11,7 +11,7 @@ feature 'Jobs', :clean_gitlab_redis_shared_state do let(:job2) { create(:ci_build) } let(:artifacts_file) do - fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') + fixture_file_upload('spec/fixtures/banana_sample.gif', 'image/gif') end before do diff --git a/spec/features/projects/pages_spec.rb b/spec/features/projects/pages_spec.rb index bdd49f731c7..a2899ec0f48 100644 --- a/spec/features/projects/pages_spec.rb +++ b/spec/features/projects/pages_spec.rb @@ -314,8 +314,8 @@ feature 'Pages' do project: project, pipeline: pipeline, ref: 'HEAD', - legacy_artifacts_file: fixture_file_upload(Rails.root.join('spec/fixtures/pages.zip')), - legacy_artifacts_metadata: fixture_file_upload(Rails.root.join('spec/fixtures/pages.zip.meta')) + legacy_artifacts_file: fixture_file_upload(File.join('spec/fixtures/pages.zip')), + legacy_artifacts_metadata: fixture_file_upload(File.join('spec/fixtures/pages.zip.meta')) ) end diff --git a/spec/features/tags/master_deletes_tag_spec.rb b/spec/features/tags/master_deletes_tag_spec.rb index c0b4fa52526..9981bfa4609 100644 --- a/spec/features/tags/master_deletes_tag_spec.rb +++ b/spec/features/tags/master_deletes_tag_spec.rb @@ -38,7 +38,7 @@ feature 'Master deletes tag' do context 'when Gitaly operation_user_delete_tag feature is enabled' do before do allow_any_instance_of(Gitlab::GitalyClient::OperationService).to receive(:rm_tag) - .and_raise(Gitlab::Git::HooksService::PreReceiveError, 'Do not delete tags') + .and_raise(Gitlab::Git::PreReceiveError, 'Do not delete tags') end scenario 'shows the error message' do @@ -51,7 +51,7 @@ feature 'Master deletes tag' do context 'when Gitaly operation_user_delete_tag feature is disabled', :skip_gitaly_mock do before do allow_any_instance_of(Gitlab::Git::HooksService).to receive(:execute) - .and_raise(Gitlab::Git::HooksService::PreReceiveError, 'Do not delete tags') + .and_raise(Gitlab::Git::PreReceiveError, 'Do not delete tags') end scenario 'shows the error message' do diff --git a/spec/helpers/emails_helper_spec.rb b/spec/helpers/emails_helper_spec.rb index 2390c1f3e5d..139387e0b24 100644 --- a/spec/helpers/emails_helper_spec.rb +++ b/spec/helpers/emails_helper_spec.rb @@ -47,9 +47,7 @@ describe EmailsHelper do describe '#header_logo' do context 'there is a brand item with a logo' do it 'returns the brand header logo' do - appearance = create :appearance, header_logo: fixture_file_upload( - Rails.root.join('spec/fixtures/dk.png') - ) + appearance = create :appearance, header_logo: fixture_file_upload('spec/fixtures/dk.png') expect(header_logo).to eq( %{<img style="height: 50px" src="/uploads/-/system/appearance/header_logo/#{appearance.id}/dk.png" alt="Dk" />} diff --git a/spec/helpers/groups_helper_spec.rb b/spec/helpers/groups_helper_spec.rb index b48c252acd3..6c94bd4e504 100644 --- a/spec/helpers/groups_helper_spec.rb +++ b/spec/helpers/groups_helper_spec.rb @@ -4,9 +4,9 @@ describe GroupsHelper do include ApplicationHelper describe 'group_icon' do - avatar_file_path = File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif') - it 'returns an url for the avatar' do + avatar_file_path = File.join('spec', 'fixtures', 'banana_sample.gif') + group = create(:group) group.avatar = fixture_file_upload(avatar_file_path) group.save! @@ -17,9 +17,9 @@ describe GroupsHelper do end describe 'group_icon_url' do - avatar_file_path = File.join(Rails.root, 'spec', 'fixtures', 'banana_sample.gif') - it 'returns an url for the avatar' do + avatar_file_path = File.join('spec', 'fixtures', 'banana_sample.gif') + group = create(:group) group.avatar = fixture_file_upload(avatar_file_path) group.save! diff --git a/spec/javascripts/clusters/stores/clusters_store_spec.js b/spec/javascripts/clusters/stores/clusters_store_spec.js index 6854b016852..9e43552f740 100644 --- a/spec/javascripts/clusters/stores/clusters_store_spec.js +++ b/spec/javascripts/clusters/stores/clusters_store_spec.js @@ -110,7 +110,7 @@ describe('Clusters Store', () => { expect( store.state.applications.jupyter.hostname, - ).toEqual(`jupyter.${store.state.applications.ingress.externalIp}.xip.io`); + ).toEqual(`jupyter.${store.state.applications.ingress.externalIp}.nip.io`); }); }); }); diff --git a/spec/javascripts/ide/components/pipelines/list_spec.js b/spec/javascripts/ide/components/pipelines/list_spec.js index 2bb5aa08c3b..68487733cb9 100644 --- a/spec/javascripts/ide/components/pipelines/list_spec.js +++ b/spec/javascripts/ide/components/pipelines/list_spec.js @@ -45,12 +45,15 @@ describe('IDE pipelines list', () => { setTimeout(done); }); - afterEach(() => { - vm.$store.dispatch('pipelines/stopPipelinePolling'); - vm.$store.dispatch('pipelines/clearEtagPoll'); - + afterEach(done => { vm.$destroy(); mock.restore(); + + vm.$store + .dispatch('pipelines/stopPipelinePolling') + .then(() => vm.$store.dispatch('pipelines/clearEtagPoll')) + .then(done) + .catch(done.fail); }); it('renders pipeline data', () => { diff --git a/spec/javascripts/ide/stores/modules/merge_requests/actions_spec.js b/spec/javascripts/ide/stores/modules/merge_requests/actions_spec.js index d178a44b76a..03ec08d05c3 100644 --- a/spec/javascripts/ide/stores/modules/merge_requests/actions_spec.js +++ b/spec/javascripts/ide/stores/modules/merge_requests/actions_spec.js @@ -199,28 +199,39 @@ describe('IDE merge requests actions', () => { }); it('commits reset mutations and actions', done => { - testAction( - openMergeRequest, - { projectPath: 'gitlab-org/gitlab-ce', id: '1' }, - mockedState, - [ - { type: 'CLEAR_PROJECTS' }, - { type: 'SET_CURRENT_MERGE_REQUEST', payload: '1' }, - { type: 'RESET_OPEN_FILES' }, - ], - [ - { type: 'pipelines/stopPipelinePolling' }, - { type: 'pipelines/clearEtagPoll' }, - { type: 'pipelines/resetLatestPipeline' }, - { type: 'setCurrentBranchId', payload: '' }, - ], - done, - ); + const commit = jasmine.createSpy(); + const dispatch = jasmine.createSpy().and.returnValue(Promise.resolve()); + openMergeRequest({ commit, dispatch }, { projectPath: 'gitlab-org/gitlab-ce', id: '1' }); + + setTimeout(() => { + expect(commit.calls.argsFor(0)).toEqual(['CLEAR_PROJECTS', null, { root: true }]); + expect(commit.calls.argsFor(1)).toEqual(['SET_CURRENT_MERGE_REQUEST', '1', { root: true }]); + expect(commit.calls.argsFor(2)).toEqual(['RESET_OPEN_FILES', null, { root: true }]); + + expect(dispatch.calls.argsFor(0)).toEqual([ + 'pipelines/resetLatestPipeline', + null, + { root: true }, + ]); + expect(dispatch.calls.argsFor(1)).toEqual(['setCurrentBranchId', '', { root: true }]); + expect(dispatch.calls.argsFor(2)).toEqual([ + 'pipelines/stopPipelinePolling', + null, + { root: true }, + ]); + expect(dispatch.calls.argsFor(3)).toEqual([ + 'pipelines/clearEtagPoll', + null, + { root: true }, + ]); + + done(); + }); }); it('pushes new route', () => { openMergeRequest( - { commit() {}, dispatch() {} }, + { commit() {}, dispatch: () => Promise.resolve() }, { projectPath: 'gitlab-org/gitlab-ce', id: '1' }, ); diff --git a/spec/javascripts/vue_mr_widget/components/mr_widget_author_time_spec.js b/spec/javascripts/vue_mr_widget/components/mr_widget_author_time_spec.js index 6784b498c29..10143402acf 100644 --- a/spec/javascripts/vue_mr_widget/components/mr_widget_author_time_spec.js +++ b/spec/javascripts/vue_mr_widget/components/mr_widget_author_time_spec.js @@ -1,12 +1,12 @@ import Vue from 'vue'; -import authorTimeComponent from '~/vue_merge_request_widget/components/mr_widget_author_time.vue'; +import MrWidgetAuthorTime from '~/vue_merge_request_widget/components/mr_widget_author_time.vue'; import mountComponent from 'spec/helpers/vue_mount_component_helper'; -describe('MRWidgetAuthorTime', () => { +describe('MrWidgetAuthorTime', () => { let vm; beforeEach(() => { - const Component = Vue.extend(authorTimeComponent); + const Component = Vue.extend(MrWidgetAuthorTime); vm = mountComponent(Component, { actionText: 'Merged by', @@ -34,7 +34,7 @@ describe('MRWidgetAuthorTime', () => { }); it('renders provided time', () => { - expect(vm.$el.querySelector('time').getAttribute('title')).toEqual('2017-03-23T23:02:00.807Z'); + expect(vm.$el.querySelector('time').getAttribute('data-original-title')).toEqual('2017-03-23T23:02:00.807Z'); expect(vm.$el.querySelector('time').textContent.trim()).toEqual('12 hours ago'); }); }); diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js index adeea03481f..3e2fd71b5b8 100644 --- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js +++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_merged_spec.js @@ -186,7 +186,7 @@ describe('MRWidgetMerged', () => { it('should use mergedEvent mergedAt as tooltip title', () => { expect( - vm.$el.querySelector('time').getAttribute('title'), + vm.$el.querySelector('time').getAttribute('data-original-title'), ).toBe('Jan 24, 2018 1:02pm GMT+0000'); }); }); diff --git a/spec/lib/gitlab/favicon_spec.rb b/spec/lib/gitlab/favicon_spec.rb index fdc5c0180e4..08c4a474217 100644 --- a/spec/lib/gitlab/favicon_spec.rb +++ b/spec/lib/gitlab/favicon_spec.rb @@ -18,7 +18,7 @@ RSpec.describe Gitlab::Favicon, :request_store do end it 'uses the custom favicon if a favicon appearance is present' do - create :appearance, favicon: fixture_file_upload(Rails.root.join('spec/fixtures/dk.png')) + create :appearance, favicon: fixture_file_upload('spec/fixtures/dk.png') expect(described_class.main).to match %r{/uploads/-/system/appearance/favicon/\d+/favicon_main_dk.png} end end diff --git a/spec/lib/gitlab/git/hook_spec.rb b/spec/lib/gitlab/git/hook_spec.rb index 2fe1f5603ce..d9b3d0cf419 100644 --- a/spec/lib/gitlab/git/hook_spec.rb +++ b/spec/lib/gitlab/git/hook_spec.rb @@ -9,24 +9,31 @@ describe Gitlab::Git::Hook do end describe "#trigger" do - let(:project) { create(:project, :repository) } + set(:project) { create(:project, :repository) } let(:repository) { project.repository.raw_repository } let(:repo_path) { repository.path } + let(:hooks_dir) { File.join(repo_path, 'hooks') } let(:user) { create(:user) } let(:gl_id) { Gitlab::GlId.gl_id(user) } let(:gl_username) { user.username } def create_hook(name) - FileUtils.mkdir_p(File.join(repo_path, 'hooks')) - File.open(File.join(repo_path, 'hooks', name), 'w', 0755) do |f| - f.write('exit 0') + FileUtils.mkdir_p(hooks_dir) + hook_path = File.join(hooks_dir, name) + File.open(hook_path, 'w', 0755) do |f| + f.write(<<~HOOK) + #!/bin/sh + exit 0 + HOOK end end def create_failing_hook(name) - FileUtils.mkdir_p(File.join(repo_path, 'hooks')) - File.open(File.join(repo_path, 'hooks', name), 'w', 0755) do |f| - f.write(<<-HOOK) + FileUtils.mkdir_p(hooks_dir) + hook_path = File.join(hooks_dir, name) + File.open(hook_path, 'w', 0755) do |f| + f.write(<<~HOOK) + #!/bin/sh echo 'regular message from the hook' echo 'error message from the hook' 1>&2 echo 'error message from the hook line 2' 1>&2 @@ -38,7 +45,7 @@ describe Gitlab::Git::Hook do ['pre-receive', 'post-receive', 'update'].each do |hook_name| context "when triggering a #{hook_name} hook" do context "when the hook is successful" do - let(:hook_path) { File.join(repo_path, 'hooks', hook_name) } + let(:hook_path) { File.join(hooks_dir, hook_name) } let(:gl_repository) { Gitlab::GlRepository.gl_repository(project, false) } let(:env) do { @@ -76,7 +83,7 @@ describe Gitlab::Git::Hook do status, errors = hook.trigger(gl_id, gl_username, blank, blank, ref) expect(status).to be false - expect(errors).to eq("error message from the hook<br>error message from the hook line 2<br>") + expect(errors).to eq("error message from the hook\nerror message from the hook line 2\n") end end end diff --git a/spec/lib/gitlab/git/hooks_service_spec.rb b/spec/lib/gitlab/git/hooks_service_spec.rb index 3ed3feb4c74..9337aa39e13 100644 --- a/spec/lib/gitlab/git/hooks_service_spec.rb +++ b/spec/lib/gitlab/git/hooks_service_spec.rb @@ -26,24 +26,24 @@ describe Gitlab::Git::HooksService, seed_helper: true do context 'when pre-receive hook failed' do it 'does not call post-receive hook' do - expect(service).to receive(:run_hook).with('pre-receive').and_return([false, '']) + expect(service).to receive(:run_hook).with('pre-receive').and_return([false, 'hello world']) expect(service).not_to receive(:run_hook).with('post-receive') expect do service.execute(user, repository, blankrev, newrev, ref) - end.to raise_error(Gitlab::Git::HooksService::PreReceiveError) + end.to raise_error(Gitlab::Git::PreReceiveError, 'hello world') end end context 'when update hook failed' do it 'does not call post-receive hook' do expect(service).to receive(:run_hook).with('pre-receive').and_return([true, nil]) - expect(service).to receive(:run_hook).with('update').and_return([false, '']) + expect(service).to receive(:run_hook).with('update').and_return([false, 'hello world']) expect(service).not_to receive(:run_hook).with('post-receive') expect do service.execute(user, repository, blankrev, newrev, ref) - end.to raise_error(Gitlab::Git::HooksService::PreReceiveError) + end.to raise_error(Gitlab::Git::PreReceiveError, 'hello world') end end end diff --git a/spec/lib/gitlab/git/pre_receive_error_spec.rb b/spec/lib/gitlab/git/pre_receive_error_spec.rb new file mode 100644 index 00000000000..1b8be62dec6 --- /dev/null +++ b/spec/lib/gitlab/git/pre_receive_error_spec.rb @@ -0,0 +1,9 @@ +require 'spec_helper' + +describe Gitlab::Git::PreReceiveError do + it 'makes its message HTML-friendly' do + ex = described_class.new("hello\nworld\n") + + expect(ex.message).to eq('hello<br>world<br>') + end +end diff --git a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb index 9fbdd73ee0e..9709f1f5646 100644 --- a/spec/lib/gitlab/gitaly_client/operation_service_spec.rb +++ b/spec/lib/gitlab/gitaly_client/operation_service_spec.rb @@ -48,7 +48,7 @@ describe Gitlab::GitalyClient::OperationService do .and_return(response) expect { subject }.to raise_error( - Gitlab::Git::HooksService::PreReceiveError, "something failed") + Gitlab::Git::PreReceiveError, "something failed") end end end @@ -85,7 +85,7 @@ describe Gitlab::GitalyClient::OperationService do .and_return(response) expect { subject }.to raise_error( - Gitlab::Git::HooksService::PreReceiveError, "something failed") + Gitlab::Git::PreReceiveError, "something failed") end end end diff --git a/spec/lib/gitlab/github_import/sequential_importer_spec.rb b/spec/lib/gitlab/github_import/sequential_importer_spec.rb index 6089b0b751f..05d3243f806 100644 --- a/spec/lib/gitlab/github_import/sequential_importer_spec.rb +++ b/spec/lib/gitlab/github_import/sequential_importer_spec.rb @@ -30,7 +30,6 @@ describe Gitlab::GithubImport::SequentialImporter do expect(instance).to receive(:execute) end - expect(repository).to receive(:after_import) expect(importer.execute).to eq(true) end end diff --git a/spec/lib/gitlab/import_export/avatar_saver_spec.rb b/spec/lib/gitlab/import_export/avatar_saver_spec.rb index f40d4bc2d08..2223f163177 100644 --- a/spec/lib/gitlab/import_export/avatar_saver_spec.rb +++ b/spec/lib/gitlab/import_export/avatar_saver_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Gitlab::ImportExport::AvatarSaver do let(:shared) { project.import_export_shared } let(:export_path) { "#{Dir.tmpdir}/project_tree_saver_spec" } - let(:project_with_avatar) { create(:project, avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png")) } + let(:project_with_avatar) { create(:project, avatar: fixture_file_upload("spec/fixtures/dk.png", "image/png")) } let(:project) { create(:project) } before do diff --git a/spec/lib/gitlab/import_export/uploads_saver_spec.rb b/spec/lib/gitlab/import_export/uploads_saver_spec.rb index 1304d8fabfc..095687fa89d 100644 --- a/spec/lib/gitlab/import_export/uploads_saver_spec.rb +++ b/spec/lib/gitlab/import_export/uploads_saver_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Gitlab::ImportExport::UploadsSaver do describe 'bundle a project Git repo' do let(:export_path) { "#{Dir.tmpdir}/uploads_saver_spec" } - let(:file) { fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') } + let(:file) { fixture_file_upload('spec/fixtures/banana_sample.gif', 'image/gif') } let(:shared) { project.import_export_shared } before do diff --git a/spec/lib/gitlab/url_blocker_spec.rb b/spec/lib/gitlab/url_blocker_spec.rb index 81dbbb962dd..6f5f9938eca 100644 --- a/spec/lib/gitlab/url_blocker_spec.rb +++ b/spec/lib/gitlab/url_blocker_spec.rb @@ -58,20 +58,6 @@ describe Gitlab::UrlBlocker do end end - it 'returns true for a non-alphanumeric username' do - stub_resolv - - aggregate_failures do - expect(described_class).to be_blocked_url('ssh://-oProxyCommand=whoami@example.com/a') - - # The leading character here is a Unicode "soft hyphen" - expect(described_class).to be_blocked_url('ssh://oProxyCommand=whoami@example.com/a') - - # Unicode alphanumerics are allowed - expect(described_class).not_to be_blocked_url('ssh://ğitlab@example.com/a') - end - end - it 'returns true for invalid URL' do expect(described_class.blocked_url?('http://:8080')).to be true end @@ -120,6 +106,38 @@ describe Gitlab::UrlBlocker do allow(Addrinfo).to receive(:getaddrinfo).and_call_original end end + + context 'when enforce_user is' do + before do + stub_resolv + end + + context 'false (default)' do + it 'does not block urls with a non-alphanumeric username' do + expect(described_class).not_to be_blocked_url('ssh://-oProxyCommand=whoami@example.com/a') + + # The leading character here is a Unicode "soft hyphen" + expect(described_class).not_to be_blocked_url('ssh://oProxyCommand=whoami@example.com/a') + + # Unicode alphanumerics are allowed + expect(described_class).not_to be_blocked_url('ssh://ğitlab@example.com/a') + end + end + + context 'true' do + it 'blocks urls with a non-alphanumeric username' do + aggregate_failures do + expect(described_class).to be_blocked_url('ssh://-oProxyCommand=whoami@example.com/a', enforce_user: true) + + # The leading character here is a Unicode "soft hyphen" + expect(described_class).to be_blocked_url('ssh://oProxyCommand=whoami@example.com/a', enforce_user: true) + + # Unicode alphanumerics are allowed + expect(described_class).not_to be_blocked_url('ssh://ğitlab@example.com/a', enforce_user: true) + end + end + end + end end # Resolv does not support resolving UTF-8 domain names diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb index a3e119cbc27..efddd4e7662 100644 --- a/spec/models/ci/job_artifact_spec.rb +++ b/spec/models/ci/job_artifact_spec.rb @@ -76,12 +76,12 @@ describe Ci::JobArtifact do context 'updating the artifact file' do it 'updates the artifact size' do - artifact.update!(file: fixture_file_upload(File.join(Rails.root, 'spec/fixtures/dk.png'))) + artifact.update!(file: fixture_file_upload('spec/fixtures/dk.png')) expect(artifact.size).to eq(1062) end it 'updates the project statistics' do - expect { artifact.update!(file: fixture_file_upload(File.join(Rails.root, 'spec/fixtures/dk.png'))) } + expect { artifact.update!(file: fixture_file_upload('spec/fixtures/dk.png')) } .to change { artifact.project.statistics.reload.build_artifacts_size } .by(1062 - 106365) end diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index c3b4eb17a5c..b9f1c7dd5df 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -475,7 +475,7 @@ describe JiraService do end it 'includes returns the custom favicon' do - create :appearance, favicon: fixture_file_upload(Rails.root.join('spec/fixtures/dk.png')) + create :appearance, favicon: fixture_file_upload('spec/fixtures/dk.png') props = described_class.new.send(:build_remote_link_props, url: 'http://example.com', title: 'title') expect(props[:object][:icon][:url16x16]).to match %r{^http://localhost/uploads/-/system/appearance/favicon/\d+/favicon_main_dk.png$} diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 1a6ad3edd78..a7a6d0bb09c 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -238,20 +238,27 @@ describe Project do expect(project2.import_data).to be_nil end - it "does not allow blocked import_url localhost" do + it "does not allow import_url pointing to localhost" do project2 = build(:project, import_url: 'http://localhost:9000/t.git') expect(project2).to be_invalid expect(project2.errors[:import_url].first).to include('Requests to localhost are not allowed') end - it "does not allow blocked import_url port" do + it "does not allow import_url with invalid ports" do project2 = build(:project, import_url: 'http://github.com:25/t.git') expect(project2).to be_invalid expect(project2.errors[:import_url].first).to include('Only allowed ports are 22, 80, 443') end + it "does not allow import_url with invalid user" do + project2 = build(:project, import_url: 'http://$user:password@github.com/t.git') + + expect(project2).to be_invalid + expect(project2.errors[:import_url].first).to include('Username needs to start with an alphanumeric character') + end + describe 'project pending deletion' do let!(:project_pending_deletion) do create(:project, @@ -1726,7 +1733,11 @@ describe Project do .with(project.repository_storage, project.disk_path, project.import_url) .and_return(true) - expect_any_instance_of(Repository).to receive(:after_import) + # Works around https://github.com/rspec/rspec-mocks/issues/910 + expect(described_class).to receive(:find).with(project.id).twice.and_return(project) + expect(project.repository).to receive(:after_import) + .and_call_original + expect(project.wiki.repository).to receive(:after_import) .and_call_original end @@ -3391,10 +3402,11 @@ describe Project do end describe '#after_import' do - let(:project) { build(:project) } + let(:project) { create(:project) } it 'runs the correct hooks' do expect(project.repository).to receive(:after_import) + expect(project.wiki.repository).to receive(:after_import) expect(project).to receive(:import_finish) expect(project).to receive(:update_project_counter_caches) expect(project).to receive(:remove_import_jid) diff --git a/spec/models/remote_mirror_spec.rb b/spec/models/remote_mirror_spec.rb index 1d94abe4195..4c086eeadfc 100644 --- a/spec/models/remote_mirror_spec.rb +++ b/spec/models/remote_mirror_spec.rb @@ -15,6 +15,13 @@ describe RemoteMirror do expect(remote_mirror).not_to be_valid end + + it 'does not allow url with an invalid user' do + remote_mirror = build(:remote_mirror, url: 'http://$user:password@invalid.invalid') + + expect(remote_mirror).to be_invalid + expect(remote_mirror.errors[:url].first).to include('Username needs to start with an alphanumeric character') + end end end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 7c0a1cd967c..b6df048d4ca 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1195,7 +1195,7 @@ describe Repository do Gitlab::Git::OperationService.new(git_user, repository.raw_repository).with_branch('feature') do new_rev end - end.to raise_error(Gitlab::Git::HooksService::PreReceiveError) + end.to raise_error(Gitlab::Git::PreReceiveError) end end @@ -1938,13 +1938,13 @@ describe Repository do context 'when pre hooks failed' do before do allow_any_instance_of(Gitlab::GitalyClient::OperationService) - .to receive(:user_delete_branch).and_raise(Gitlab::Git::HooksService::PreReceiveError) + .to receive(:user_delete_branch).and_raise(Gitlab::Git::PreReceiveError) end it 'gets an error and does not delete the branch' do expect do repository.rm_branch(user, 'feature') - end.to raise_error(Gitlab::Git::HooksService::PreReceiveError) + end.to raise_error(Gitlab::Git::PreReceiveError) expect(repository.find_branch('feature')).not_to be_nil end @@ -1980,7 +1980,7 @@ describe Repository do expect do repository.rm_branch(user, 'feature') - end.to raise_error(Gitlab::Git::HooksService::PreReceiveError) + end.to raise_error(Gitlab::Git::PreReceiveError) end it 'does not delete the branch' do @@ -1988,7 +1988,7 @@ describe Repository do expect do repository.rm_branch(user, 'feature') - end.to raise_error(Gitlab::Git::HooksService::PreReceiveError) + end.to raise_error(Gitlab::Git::PreReceiveError) expect(repository.find_branch('feature')).not_to be_nil end end diff --git a/spec/requests/api/project_import_spec.rb b/spec/requests/api/project_import_spec.rb index f8c64f063af..97dffdc9233 100644 --- a/spec/requests/api/project_import_spec.rb +++ b/spec/requests/api/project_import_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe API::ProjectImport do let(:export_path) { "#{Dir.tmpdir}/project_export_spec" } let(:user) { create(:user) } - let(:file) { File.join(Rails.root, 'spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') } + let(:file) { File.join('spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') } let(:namespace) { create(:group) } before do allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path) diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index 9b7c3205c1f..99103039f77 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -518,7 +518,7 @@ describe API::Projects do end it 'uploads avatar for project a project' do - project = attributes_for(:project, avatar: fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif')) + project = attributes_for(:project, avatar: fixture_file_upload('spec/fixtures/banana_sample.gif', 'image/gif')) post api('/projects', user), project @@ -777,7 +777,7 @@ describe API::Projects do end it "uploads the file and returns its info" do - post api("/projects/#{project.id}/uploads", user), file: fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png") + post api("/projects/#{project.id}/uploads", user), file: fixture_file_upload("spec/fixtures/dk.png", "image/png") expect(response).to have_gitlab_http_status(201) expect(json_response['alt']).to eq("dk") diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb index 57d238ff79b..16e6f19773f 100644 --- a/spec/requests/api/runner_spec.rb +++ b/spec/requests/api/runner_spec.rb @@ -1085,8 +1085,8 @@ describe API::Runner, :clean_gitlab_redis_shared_state do let(:jwt_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') } let(:headers) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => jwt_token } } let(:headers_with_token) { headers.merge(API::Helpers::Runner::JOB_TOKEN_HEADER => job.token) } - let(:file_upload) { fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') } - let(:file_upload2) { fixture_file_upload(Rails.root + 'spec/fixtures/dk.png', 'image/gif') } + let(:file_upload) { fixture_file_upload('spec/fixtures/banana_sample.gif', 'image/gif') } + let(:file_upload2) { fixture_file_upload('spec/fixtures/dk.png', 'image/gif') } before do stub_artifacts_object_storage diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb index 05637eb0729..3377d67b644 100644 --- a/spec/requests/api/users_spec.rb +++ b/spec/requests/api/users_spec.rb @@ -512,7 +512,7 @@ describe API::Users do end it 'updates user with avatar' do - put api("/users/#{user.id}", admin), { avatar: fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') } + put api("/users/#{user.id}", admin), { avatar: fixture_file_upload('spec/fixtures/banana_sample.gif', 'image/gif') } user.reload diff --git a/spec/requests/openid_connect_spec.rb b/spec/requests/openid_connect_spec.rb index be286c490fe..bcb8d6c2bfc 100644 --- a/spec/requests/openid_connect_spec.rb +++ b/spec/requests/openid_connect_spec.rb @@ -61,7 +61,7 @@ describe 'OpenID Connect requests' do email: private_email.email, public_email: public_email.email, website_url: 'https://example.com', - avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png") + avatar: fixture_file_upload('spec/fixtures/dk.png') ) end diff --git a/spec/services/merge_requests/ff_merge_service_spec.rb b/spec/services/merge_requests/ff_merge_service_spec.rb index 5ef6365fcc9..28f56d19657 100644 --- a/spec/services/merge_requests/ff_merge_service_spec.rb +++ b/spec/services/merge_requests/ff_merge_service_spec.rb @@ -72,7 +72,7 @@ describe MergeRequests::FfMergeService do it 'logs and saves error if there is an PreReceiveError exception' do error_message = 'error message' - allow(service).to receive(:repository).and_raise(Gitlab::Git::HooksService::PreReceiveError, error_message) + allow(service).to receive(:repository).and_raise(Gitlab::Git::PreReceiveError, error_message) allow(service).to receive(:execute_hooks) service.execute(merge_request) diff --git a/spec/services/merge_requests/merge_service_spec.rb b/spec/services/merge_requests/merge_service_spec.rb index dc30a9bccc1..ef2738ef504 100644 --- a/spec/services/merge_requests/merge_service_spec.rb +++ b/spec/services/merge_requests/merge_service_spec.rb @@ -226,7 +226,7 @@ describe MergeRequests::MergeService do it 'logs and saves error if there is an PreReceiveError exception' do error_message = 'error message' - allow(service).to receive(:repository).and_raise(Gitlab::Git::HooksService::PreReceiveError, error_message) + allow(service).to receive(:repository).and_raise(Gitlab::Git::PreReceiveError, error_message) allow(service).to receive(:execute_hooks) service.execute(merge_request) diff --git a/spec/services/projects/fork_service_spec.rb b/spec/services/projects/fork_service_spec.rb index a93f6f1ddc2..c15f5120b8a 100644 --- a/spec/services/projects/fork_service_spec.rb +++ b/spec/services/projects/fork_service_spec.rb @@ -8,7 +8,7 @@ describe Projects::ForkService do before do @from_user = create(:user) @from_namespace = @from_user.namespace - avatar = fixture_file_upload(Rails.root + "spec/fixtures/dk.png", "image/png") + avatar = fixture_file_upload("spec/fixtures/dk.png", "image/png") @from_project = create(:project, :repository, creator_id: @from_user.id, diff --git a/spec/services/projects/gitlab_projects_import_service_spec.rb b/spec/services/projects/gitlab_projects_import_service_spec.rb index ee1a886f5d6..0a898e9b89b 100644 --- a/spec/services/projects/gitlab_projects_import_service_spec.rb +++ b/spec/services/projects/gitlab_projects_import_service_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Projects::GitlabProjectsImportService do set(:namespace) { create(:namespace) } let(:path) { 'test-path' } - let(:file) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') } + let(:file) { fixture_file_upload('spec/fixtures/doc_sample.txt', 'text/plain') } let(:overwrite) { false } let(:import_params) { { namespace_id: namespace.id, path: path, file: file, overwrite: overwrite } } subject { described_class.new(namespace.owner, import_params) } diff --git a/spec/services/projects/participants_service_spec.rb b/spec/services/projects/participants_service_spec.rb index 0d18ceb8ff8..6040f9100f8 100644 --- a/spec/services/projects/participants_service_spec.rb +++ b/spec/services/projects/participants_service_spec.rb @@ -4,7 +4,7 @@ describe Projects::ParticipantsService do describe '#groups' do describe 'avatar_url' do let(:project) { create(:project, :public) } - let(:group) { create(:group, avatar: fixture_file_upload(Rails.root + 'spec/fixtures/dk.png')) } + let(:group) { create(:group, avatar: fixture_file_upload('spec/fixtures/dk.png')) } let(:user) { create(:user) } let!(:group_member) { create(:group_member, group: group, user: user) } diff --git a/spec/services/projects/update_pages_service_spec.rb b/spec/services/projects/update_pages_service_spec.rb index 347ac13828c..1bffeee6790 100644 --- a/spec/services/projects/update_pages_service_spec.rb +++ b/spec/services/projects/update_pages_service_spec.rb @@ -4,13 +4,13 @@ describe Projects::UpdatePagesService do set(:project) { create(:project, :repository) } set(:pipeline) { create(:ci_pipeline, project: project, sha: project.commit('HEAD').sha) } set(:build) { create(:ci_build, pipeline: pipeline, ref: 'HEAD') } - let(:invalid_file) { fixture_file_upload(Rails.root + 'spec/fixtures/dk.png') } + let(:invalid_file) { fixture_file_upload('spec/fixtures/dk.png') } let(:extension) { 'zip' } - let(:file) { fixture_file_upload(Rails.root + "spec/fixtures/pages.#{extension}") } - let(:empty_file) { fixture_file_upload(Rails.root + "spec/fixtures/pages_empty.#{extension}") } + let(:file) { fixture_file_upload("spec/fixtures/pages.#{extension}") } + let(:empty_file) { fixture_file_upload("spec/fixtures/pages_empty.#{extension}") } let(:metadata) do - filename = Rails.root + "spec/fixtures/pages.#{extension}.meta" + filename = "spec/fixtures/pages.#{extension}.meta" fixture_file_upload(filename) if File.exist?(filename) end @@ -196,8 +196,8 @@ describe Projects::UpdatePagesService do let(:metadata) { spy('metadata') } before do - file = fixture_file_upload(Rails.root + 'spec/fixtures/pages.zip') - metafile = fixture_file_upload(Rails.root + 'spec/fixtures/pages.zip.meta') + file = fixture_file_upload('spec/fixtures/pages.zip') + metafile = fixture_file_upload('spec/fixtures/pages.zip.meta') build.update_attributes(legacy_artifacts_file: file) build.update_attributes(legacy_artifacts_metadata: metafile) diff --git a/spec/services/tags/create_service_spec.rb b/spec/services/tags/create_service_spec.rb index e7e9080b6b0..0cbe57352be 100644 --- a/spec/services/tags/create_service_spec.rb +++ b/spec/services/tags/create_service_spec.rb @@ -41,7 +41,7 @@ describe Tags::CreateService do it 'returns an error' do expect(repository).to receive(:add_tag) .with(user, 'v1.1.0', 'master', 'Foo') - .and_raise(Gitlab::Git::HooksService::PreReceiveError, 'something went wrong') + .and_raise(Gitlab::Git::PreReceiveError, 'something went wrong') response = service.execute('v1.1.0', 'master', 'Foo') diff --git a/spec/services/upload_service_spec.rb b/spec/services/upload_service_spec.rb index 24f3a5c5ff0..9b232a52efa 100644 --- a/spec/services/upload_service_spec.rb +++ b/spec/services/upload_service_spec.rb @@ -9,7 +9,7 @@ describe UploadService do context 'for valid gif file' do before do - gif = fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') + gif = fixture_file_upload('spec/fixtures/banana_sample.gif', 'image/gif') @link_to_file = upload_file(@project, gif) end @@ -21,7 +21,7 @@ describe UploadService do context 'for valid png file' do before do - png = fixture_file_upload(Rails.root + 'spec/fixtures/dk.png', + png = fixture_file_upload('spec/fixtures/dk.png', 'image/png') @link_to_file = upload_file(@project, png) end @@ -34,7 +34,7 @@ describe UploadService do context 'for valid jpg file' do before do - jpg = fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') + jpg = fixture_file_upload('spec/fixtures/rails_sample.jpg', 'image/jpg') @link_to_file = upload_file(@project, jpg) end @@ -46,7 +46,7 @@ describe UploadService do context 'for txt file' do before do - txt = fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') + txt = fixture_file_upload('spec/fixtures/doc_sample.txt', 'text/plain') @link_to_file = upload_file(@project, txt) end @@ -58,7 +58,7 @@ describe UploadService do context 'for too large a file' do before do - txt = fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') + txt = fixture_file_upload('spec/fixtures/doc_sample.txt', 'text/plain') allow(txt).to receive(:size) { 1000.megabytes.to_i } @link_to_file = upload_file(@project, txt) end diff --git a/spec/support/rspec.rb b/spec/support/rspec.rb index dffab22d8b5..54b8df7aa19 100644 --- a/spec/support/rspec.rb +++ b/spec/support/rspec.rb @@ -9,4 +9,6 @@ RSpec.configure do |config| config.include StubConfiguration config.include StubObjectStorage config.include StubENV + + config.fixture_path = Rails.root if defined?(Rails) end diff --git a/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb b/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb index ea7dbade171..bbbad86dcd5 100644 --- a/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb +++ b/spec/support/shared_examples/controllers/uploads_actions_shared_examples.rb @@ -1,7 +1,7 @@ shared_examples 'handle uploads' do let(:user) { create(:user) } - let(:jpg) { fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') } - let(:txt) { fixture_file_upload(Rails.root + 'spec/fixtures/doc_sample.txt', 'text/plain') } + let(:jpg) { fixture_file_upload('spec/fixtures/rails_sample.jpg', 'image/jpg') } + let(:txt) { fixture_file_upload('spec/fixtures/doc_sample.txt', 'text/plain') } let(:secret) { FileUploader.generate_secret } let(:uploader_class) { FileUploader } diff --git a/spec/uploaders/attachment_uploader_spec.rb b/spec/uploaders/attachment_uploader_spec.rb index d302c14efb9..a9415854d25 100644 --- a/spec/uploaders/attachment_uploader_spec.rb +++ b/spec/uploaders/attachment_uploader_spec.rb @@ -26,7 +26,7 @@ describe AttachmentUploader do describe "#migrate!" do before do - uploader.store!(fixture_file_upload(Rails.root.join('spec/fixtures/doc_sample.txt'))) + uploader.store!(fixture_file_upload(File.join('spec/fixtures/doc_sample.txt'))) stub_uploads_object_storage end diff --git a/spec/uploaders/favicon_uploader_spec.rb b/spec/uploaders/favicon_uploader_spec.rb index db8a3207f4d..37deea8ab90 100644 --- a/spec/uploaders/favicon_uploader_spec.rb +++ b/spec/uploaders/favicon_uploader_spec.rb @@ -10,7 +10,7 @@ RSpec.describe FaviconUploader do end def upload_fixture(filename) - fixture_file_upload(Rails.root.join('spec', 'fixtures', filename)) + fixture_file_upload("spec/fixtures/#{filename}") end context 'versions' do diff --git a/spec/uploaders/file_mover_spec.rb b/spec/uploaders/file_mover_spec.rb index 68b7e24776d..de29d0c943f 100644 --- a/spec/uploaders/file_mover_spec.rb +++ b/spec/uploaders/file_mover_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe FileMover do let(:filename) { 'banana_sample.gif' } - let(:file) { fixture_file_upload(Rails.root.join('spec', 'fixtures', filename)) } + let(:file) { fixture_file_upload(File.join('spec', 'fixtures', filename)) } let(:temp_file_path) { File.join('uploads/-/system/temp', 'secret55', filename) } let(:temp_description) do diff --git a/spec/uploaders/file_uploader_spec.rb b/spec/uploaders/file_uploader_spec.rb index db2810bbe1d..59013a02938 100644 --- a/spec/uploaders/file_uploader_spec.rb +++ b/spec/uploaders/file_uploader_spec.rb @@ -89,7 +89,7 @@ describe FileUploader do describe "#migrate!" do before do - uploader.store!(fixture_file_upload(Rails.root.join('spec/fixtures/dk.png'))) + uploader.store!(fixture_file_upload('spec/fixtures/dk.png')) stub_uploads_object_storage end diff --git a/spec/uploaders/gitlab_uploader_spec.rb b/spec/uploaders/gitlab_uploader_spec.rb index 4fba122cce1..362f89424d4 100644 --- a/spec/uploaders/gitlab_uploader_spec.rb +++ b/spec/uploaders/gitlab_uploader_spec.rb @@ -62,7 +62,7 @@ describe GitlabUploader do expect(FileUtils).to receive(:mv).with(anything, /^#{subject.work_dir}/).and_call_original expect(FileUtils).to receive(:mv).with(/^#{subject.work_dir}/, /#{subject.cache_dir}/).and_call_original - fixture = Rails.root.join('spec', 'fixtures', 'rails_sample.jpg') + fixture = File.join('spec', 'fixtures', 'rails_sample.jpg') subject.cache!(fixture_file_upload(fixture)) expect(subject.file.path).to match(/#{subject.cache_dir}/) diff --git a/spec/uploaders/job_artifact_uploader_spec.rb b/spec/uploaders/job_artifact_uploader_spec.rb index 42036d67f3d..026e4356ed6 100644 --- a/spec/uploaders/job_artifact_uploader_spec.rb +++ b/spec/uploaders/job_artifact_uploader_spec.rb @@ -29,8 +29,7 @@ describe JobArtifactUploader do context 'when trace is stored in File storage' do context 'when file exists' do let(:file) do - fixture_file_upload( - Rails.root.join('spec/fixtures/trace/sample_trace'), 'text/plain') + fixture_file_upload('spec/fixtures/trace/sample_trace', 'text/plain') end before do @@ -63,8 +62,7 @@ describe JobArtifactUploader do context 'file is stored in valid local_path' do let(:file) do - fixture_file_upload( - Rails.root.join('spec/fixtures/ci_build_artifacts.zip'), 'application/zip') + fixture_file_upload('spec/fixtures/ci_build_artifacts.zip', 'application/zip') end before do @@ -81,7 +79,7 @@ describe JobArtifactUploader do describe "#migrate!" do before do - uploader.store!(fixture_file_upload(Rails.root.join('spec/fixtures/trace/sample_trace'))) + uploader.store!(fixture_file_upload('spec/fixtures/trace/sample_trace')) stub_artifacts_object_storage end diff --git a/spec/uploaders/legacy_artifact_uploader_spec.rb b/spec/uploaders/legacy_artifact_uploader_spec.rb index eeb6fd90c9d..0589563b502 100644 --- a/spec/uploaders/legacy_artifact_uploader_spec.rb +++ b/spec/uploaders/legacy_artifact_uploader_spec.rb @@ -44,8 +44,7 @@ describe LegacyArtifactUploader do context 'file is stored in valid path' do let(:file) do - fixture_file_upload( - Rails.root.join('spec/fixtures/ci_build_artifacts.zip'), 'application/zip') + fixture_file_upload('spec/fixtures/ci_build_artifacts.zip', 'application/zip') end before do diff --git a/spec/uploaders/namespace_file_uploader_spec.rb b/spec/uploaders/namespace_file_uploader_spec.rb index a8ba01d70b8..71fe2c353c0 100644 --- a/spec/uploaders/namespace_file_uploader_spec.rb +++ b/spec/uploaders/namespace_file_uploader_spec.rb @@ -28,7 +28,7 @@ describe NamespaceFileUploader do describe "#migrate!" do before do - uploader.store!(fixture_file_upload(Rails.root.join('spec/fixtures/doc_sample.txt'))) + uploader.store!(fixture_file_upload(File.join('spec/fixtures/doc_sample.txt'))) stub_uploads_object_storage end diff --git a/spec/uploaders/object_storage_spec.rb b/spec/uploaders/object_storage_spec.rb index 4503288e410..0bc5b6751b3 100644 --- a/spec/uploaders/object_storage_spec.rb +++ b/spec/uploaders/object_storage_spec.rb @@ -571,7 +571,7 @@ describe ObjectStorage do context 'when local file is used' do context 'when valid file is used' do let(:uploaded_file) do - fixture_file_upload(Rails.root + 'spec/fixtures/rails_sample.jpg', 'image/jpg') + fixture_file_upload('spec/fixtures/rails_sample.jpg', 'image/jpg') end it "properly caches the file" do diff --git a/spec/uploaders/personal_file_uploader_spec.rb b/spec/uploaders/personal_file_uploader_spec.rb index c70521d90dc..7700b14ce6b 100644 --- a/spec/uploaders/personal_file_uploader_spec.rb +++ b/spec/uploaders/personal_file_uploader_spec.rb @@ -45,7 +45,7 @@ describe PersonalFileUploader do describe "#migrate!" do before do - uploader.store!(fixture_file_upload(Rails.root.join('spec/fixtures/doc_sample.txt'))) + uploader.store!(fixture_file_upload('spec/fixtures/doc_sample.txt')) stub_uploads_object_storage end diff --git a/spec/uploaders/records_uploads_spec.rb b/spec/uploaders/records_uploads_spec.rb index 9a3e5d83e01..3592a11360d 100644 --- a/spec/uploaders/records_uploads_spec.rb +++ b/spec/uploaders/records_uploads_spec.rb @@ -16,7 +16,7 @@ describe RecordsUploads do end def upload_fixture(filename) - fixture_file_upload(Rails.root.join('spec', 'fixtures', filename)) + fixture_file_upload(File.join('spec', 'fixtures', filename)) end describe 'callbacks' do diff --git a/spec/uploaders/uploader_helper_spec.rb b/spec/uploaders/uploader_helper_spec.rb index c47f09adb6d..33da93cc9d0 100644 --- a/spec/uploaders/uploader_helper_spec.rb +++ b/spec/uploaders/uploader_helper_spec.rb @@ -12,7 +12,7 @@ describe UploaderHelper do end def upload_fixture(filename) - fixture_file_upload(Rails.root.join('spec', 'fixtures', filename)) + fixture_file_upload(File.join('spec', 'fixtures', filename)) end describe '#image_or_video?' do diff --git a/spec/validators/url_validator_spec.rb b/spec/validators/url_validator_spec.rb index 2d719263fc8..93fe013d11c 100644 --- a/spec/validators/url_validator_spec.rb +++ b/spec/validators/url_validator_spec.rb @@ -50,13 +50,56 @@ describe UrlValidator do end end - context 'when ports is set' do - let(:validator) { described_class.new(attributes: [:link_url], ports: [443]) } + context 'when ports is' do + let(:validator) { described_class.new(attributes: [:link_url], ports: ports) } - it 'blocks urls with a different port' do - subject + context 'empty' do + let(:ports) { [] } - expect(badge.errors.empty?).to be false + it 'does not block any port' do + subject + + expect(badge.errors.empty?).to be true + end + end + + context 'set' do + let(:ports) { [443] } + + it 'blocks urls with a different port' do + subject + + expect(badge.errors.empty?).to be false + end + end + end + + context 'when enforce_user is' do + let(:url) { 'http://$user@example.com'} + let(:validator) { described_class.new(attributes: [:link_url], enforce_user: enforce_user) } + + context 'true' do + let(:enforce_user) { true } + + it 'checks user format' do + badge.link_url = url + + subject + + expect(badge.errors.empty?).to be false + end + end + + context 'false (default)' do + let(:enforce_user) { false } + + it 'does not check user format' do + badge.link_url = url + + subject + + expect(badge.errors.empty?).to be true + end end end end diff --git a/spec/workers/repository_fork_worker_spec.rb b/spec/workers/repository_fork_worker_spec.rb index 4b3c1736ea0..ae4786389c7 100644 --- a/spec/workers/repository_fork_worker_spec.rb +++ b/spec/workers/repository_fork_worker_spec.rb @@ -55,10 +55,15 @@ describe RepositoryForkWorker do it 'flushes various caches' do expect_fork_repository.and_return(true) - expect_any_instance_of(Repository).to receive(:expire_emptiness_caches) + # Works around https://github.com/rspec/rspec-mocks/issues/910 + expect(Project).to receive(:find).with(fork_project.id).and_return(fork_project) + expect(fork_project.repository).to receive(:expire_emptiness_caches) .and_call_original - - expect_any_instance_of(Repository).to receive(:expire_exists_cache) + expect(fork_project.repository).to receive(:expire_exists_cache) + .and_call_original + expect(fork_project.wiki.repository).to receive(:expire_emptiness_caches) + .and_call_original + expect(fork_project.wiki.repository).to receive(:expire_exists_cache) .and_call_original perform! diff --git a/spec/workers/repository_import_worker_spec.rb b/spec/workers/repository_import_worker_spec.rb index 84d1b38ef19..f0884ad0aff 100644 --- a/spec/workers/repository_import_worker_spec.rb +++ b/spec/workers/repository_import_worker_spec.rb @@ -22,8 +22,11 @@ describe RepositoryImportWorker do expect_any_instance_of(Projects::ImportService).to receive(:execute) .and_return({ status: :ok }) - expect_any_instance_of(Repository).to receive(:expire_emptiness_caches) - expect_any_instance_of(Project).to receive(:import_finish) + # Works around https://github.com/rspec/rspec-mocks/issues/910 + expect(Project).to receive(:find).with(project.id).and_return(project) + expect(project.repository).to receive(:expire_emptiness_caches) + expect(project.wiki.repository).to receive(:expire_emptiness_caches) + expect(project).to receive(:import_finish) subject.perform(project.id) end @@ -34,9 +37,11 @@ describe RepositoryImportWorker do expect_any_instance_of(Projects::ImportService).to receive(:execute) .and_return({ status: :ok }) - expect_any_instance_of(Project).to receive(:after_import).and_call_original - expect_any_instance_of(Repository).to receive(:expire_emptiness_caches) - expect_any_instance_of(Project).to receive(:import_finish) + # Works around https://github.com/rspec/rspec-mocks/issues/910 + expect(Project).to receive(:find).with(project.id).and_return(project) + expect(project.repository).to receive(:expire_emptiness_caches) + expect(project.wiki.repository).to receive(:expire_emptiness_caches) + expect(project).to receive(:import_finish) subject.perform(project.id) end |