diff options
115 files changed, 802 insertions, 443 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 44beccd966a..c971df3ba5f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,4 +1,4 @@ -image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-golang-1.11-git-2.21-chrome-73.0-node-10.x-yarn-1.12-postgresql-9.6-graphicsmagick-1.3.29" +image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.21-chrome-73.0-node-10.x-yarn-1.12-postgresql-9.6-graphicsmagick-1.3.29" variables: MYSQL_ALLOW_EMPTY_PASSWORD: "1" diff --git a/.gitlab/ci/cng.gitlab-ci.yml b/.gitlab/ci/cng.gitlab-ci.yml index c384bcdcdfc..d624e8d09f6 100644 --- a/.gitlab/ci/cng.gitlab-ci.yml +++ b/.gitlab/ci/cng.gitlab-ci.yml @@ -1,5 +1,5 @@ cloud-native-image: - image: ruby:2.5-alpine + image: ruby:2.6-alpine before_script: [] dependencies: [] stage: post-test diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml index fbf8925e30a..986ba7558d5 100644 --- a/.gitlab/ci/frontend.gitlab-ci.yml +++ b/.gitlab/ci/frontend.gitlab-ci.yml @@ -16,7 +16,7 @@ gitlab:assets:compile: <<: *assets-compile-cache extends: .dedicated-no-docs-pull-cache-job - image: dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-git-2.21-chrome-73.0-node-8.x-yarn-1.12-graphicsmagick-1.3.29-docker-18.06.1 + image: dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-git-2.21-chrome-73.0-node-8.x-yarn-1.12-graphicsmagick-1.3.29-docker-18.06.1 dependencies: - setup-test-env services: diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml index 466c47b37c7..cf87f5eb39c 100644 --- a/.gitlab/ci/global.gitlab-ci.yml +++ b/.gitlab/ci/global.gitlab-ci.yml @@ -9,7 +9,7 @@ - gitlab-org .default-cache: &default-cache - key: "debian-stretch-ruby-2.5.3-node-10.x" + key: "debian-stretch-ruby-2.6.3-node-10.x" paths: - vendor/ruby - .yarn-cache/ @@ -47,7 +47,7 @@ .single-script-job-dedicated-runner: extends: .dedicated-runner - image: ruby:2.5-alpine + image: ruby:2.6-alpine stage: test cache: {} dependencies: [] diff --git a/.gitlab/ci/qa.gitlab-ci.yml b/.gitlab/ci/qa.gitlab-ci.yml index 85c6409186e..122ed622ee2 100644 --- a/.gitlab/ci/qa.gitlab-ci.yml +++ b/.gitlab/ci/qa.gitlab-ci.yml @@ -1,5 +1,5 @@ package-and-qa: - image: ruby:2.5-alpine + image: ruby:2.6-alpine stage: qa when: manual before_script: [] diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml index 35c5f67427e..29534e40a14 100644 --- a/.gitlab/ci/rails.gitlab-ci.yml +++ b/.gitlab/ci/rails.gitlab-ci.yml @@ -86,7 +86,7 @@ .rspec-metadata-pg-10: &rspec-metadata-pg-10 <<: *rspec-metadata <<: *use-pg-10 - image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.5.3-golang-1.11-git-2.21-chrome-73.0-node-10.x-yarn-1.12-postgresql-10-graphicsmagick-1.3.29" + image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.6.3-golang-1.11-git-2.21-chrome-73.0-node-10.x-yarn-1.12-postgresql-10-graphicsmagick-1.3.29" .rspec-metadata-mysql: &rspec-metadata-mysql <<: *rspec-metadata @@ -108,7 +108,8 @@ - git fetch https://gitlab.com/gitlab-org/gitlab-ce.git v9.3.0 - git checkout -f FETCH_HEAD - sed -i "s/gem 'oj', '~> 2.17.4'//" Gemfile - - bundle update google-protobuf grpc + - sed -i "s/gem 'bootsnap', '~> 1.0.0'/gem 'bootsnap'/" Gemfile + - bundle update google-protobuf grpc bootsnap - bundle install $BUNDLE_INSTALL_FLAGS - date - cp config/gitlab.yml.example config/gitlab.yml @@ -183,7 +184,7 @@ static-analysis: script: - scripts/static-analysis cache: - key: "debian-stretch-ruby-2.5.3-node-10.x-and-rubocop" + key: "debian-stretch-ruby-2.6.3-node-10.x-and-rubocop" paths: - vendor/ruby - .yarn-cache/ diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml index ae16549ef6b..3a024c44fe2 100644 --- a/.gitlab/ci/review.gitlab-ci.yml +++ b/.gitlab/ci/review.gitlab-ci.yml @@ -54,7 +54,7 @@ build-qa-image: - time docker push ${QA_IMAGE} .review-build-cng-base: &review-build-cng-base - image: ruby:2.5-alpine + image: ruby:2.6-alpine stage: test when: manual before_script: diff --git a/.gitlab/ci/test-metadata.gitlab-ci.yml b/.gitlab/ci/test-metadata.gitlab-ci.yml index 3ba7af956b5..4b595083ec6 100644 --- a/.gitlab/ci/test-metadata.gitlab-ci.yml +++ b/.gitlab/ci/test-metadata.gitlab-ci.yml @@ -56,7 +56,7 @@ update-tests-metadata: flaky-examples-check: extends: .dedicated-runner - image: ruby:2.5-alpine + image: ruby:2.6-alpine services: [] before_script: [] variables: diff --git a/.ruby-version b/.ruby-version index aedc15bb0c6..ec1cf33c3f6 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.5.3 +2.6.3 diff --git a/Gemfile.lock b/Gemfile.lock index 3dd1adb5f63..2be35efe1da 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -272,7 +272,7 @@ GEM ruby-progressbar (~> 1.4) gemojione (3.3.0) json - get_process_mem (0.2.0) + get_process_mem (0.2.3) gettext (3.2.9) locale (>= 2.0.5) text (>= 1.3.0) diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js index b503c746801..213d5c6521a 100644 --- a/app/assets/javascripts/main.js +++ b/app/assets/javascripts/main.js @@ -147,7 +147,7 @@ function deferredInitialisation() { const canaryBadge = document.querySelector('.js-canary-badge'); const canaryLink = document.querySelector('.js-canary-link'); if (canaryBadge) { - canaryBadge.classList.remove('hidden'); + canaryBadge.classList.add('hidden'); } if (canaryLink) { canaryLink.classList.add('hidden'); diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb index d3746248bd3..1d16ddb1608 100644 --- a/app/controllers/profiles_controller.rb +++ b/app/controllers/profiles_controller.rb @@ -15,7 +15,7 @@ class ProfilesController < Profiles::ApplicationController result = Users::UpdateService.new(current_user, user_params.merge(user: @user)).execute if result[:status] == :success - message = "Profile was successfully updated" + message = s_("Profiles|Profile was successfully updated") format.html { redirect_back_or_default(default: { action: 'show' }, options: { notice: message }) } format.json { render json: { message: message } } @@ -31,7 +31,7 @@ class ProfilesController < Profiles::ApplicationController user.reset_incoming_email_token! end - flash[:notice] = "Incoming email token was successfully reset" + flash[:notice] = s_("Profiles|Incoming email token was successfully reset") redirect_to profile_personal_access_tokens_path end @@ -41,7 +41,7 @@ class ProfilesController < Profiles::ApplicationController user.reset_feed_token! end - flash[:notice] = 'Feed token was successfully reset' + flash[:notice] = s_('Profiles|Feed token was successfully reset') redirect_to profile_personal_access_tokens_path end diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb index ebf28dc842c..7b4832b84a8 100644 --- a/app/models/project_services/jira_service.rb +++ b/app/models/project_services/jira_service.rb @@ -265,6 +265,7 @@ class JiraService < IssueTrackerService def find_remote_link(issue, url) links = jira_request { issue.remotelink.all } + return unless links links.find { |link| link.object["url"] == url } end diff --git a/app/models/repository.rb b/app/models/repository.rb index be17b54ff12..1c02e68f2f6 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -465,7 +465,7 @@ class Repository def after_import expire_content_cache - DetectRepositoryLanguagesWorker.perform_async(project.id, project.owner.id) + DetectRepositoryLanguagesWorker.perform_async(project.id) end # Runs code after a new commit has been pushed. diff --git a/app/policies/project_policy.rb b/app/policies/project_policy.rb index 76544249688..3218c04b219 100644 --- a/app/policies/project_policy.rb +++ b/app/policies/project_policy.rb @@ -488,6 +488,10 @@ class ProjectPolicy < BasePolicy def team_access_level return -1 if @user.nil? + lookup_access_level! + end + + def lookup_access_level! # NOTE: max_member_access has its own cache project.team.max_member_access(@user.id) end diff --git a/app/services/git/branch_push_service.rb b/app/services/git/branch_push_service.rb index da053ce80c7..abf11f253f6 100644 --- a/app/services/git/branch_push_service.rb +++ b/app/services/git/branch_push_service.rb @@ -48,7 +48,7 @@ module Git def enqueue_detect_repository_languages return unless default_branch? - DetectRepositoryLanguagesWorker.perform_async(project.id, current_user.id) + DetectRepositoryLanguagesWorker.perform_async(project.id) end # Only stop environments if the ref is a branch that is being deleted diff --git a/app/services/members/create_service.rb b/app/services/members/create_service.rb index f6bad74736c..d6b17ec10be 100644 --- a/app/services/members/create_service.rb +++ b/app/services/members/create_service.rb @@ -23,7 +23,16 @@ module Members members.each do |member| if member.errors.any? - errors << "#{member.user.username}: #{member.errors.full_messages.to_sentence}" + current_error = + # Invited users may not have an associated user + if member.user.present? + "#{member.user.username}: " + else + "" + end + + current_error += member.errors.full_messages.to_sentence + errors << current_error else after_execute(member: member) end diff --git a/app/services/projects/after_import_service.rb b/app/services/projects/after_import_service.rb index afb9048e87b..bbdde4408d2 100644 --- a/app/services/projects/after_import_service.rb +++ b/app/services/projects/after_import_service.rb @@ -9,7 +9,7 @@ module Projects end def execute - Projects::HousekeepingService.new(@project, :gc).execute do + Projects::HousekeepingService.new(@project).execute do repository.delete_all_refs_except(RESERVED_REF_PREFIXES) end rescue Projects::HousekeepingService::LeaseTaken => e diff --git a/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb b/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb index 05974948505..9b72480d18b 100644 --- a/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb +++ b/app/services/projects/lfs_pointers/lfs_download_link_list_service.rb @@ -37,7 +37,17 @@ module Projects raise DownloadLinksError, response.message unless response.success? - parse_response_links(response['objects']) + # Since the LFS Batch API may return a Content-Ttpe of + # application/vnd.git-lfs+json + # (https://github.com/git-lfs/git-lfs/blob/master/docs/api/batch.md#requests), + # HTTParty does not know this is actually JSON. + data = JSON.parse(response.body) + + raise DownloadLinksError, "LFS Batch API did return any objects" unless data.is_a?(Hash) && data.key?('objects') + + parse_response_links(data['objects']) + rescue JSON::ParserError + raise DownloadLinksError, "LFS Batch API response is not JSON" end def parse_response_links(objects_response) diff --git a/app/services/projects/repository_languages_service.rb b/app/services/projects/repository_languages_service.rb index e75851c7da4..05f43c2264b 100644 --- a/app/services/projects/repository_languages_service.rb +++ b/app/services/projects/repository_languages_service.rb @@ -11,7 +11,7 @@ module Projects def perform_language_detection if persisted_repository_languages.blank? - ::DetectRepositoryLanguagesWorker.perform_async(project.id, current_user.id) + ::DetectRepositoryLanguagesWorker.perform_async(project.id) else project.update_column(:detected_repository_languages, true) end diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml index bc34af88928..f016a157daf 100644 --- a/app/views/admin/projects/show.html.haml +++ b/app/views/admin/projects/show.html.haml @@ -100,6 +100,8 @@ %span.light archived: %strong project is read-only + = render_if_exists "shared_runner_status", project: @project + %li %span.light access: %strong diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml index 09cc713e3af..021c0b6c429 100644 --- a/app/views/groups/group_members/index.html.haml +++ b/app/views/groups/group_members/index.html.haml @@ -14,6 +14,8 @@ = render 'shared/members/requests', membership_source: @group, requesters: @requesters + = render_if_exists 'groups/group_members/ldap_sync' + .clearfix %h5.member.existing-title Existing members diff --git a/app/views/layouts/_piwik.html.haml b/app/views/layouts/_piwik.html.haml index a888e8ae187..473b14ce626 100644 --- a/app/views/layouts/_piwik.html.haml +++ b/app/views/layouts/_piwik.html.haml @@ -7,7 +7,7 @@ (function() { var u="//#{extra_config.piwik_url}/"; _paq.push(['setTrackerUrl', u+'piwik.php']); - _paq.push(['setSiteId', #{extra_config.piwik_site_id}]); + _paq.push(['setSiteId', "#{extra_config.piwik_site_id}"]); var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s); })(); diff --git a/app/views/layouts/nav/sidebar/_profile.html.haml b/app/views/layouts/nav/sidebar/_profile.html.haml index 1e3bb8f1224..2061eac917f 100644 --- a/app/views/layouts/nav/sidebar/_profile.html.haml +++ b/app/views/layouts/nav/sidebar/_profile.html.haml @@ -4,7 +4,7 @@ = link_to profile_path, title: _('Profile Settings') do .avatar-container.s40.settings-avatar = image_tag avatar_icon_for_user(current_user, 40), class: "avatar s40 avatar-tile", alt: current_user.name - .sidebar-context-title User Settings + .sidebar-context-title= _('User Settings') %ul.sidebar-top-level-items = nav_link(path: 'profiles#show', html_options: {class: 'home'}) do = link_to profile_path do diff --git a/app/views/profiles/show.html.haml b/app/views/profiles/show.html.haml index 45b6453b5ff..917e7acc353 100644 --- a/app/views/profiles/show.html.haml +++ b/app/views/profiles/show.html.haml @@ -92,8 +92,8 @@ = f.text_field :name, required: true, readonly: true, wrapper: { class: 'col-md-9 qa-full-name' }, help: s_("Profiles|Your name was automatically set based on your %{provider_label} account, so people you know can recognize you") % { provider_label: attribute_provider_label(:name) } - else - = f.text_field :name, label: 'Full name', required: true, title: s_("Profiles|Using emojis in names seems fun, but please try to set a status message instead"), wrapper: { class: 'col-md-9 qa-full-name' }, help: s_("Profiles|Enter your name, so people you know can recognize you") - = f.text_field :id, readonly: true, label: 'User ID', wrapper: { class: 'col-md-3' } + = f.text_field :name, label: s_('Profiles|Full name'), required: true, title: s_("Profiles|Using emojis in names seems fun, but please try to set a status message instead"), wrapper: { class: 'col-md-9 qa-full-name' }, help: s_("Profiles|Enter your name, so people you know can recognize you") + = f.text_field :id, readonly: true, label: s_('Profiles|User ID'), wrapper: { class: 'col-md-3' } = render_if_exists 'profiles/email_settings', form: f = f.text_field :skype, class: 'input-md', placeholder: s_("Profiles|username") @@ -103,18 +103,18 @@ - if @user.read_only_attribute?(:location) = f.text_field :location, readonly: true, help: s_("Profiles|Your location was automatically set based on your %{provider_label} account") % { provider_label: attribute_provider_label(:location) } - else - = f.text_field :location, class: 'input-lg', placeholder: s_("Profiles|City, country") - = f.text_field :organization, class: 'input-md', help: s_("Profiles|Who you represent or work for") - = f.text_area :bio, rows: 4, maxlength: 250, help: s_("Profiles|Tell us about yourself in fewer than 250 characters") + = f.text_field :location, label: s_('Profiles|Location'), class: 'input-lg', placeholder: s_("Profiles|City, country") + = f.text_field :organization, label: s_('Profiles|Organization'), class: 'input-md', help: s_("Profiles|Who you represent or work for") + = f.text_area :bio, label: s_('Profiles|Bio'), rows: 4, maxlength: 250, help: s_("Profiles|Tell us about yourself in fewer than 250 characters") %hr - %h5= ("Private profile") + %h5= s_("Private profile") .checkbox-icon-inline-wrapper - private_profile_label = capture do = s_("Profiles|Don't display activity-related personal information on your profiles") = f.check_box :private_profile, label: private_profile_label, inline: true, wrapper_class: 'mr-0' = link_to icon('question-circle'), help_page_path('user/profile/index.md', anchor: 'private-profile') %h5= s_("Profiles|Private contributions") - = f.check_box :include_private_contributions, label: 'Include private contributions on my profile', wrapper_class: 'mb-2', inline: true + = f.check_box :include_private_contributions, label: s_('Profiles|Include private contributions on my profile'), wrapper_class: 'mb-2', inline: true .help-block = s_("Profiles|Choose to show contributions of private projects on your public profile without any project, repository or organization information") .prepend-top-default.append-bottom-default diff --git a/app/views/projects/branches/_branch.html.haml b/app/views/projects/branches/_branch.html.haml index 91c51d5e091..0e15f581ddc 100644 --- a/app/views/projects/branches/_branch.html.haml +++ b/app/views/projects/branches/_branch.html.haml @@ -10,7 +10,7 @@ .branch-info .branch-title = sprite_icon('fork', size: 12) - = link_to project_tree_path(@project, branch.name), class: 'item-title str-truncated-100 ref-name prepend-left-8' do + = link_to project_tree_path(@project, branch.name), class: 'item-title str-truncated-100 ref-name prepend-left-8 qa-branch-name' do = branch.name - if branch.name == @repository.root_ref %span.badge.badge-primary.prepend-left-5 default diff --git a/app/views/shared/issuable/form/_contribution.html.haml b/app/views/shared/issuable/form/_contribution.html.haml index bc9a1edc39c..a78231b37ce 100644 --- a/app/views/shared/issuable/form/_contribution.html.haml +++ b/app/views/shared/issuable/form/_contribution.html.haml @@ -15,6 +15,6 @@ = form.check_box :allow_collaboration, disabled: !issuable.can_allow_collaboration?(current_user), class: 'form-check-input' = form.label :allow_collaboration, class: 'form-check-label' do = _('Allow commits from members who can merge to the target branch.') - = link_to 'About this feature', help_page_path('user/project/merge_requests/allow_collaboration') + = link_to 'About this feature', help_page_path('user/project/merge_requests/allow_collaboration'), target: '_blank', rel: 'noopener noreferrer nofollow' .form-text.text-muted = allow_collaboration_unavailable_reason(issuable) diff --git a/app/workers/detect_repository_languages_worker.rb b/app/workers/detect_repository_languages_worker.rb index 64bc9776d48..838c3be78f0 100644 --- a/app/workers/detect_repository_languages_worker.rb +++ b/app/workers/detect_repository_languages_worker.rb @@ -12,13 +12,12 @@ class DetectRepositoryLanguagesWorker attr_reader :project # rubocop: disable CodeReuse/ActiveRecord - def perform(project_id, user_id) + def perform(project_id, user_id = nil) @project = Project.find_by(id: project_id) - user = User.find_by(id: user_id) - return unless project && user + return unless project try_obtain_lease do - ::Projects::DetectRepositoryLanguagesService.new(project, user).execute + ::Projects::DetectRepositoryLanguagesService.new(project).execute end end # rubocop: enable CodeReuse/ActiveRecord diff --git a/changelogs/unreleased/27987-use-findorcreateservice-to-create-labels.yml b/changelogs/unreleased/27987-use-findorcreateservice-to-create-labels.yml new file mode 100644 index 00000000000..8d3501e0171 --- /dev/null +++ b/changelogs/unreleased/27987-use-findorcreateservice-to-create-labels.yml @@ -0,0 +1,5 @@ +--- +title: Use FindOrCreateService to create labels and check for existing ones +merge_request: 27987 +author: Matt Duren +type: fixed diff --git a/changelogs/unreleased/60180-jira-service-fix-nil-on-find-call.yml b/changelogs/unreleased/60180-jira-service-fix-nil-on-find-call.yml new file mode 100644 index 00000000000..6891a9ca83c --- /dev/null +++ b/changelogs/unreleased/60180-jira-service-fix-nil-on-find-call.yml @@ -0,0 +1,5 @@ +--- +title: 'Resolved JIRA service: NoMethodError: undefined method ''find'' for nil:NilClass' +merge_request: 28206 +author: +type: fixed diff --git a/changelogs/unreleased/60425-fix-500-when-accessing-charts-with-anonymous-user.yml b/changelogs/unreleased/60425-fix-500-when-accessing-charts-with-anonymous-user.yml new file mode 100644 index 00000000000..4274dc5918c --- /dev/null +++ b/changelogs/unreleased/60425-fix-500-when-accessing-charts-with-anonymous-user.yml @@ -0,0 +1,5 @@ +--- +title: "Fix 500 error when accessing charts with an anonymous user" +merge_request: 28091 +author: Diego Silva +type: fixed diff --git a/changelogs/unreleased/61550-next-badge.yml b/changelogs/unreleased/61550-next-badge.yml new file mode 100644 index 00000000000..122e394a68c --- /dev/null +++ b/changelogs/unreleased/61550-next-badge.yml @@ -0,0 +1,5 @@ +--- +title: Fixes next badge being always visible +merge_request: +author: +type: fixed diff --git a/changelogs/unreleased/61606-support-string-piwik-website-ids.yml b/changelogs/unreleased/61606-support-string-piwik-website-ids.yml new file mode 100644 index 00000000000..5c525294132 --- /dev/null +++ b/changelogs/unreleased/61606-support-string-piwik-website-ids.yml @@ -0,0 +1,5 @@ +--- +title: "Supports Matomo/Piwik string website ID (\"Protect Track ID\" plugin)" +merge_request: 28214 +author: DUVERGIER Claude +type: fixed
\ No newline at end of file diff --git a/changelogs/unreleased/add-warning-to-backup-rake-task.yml b/changelogs/unreleased/add-warning-to-backup-rake-task.yml new file mode 100644 index 00000000000..7ddeae3f9fd --- /dev/null +++ b/changelogs/unreleased/add-warning-to-backup-rake-task.yml @@ -0,0 +1,5 @@ +--- +title: Add warning that gitlab-secrets isn't included in backup +merge_request: +author: +type: other diff --git a/changelogs/unreleased/antonyliu-i18n-user-profile.yml b/changelogs/unreleased/antonyliu-i18n-user-profile.yml new file mode 100644 index 00000000000..f9065ee5697 --- /dev/null +++ b/changelogs/unreleased/antonyliu-i18n-user-profile.yml @@ -0,0 +1,5 @@ +--- +title: 'i18n: externalize strings from user profile settings' +merge_request: 28088 +author: Antony Liu +type: other diff --git a/changelogs/unreleased/include-ee-fixtures.yml b/changelogs/unreleased/include-ee-fixtures.yml new file mode 100644 index 00000000000..ba500d92de3 --- /dev/null +++ b/changelogs/unreleased/include-ee-fixtures.yml @@ -0,0 +1,5 @@ +--- +title: Add EE fixtures to SeedFu list +merge_request: 28241 +author: +type: other diff --git a/changelogs/unreleased/sh-fix-invited-members.yml b/changelogs/unreleased/sh-fix-invited-members.yml new file mode 100644 index 00000000000..96e43e1aa53 --- /dev/null +++ b/changelogs/unreleased/sh-fix-invited-members.yml @@ -0,0 +1,5 @@ +--- +title: Fix Error 500 when inviting user already present +merge_request: 28198 +author: +type: fixed diff --git a/changelogs/unreleased/sh-fix-lfs-download-errors.yml b/changelogs/unreleased/sh-fix-lfs-download-errors.yml new file mode 100644 index 00000000000..ad67df6bb06 --- /dev/null +++ b/changelogs/unreleased/sh-fix-lfs-download-errors.yml @@ -0,0 +1,5 @@ +--- +title: Properly handle LFS Batch API response in project import +merge_request: 28223 +author: +type: fixed diff --git a/changelogs/unreleased/sh-update-process-mem.yml b/changelogs/unreleased/sh-update-process-mem.yml new file mode 100644 index 00000000000..51b22fb0f00 --- /dev/null +++ b/changelogs/unreleased/sh-update-process-mem.yml @@ -0,0 +1,5 @@ +--- +title: Update get_process_mem to 0.2.3 +merge_request: 28248 +author: +type: other diff --git a/changelogs/unreleased/sh-upgrade-ruby-2-6-3-ce.yml b/changelogs/unreleased/sh-upgrade-ruby-2-6-3-ce.yml new file mode 100644 index 00000000000..9ad5c9ebb64 --- /dev/null +++ b/changelogs/unreleased/sh-upgrade-ruby-2-6-3-ce.yml @@ -0,0 +1,5 @@ +--- +title: Upgrade Ruby version to 2.6.3 +merge_request: 28117 +author: +type: performance diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example index bff809b7661..23377b43f78 100644 --- a/config/gitlab.yml.example +++ b/config/gitlab.yml.example @@ -245,7 +245,7 @@ production: &base host: example.com port: 80 # Set to 443 if you serve the pages with HTTPS https: false # Set to true if you serve the pages with HTTPS - artifacts_server: true + artifacts_server: true # Set to false if you want to disable online view of HTML artifacts # external_http: ["1.1.1.1:80", "[2001::1]:80"] # If defined, enables custom domain support in GitLab Pages # external_https: ["1.1.1.1:443", "[2001::1]:443"] # If defined, enables custom domain and certificate support in GitLab Pages admin: diff --git a/config/initializers/01_secret_token.rb b/config/initializers/01_secret_token.rb index 02bded43083..e24b5cbd510 100644 --- a/config/initializers/01_secret_token.rb +++ b/config/initializers/01_secret_token.rb @@ -1,3 +1,14 @@ +# WARNING: If you add a new secret to this file, make sure you also +# update Omnibus GitLab or updates will fail. Omnibus is responsible for +# writing the `secrets.yml` file. If Omnibus doesn't know about a +# secret, Rails will attempt to write to the file, but this will fail +# because Rails doesn't have write access. +# +# As an example: +# * https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/27581 +# * https://gitlab.com/gitlab-org/omnibus-gitlab/merge_requests/3267 +# +# # This file needs to be loaded BEFORE any initializers that attempt to # prepend modules that require access to secrets (e.g. EE's 0_as_concern.rb). # @@ -28,7 +39,8 @@ def create_tokens secret_key_base: file_secret_key || generate_new_secure_token, otp_key_base: env_secret_key || file_secret_key || generate_new_secure_token, db_key_base: generate_new_secure_token, - openid_connect_signing_key: generate_new_rsa_private_key + openid_connect_signing_key: generate_new_rsa_private_key, + lets_encrypt_private_key: generate_lets_encrypt_private_key } missing_secrets = set_missing_keys(defaults) @@ -49,6 +61,10 @@ def generate_new_rsa_private_key OpenSSL::PKey::RSA.new(2048).to_pem end +def generate_lets_encrypt_private_key + OpenSSL::PKey::RSA.new(4096).to_pem +end + def warn_missing_secret(secret) warn "Missing Rails.application.secrets.#{secret} for #{Rails.env} environment. The secret will be generated and stored in config/secrets.yml." end diff --git a/config/initializers/seed_fu.rb b/config/initializers/seed_fu.rb new file mode 100644 index 00000000000..2e48e41a311 --- /dev/null +++ b/config/initializers/seed_fu.rb @@ -0,0 +1,4 @@ +# frozen_string_literal: true +if Gitlab.ee? + SeedFu.fixture_paths += %W[ee/db/fixtures ee/db/fixtures/#{Rails.env}] +end diff --git a/db/migrate/20190412155659_add_merge_request_blocks.rb b/db/migrate/20190412155659_add_merge_request_blocks.rb new file mode 100644 index 00000000000..9e7f370d1cf --- /dev/null +++ b/db/migrate/20190412155659_add_merge_request_blocks.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +class AddMergeRequestBlocks < ActiveRecord::Migration[5.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + def change + create_table :merge_request_blocks, id: :bigserial do |t| + t.references :blocking_merge_request, + index: false, null: false, + foreign_key: { to_table: :merge_requests, on_delete: :cascade } + + t.references :blocked_merge_request, + index: true, null: false, + foreign_key: { to_table: :merge_requests, on_delete: :cascade } + + t.index [:blocking_merge_request_id, :blocked_merge_request_id], + unique: true, + name: 'index_mr_blocks_on_blocking_and_blocked_mr_ids' + + t.timestamps_with_timezone + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 1be3afd5282..159e7e03cf4 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -1227,6 +1227,15 @@ ActiveRecord::Schema.define(version: 20190506135400) do t.index ["user_id"], name: "index_merge_request_assignees_on_user_id", using: :btree end + create_table "merge_request_blocks", force: :cascade do |t| + t.integer "blocking_merge_request_id", null: false + t.integer "blocked_merge_request_id", null: false + t.datetime_with_timezone "created_at", null: false + t.datetime_with_timezone "updated_at", null: false + t.index ["blocked_merge_request_id"], name: "index_merge_request_blocks_on_blocked_merge_request_id", using: :btree + t.index ["blocking_merge_request_id", "blocked_merge_request_id"], name: "index_mr_blocks_on_blocking_and_blocked_mr_ids", unique: true, using: :btree + end + create_table "merge_request_diff_commits", id: false, force: :cascade do |t| t.datetime_with_timezone "authored_date" t.datetime_with_timezone "committed_date" @@ -2514,6 +2523,8 @@ ActiveRecord::Schema.define(version: 20190506135400) do add_foreign_key "members", "users", name: "fk_2e88fb7ce9", on_delete: :cascade add_foreign_key "merge_request_assignees", "merge_requests", on_delete: :cascade add_foreign_key "merge_request_assignees", "users", on_delete: :cascade + add_foreign_key "merge_request_blocks", "merge_requests", column: "blocked_merge_request_id", on_delete: :cascade + add_foreign_key "merge_request_blocks", "merge_requests", column: "blocking_merge_request_id", on_delete: :cascade add_foreign_key "merge_request_diff_commits", "merge_request_diffs", on_delete: :cascade add_foreign_key "merge_request_diff_files", "merge_request_diffs", on_delete: :cascade add_foreign_key "merge_request_diffs", "merge_requests", name: "fk_8483f3258f", on_delete: :cascade diff --git a/doc/administration/integration/plantuml.md b/doc/administration/integration/plantuml.md index d383d1efe70..b7b820abb40 100644 --- a/doc/administration/integration/plantuml.md +++ b/doc/administration/integration/plantuml.md @@ -57,8 +57,7 @@ you can change these defaults by editing the `/etc/tomcat7/server.xml` file. You need to enable PlantUML integration from Settings under Admin Area. To do that, login with an Admin account and do following: - - in GitLab go to **Admin Area** and then **Settings** - - scroll to bottom of the page until PlantUML section + - in GitLab go to **Admin Area**->**Settings**->**Integrations**->**PlantUML** - check **Enable PlantUML** checkbox - set the PlantUML instance as **PlantUML URL** diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md index e079483e2b5..3f72fe3e9eb 100644 --- a/doc/ci/caching/index.md +++ b/doc/ci/caching/index.md @@ -289,7 +289,7 @@ jobs inherit it. Gems are installed in `vendor/ruby/` and are cached per-branch: # # https://gitlab.com/gitlab-org/gitlab-ce/tree/master/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml # -image: ruby:2.5 +image: ruby:2.6 # Cache gems in between builds cache: diff --git a/doc/development/architecture.md b/doc/development/architecture.md index 8d1879e2944..1e59b59b312 100644 --- a/doc/development/architecture.md +++ b/doc/development/architecture.md @@ -213,105 +213,73 @@ To serve repositories over SSH there's an add-on application called gitlab-shell ```mermaid graph TB - HTTP[HTTP/HTTPS] -- TCP 80, 443 --> NGINX(NGINX) - SSH --TCP 22 --> GitLabShell(GitLab Shell) - SMTP(SMTP Gateway) - Geo(GitLab Geo Node) -- TCP 22, 80, 443 --> NGINX - - subgraph GitLab - GitLabShell --TCP 8080 -->Unicorn["Unicorn (GitLab Rails)"] - GitLabShell --> Gitaly - GitLabShell --> Redis - Unicorn --> PgBouncer(PgBouncer) - Unicorn --> Redis - Unicorn --> Gitaly - Redis --> Sidekiq - Sidekiq("Sidekiq (GitLab Rails, ES Indexer)") --> PgBouncer - GitLabWorkhorse(GitLab Workhorse) --> Unicorn - GitLabWorkhorse --> Redis - GitLabWorkhorse --> Gitaly - Gitaly --> Redis - NGINX --> GitLabWorkhorse - NGINX -- TCP 8090 --> GitLabPages(GitLab Pages) - NGINX --> Grafana(Grafana) - Grafana -- TCP 9090 --> Prometheus(Prometheus) - Prometheus -- TCP 80, 443 --> Unicorn - RedisExporter(Redis Exporter) --> Redis - Prometheus -- TCP 9121 --> RedisExporter - PostgreSQLExporter(PostgreSQL Exporter) --> PostgreSQL - PgBouncerExporter(PgBouncer Exporter) --> PgBouncer - Prometheus -- TCP 9187 --> PostgreSQLExporter - Prometheus -- TCP 9100 --> NodeExporter(Node Exporter) - Prometheus -- TCP 9168 --> GitLabMonitor(GitLab Monitor) - Prometheus -- TCP 9127 --> PgBouncerExporter - GitLabMonitor --> PostgreSQL - GitLabMonitor --> GitLabShell - GitLabMonitor --> Sidekiq - PgBouncer --> Consul(Consul) - PostgreSQL --> Consul - PgBouncer --> PostgreSQL - NGINX --> Registry(Registry) - Unicorn --> Registry - NGINX --> Mattermost(Mattermost) - Mattermost --- Unicorn - Prometheus --> Alertmanager - Migrations --> PostgreSQL - Runner(Runner) --> NGINX - Unicorn -- TCP 9200 --> ElasticSearch - Sidekiq -- TCP 9200 --> ElasticSearch - Sidekiq -- TCP 80, 443 --> Sentry - Unicorn -- TCP 80, 443 --> Sentry - Sidekiq -- UDP 6831 --> Jaeger - Unicorn -- UDP 6831 --> Jaeger - Gitaly -- UDP 6831 --> Jaeger - GitLabShell -- UDP 6831 --> Jaeger - GitLabWorkhorse -- UDP 6831 --> Jaeger - Alertmanager -- TCP 25 --> SMTP - Sidekiq -- TCP 25 --> SMTP - Unicorn -- TCP 25 --> SMTP - Unicorn -- TCP 369 --> LDAP - Sidekiq -- TCP 369 --> LDAP - Unicorn -- TCP 443 --> ObjectStorage("Object Storage") - Sidekiq -- TCP 443 --> ObjectStorage - GitLabWorkhorse -- TCP 443 --> ObjectStorage - Registry -- TCP 443 --> ObjectStorage - Geo -- TCP 5432 --> PostgreSQL - end - - HTTPK8s(HTTP/HTTPS) -- TCP 80, 443 --> LoadBalancerK8s(Load Balancer) - LoadBalancerK8s -- TCP 80, 443 --> nginx-ingressK8s - subgraph Kubernetes - PrometheusK8s(Prometheus) - TillerK8s(Tiller) - nginx-ingressK8s(NGINX Ingress) - Cert-ManagerK8s(Cert-Manager) - GitLabRunnerK8s(GitLab Runner) - GitLabRunnerK8s --> NGINX - JupyterHubK8s(JupyterHub) - nginx-ingressK8s --> JupyterHubK8s - KnativeK8s(Knative) - end - -classDef defaultoff stroke-dasharray: 5, 5 -class ElasticSearch defaultoff -class Grafana defaultoff -class PrometheusK8s defaultoff -class TillerK8s defaultoff -class nginx-ingressK8s defaultoff -class Cert-ManagerK8s defaultoff -class GitLabRunnerK8s defaultoff -class JupyterHubK8s defaultoff -class KnativeK8s defaultoff -class HTTPK8s defaultoff -class LoadBalancerK8s defaultoff -class Sentry defaultoff -class Jaeger defaultoff -class Alertmanager defaultoff -class SMTP defaultoff -class ObjectStorage defaultoff -class Geo defaultoff + HTTP[HTTP/HTTPS] -- TCP 80, 443 --> NGINX[NGINX] + SSH -- TCP 22 --> GitLabShell[GitLab Shell] + SMTP[SMTP Gateway] + Geo[GitLab Geo Node] -- TCP 22, 80, 443 --> NGINX + + GitLabShell --TCP 8080 -->Unicorn["Unicorn (GitLab Rails)"] + GitLabShell --> Gitaly + GitLabShell --> Redis + Unicorn --> PgBouncer[PgBouncer] + Unicorn --> Redis + Unicorn --> Gitaly + Redis --> Sidekiq + Sidekiq["Sidekiq (GitLab Rails, ES Indexer)"] --> PgBouncer + GitLabWorkhorse[GitLab Workhorse] --> Unicorn + GitLabWorkhorse --> Redis + GitLabWorkhorse --> Gitaly + Gitaly --> Redis + NGINX --> GitLabWorkhorse + NGINX -- TCP 8090 --> GitLabPages[GitLab Pages] + NGINX --> Grafana[Grafana] + Grafana -- TCP 9090 --> Prometheus[Prometheus] + Prometheus -- TCP 80, 443 --> Unicorn + RedisExporter[Redis Exporter] --> Redis + Prometheus -- TCP 9121 --> RedisExporter + PostgreSQLExporter[PostgreSQL Exporter] --> PostgreSQL + PgBouncerExporter[PgBouncer Exporter] --> PgBouncer + Prometheus -- TCP 9187 --> PostgreSQLExporter + Prometheus -- TCP 9100 --> NodeExporter[Node Exporter] + Prometheus -- TCP 9168 --> GitLabMonito[GitLab Monitor] + Prometheus -- TCP 9127 --> PgBouncerExporter + GitLabMonitor --> PostgreSQL + GitLabMonitor --> GitLabShell + GitLabMonitor --> Sidekiq + PgBouncer --> Consul + PostgreSQL --> Consul + PgBouncer --> PostgreSQL + NGINX --> Registry + Unicorn --> Registry + NGINX --> Mattermost + Mattermost --- Unicorn + Prometheus --> Alertmanager + Migrations --> PostgreSQL + Runner -- TCP 443 --> NGINX + Unicorn -- TCP 9200 --> ElasticSearch + Sidekiq -- TCP 9200 --> ElasticSearch + Sidekiq -- TCP 80, 443 --> Sentry + Unicorn -- TCP 80, 443 --> Sentry + Sidekiq -- UDP 6831 --> Jaeger + Unicorn -- UDP 6831 --> Jaeger + Gitaly -- UDP 6831 --> Jaeger + GitLabShell -- UDP 6831 --> Jaeger + GitLabWorkhorse -- UDP 6831 --> Jaeger + Alertmanager -- TCP 25 --> SMTP + Sidekiq -- TCP 25 --> SMTP + Unicorn -- TCP 25 --> SMTP + Unicorn -- TCP 369 --> LDAP + Sidekiq -- TCP 369 --> LDAP + Unicorn -- TCP 443 --> ObjectStorage["Object Storage"] + Sidekiq -- TCP 443 --> ObjectStorage + GitLabWorkhorse -- TCP 443 --> ObjectStorage + Registry -- TCP 443 --> ObjectStorage + Geo -- TCP 5432 --> PostgreSQL + ``` +--- + **Legend**: * ✅ - Automatically configured @@ -321,7 +289,7 @@ class Geo defaultoff | Component | Description | [Omnibus GitLab](https://docs.gitlab.com/omnibus/README.html) | [GitLab chart](https://docs.gitlab.com/charts/) | [Minikube Minimal](https://docs.gitlab.com/charts/development/minikube/#deploying-gitlab-with-minimal-settings) | [GitLab.com](https://gitlab.com) | CE/EE | | --------- | ----------- |:--------------------:|:------------------:|:-----:|:--------:|:--------:| -| NGINX | Routes requests to appropriate components, terminates SSL | [✅](https://docs.gitlab.com/omnibus/settings/nginx.html) | [✅](https://docs.gitlab.com/charts/charts/nginx/index.html) | [⚙](https://docs.gitlab.com/charts/charts/nginx/index.html) | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#service-architecture) |CE & EE | +| NGINX | Routes requests to appropriate components, terminates SSL | [✅](https://docs.gitlab.com/omnibus/settings/nginx.html) | [✅](https://docs.gitlab.com/charts/charts/nginx/index.html) | [⚙](https://docs.gitlab.com/charts/charts/nginx/index.html) | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#service-architecture) | CE & EE | | Unicorn (GitLab Rails) | Handles requests for the web interface and API | [✅](https://docs.gitlab.com/omnibus/settings/unicorn.html) | [✅](https://docs.gitlab.com/charts/charts/gitlab/unicorn/index.html) | [✅](https://docs.gitlab.com/charts/charts/gitlab/unicorn/index.html) | [✅](https://docs.gitlab.com/ee/user/gitlab_com/#unicorn) | CE & EE | | Sidekiq | Background jobs processor | [✅](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/files/gitlab-config-template/gitlab.rb.template) | [✅](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/index.html) | [✅](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/index.html) | [✅](https://docs.gitlab.com/ee/user/gitlab_com/#sidekiq) | CE & EE | | Gitaly | Git RPC service for handling all git calls made by GitLab | [✅](https://docs.gitlab.com/ee/administration/gitaly/) | [✅](https://docs.gitlab.com/charts/charts/gitlab/gitaly/index.html) | [✅](https://docs.gitlab.com/charts/charts/gitlab/gitaly/index.html) | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#service-architecture) | CE & EE | @@ -339,22 +307,22 @@ class Geo defaultoff | Redis Exporter | Prometheus endpoint with Redis metrics | [✅](https://docs.gitlab.com/ee/administration/monitoring/prometheus/redis_exporter.html) | [✅](https://docs.gitlab.com/charts/charts/redis/index.html) | [✅](https://docs.gitlab.com/charts/charts/redis/index.html) | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | CE & EE | | PostgreSQL Exporter | Prometheus endpoint with PostgreSQL metrics | [✅](https://docs.gitlab.com/ee/administration/monitoring/prometheus/postgres_exporter.html) | [✅](https://github.com/helm/charts/tree/master/stable/postgresql) | [✅](https://github.com/helm/charts/tree/master/stable/postgresql) | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | CE & EE | | PgBouncer Exporter | Prometheus endpoint with PgBouncer metrics | [⚙](https://docs.gitlab.com/ee/administration/monitoring/prometheus/pgbouncer_exporter.html) | [❌](https://docs.gitlab.com/charts/installation/deployment.html#postgresql) | [❌](https://docs.gitlab.com/charts/installation/deployment.html#postgresql) | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | CE & EE | -| GitLab Monitor | Tracks a variety of GitLab metrics | [✅](https://docs.gitlab.com/ee/administration/monitoring/prometheus/gitlab_monitor_exporter.html) | [❌](https://gitlab.com/charts/gitlab/issues/319) | [❌](https://gitlab.com/charts/gitlab/issues/319) | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | CE & EE | +| GitLab Monitor | Generates a variety of GitLab metrics | [✅](https://docs.gitlab.com/ee/administration/monitoring/prometheus/gitlab_monitor_exporter.html) | [❌](https://gitlab.com/charts/gitlab/issues/319) | [❌](https://gitlab.com/charts/gitlab/issues/319) | [✅](https://about.gitlab.com/handbook/engineering/monitoring/) | CE & EE | | Mattermost | Open-source Slack alternative | [⚙](https://docs.gitlab.com/omnibus/gitlab-mattermost/) | [⤓](https://docs.mattermost.com/install/install-mmte-helm-gitlab-helm.html) | [⤓](https://docs.mattermost.com/install/install-mmte-helm-gitlab-helm.html) | [⤓](https://docs.gitlab.com/ee/user/project/integrations/mattermost_slash_commands.html#manual-configuration), [⤓](https://docs.gitlab.com/ee/user/project/integrations/mattermost.html) | CE & EE | -| Minio | Object storage service | [⤓](https://min.io/download) | [✅](https://docs.gitlab.com/charts/charts/minio/index.html) | [✅](https://docs.gitlab.com/charts/charts/minio/index.html) | [❌](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#storage-architecture) | CE & EE | +| Minio | Object storage service | [⤓](https://min.io/download) | [✅](https://docs.gitlab.com/charts/charts/minio/index.html) | [✅](https://docs.gitlab.com/charts/charts/minio/index.html) | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#storage-architecture) | CE & EE | | Runner | Executes GitLab CI jobs | [⤓](https://docs.gitlab.com/runner/) | [✅](https://docs.gitlab.com/runner/) | [⚙](https://docs.gitlab.com/runner/) | [✅](https://docs.gitlab.com/ee/user/gitlab_com/#shared-runners) | CE & EE | -| Migrations | Database migrations | [✅](https://docs.gitlab.com/omnibus/settings/database.html#disabling-automatic-database-migration) | [✅](https://docs.gitlab.com/charts/charts/gitlab/migrations/index.html) | [✅](https://docs.gitlab.com/charts/charts/gitlab/migrations/index.html) | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#database-architecture) | CE & EE | +| DB Migrations | Database migrations | [✅](https://docs.gitlab.com/omnibus/settings/database.html#disabling-automatic-database-migration) | [✅](https://docs.gitlab.com/charts/charts/gitlab/migrations/index.html) | [✅](https://docs.gitlab.com/charts/charts/gitlab/migrations/index.html) | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#database-architecture) | CE & EE | | Certificate Management | TLS Settings, Let's Encrypt | [✅](https://docs.gitlab.com/omnibus/settings/ssl.html) | [✅](https://docs.gitlab.com/charts/installation/tls.html) | [⚙](https://docs.gitlab.com/charts/installation/tls.html) | [✅](https://about.gitlab.com/handbook/engineering/infrastructure/production-architecture/#secrets-management) | CE & EE | | GitLab Geo Node | Geographically distributed GitLab nodes | [⚙](https://docs.gitlab.com/ee/administration/geo/replication/index.html#setup-instructions) | [❌](https://gitlab.com/charts/gitlab/issues/8) | [❌](https://gitlab.com/charts/gitlab/issues/8) | ✅ | EE Only | | LDAP Authentication | Authenticate users against centralized LDAP directory | [⤓](https://docs.gitlab.com/ee/administration/auth/ldap.html) | [⤓](https://docs.gitlab.com/charts/charts/globals.html#ldap) | [⤓](https://docs.gitlab.com/charts/charts/globals.html#ldap) | [❌](https://about.gitlab.com/pricing/#gitlab-com) | CE & EE | | Outbound email (SMTP) | Send email messages to users | [⤓](https://docs.gitlab.com/omnibus/settings/smtp.html) | [⤓](https://docs.gitlab.com/charts/installation/command-line-options.html#outgoing-email-configuration) | [⤓](https://docs.gitlab.com/charts/installation/command-line-options.html#outgoing-email-configuration) | [✅](https://docs.gitlab.com/ee/user/gitlab_com/#mail-configuration) | CE & EE | | Inbound email (SMTP) | Receive messages to update issues | [⤓](https://docs.gitlab.com/ee/administration/incoming_email.html) | [⤓](https://docs.gitlab.com/charts/installation/command-line-options.html#incoming-email-configuration) | [⤓](https://docs.gitlab.com/charts/installation/command-line-options.html#incoming-email-configuration) | [✅](https://docs.gitlab.com/ee/user/gitlab_com/#mail-configuration) | CE & EE | | ElasticSearch | Improved search within GitLab | [⤓](https://docs.gitlab.com/ee/integration/elasticsearch.html) | [⤓](https://docs.gitlab.com/ee/integration/elasticsearch.html) | [⤓](https://docs.gitlab.com/ee/integration/elasticsearch.html) | [❌](https://gitlab.com/groups/gitlab-org/-/epics/153) | EE Only | -| Sentry: GitLab instance | Tracking errors generated by the GitLab instance | [⤓](https://docs.gitlab.com/omnibus/settings/configuration.html#error-reporting-and-logging-with-sentry) | [❌](https://gitlab.com/charts/gitlab/issues/1319) | [❌](https://gitlab.com/charts/gitlab/issues/1319) | [✅](https://about.gitlab.com/handbook/support/workflows/services/gitlab_com/500_errors.html#searching-sentry) | CE & EE | +| Sentry: GitLab instance | Track errors generated by the GitLab instance | [⤓](https://docs.gitlab.com/omnibus/settings/configuration.html#error-reporting-and-logging-with-sentry) | [❌](https://gitlab.com/charts/gitlab/issues/1319) | [❌](https://gitlab.com/charts/gitlab/issues/1319) | [✅](https://about.gitlab.com/handbook/support/workflows/services/gitlab_com/500_errors.html#searching-sentry) | CE & EE | | Jaeger: GitLab instance | View traces generated by the GitLab instance | [❌](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/4104) | [❌](https://gitlab.com/charts/gitlab/issues/1320) | [❌](https://gitlab.com/charts/gitlab/issues/1320) | [❌](https://gitlab.com/gitlab-org/omnibus-gitlab/issues/4104) | CE & EE | | Sentry: deployed apps | Error tracking for deployed apps | [⤓](https://docs.gitlab.com/ee/user/project/operations/error_tracking.html) | [⤓](https://docs.gitlab.com/ee/user/project/operations/error_tracking.html) | [⤓](https://docs.gitlab.com/ee/user/project/operations/error_tracking.html) | [⤓](https://docs.gitlab.com/ee/user/project/operations/error_tracking.html) | CE & EE | | Jaeger: deployed apps | Distributed tracing for deployed apps | [⤓](https://docs.gitlab.com/ee/user/project/operations/tracing.html) | [⤓](https://docs.gitlab.com/ee/user/project/operations/tracing.html) | [⤓](https://docs.gitlab.com/ee/user/project/operations/tracing.html) | [⤓](https://docs.gitlab.com/ee/user/project/operations/tracing.html) | EE Only | -| Kubernetes cluster apps | Deploy [Helm](https://docs.helm.sh/), [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/), [Cert-Manager](https://docs.cert-manager.io/en/latest/), [Prometheus](https://prometheus.io/docs/introduction/overview/), a [Runner](https://docs.gitlab.com/runner/), [JupyterHub](http://jupyter.org/), [Knative](https://cloud.google.com/knative) to a cluster | [⤓](https://docs.gitlab.com/ee/user/project/clusters/#installing-applications) | [⤓](https://docs.gitlab.com/ee/user/project/clusters/#installing-applications) | [⤓](https://docs.gitlab.com/ee/user/project/clusters/#installing-applications) | [⤓](https://docs.gitlab.com/ee/user/project/clusters/#installing-applications) | CE & EE | +| Kubernetes cluster apps | Deploy [Helm](https://docs.helm.sh/), [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/), [Cert-Manager](https://docs.cert-manager.io/en/latest/), [Prometheus](https://prometheus.io/docs/introduction/overview/), a [Runner](https://docs.gitlab.com/runner/), [JupyterHub](http://jupyter.org/), [Knative](https://cloud.google.com/knative) to a cluster | [✅](https://docs.gitlab.com/ee/user/project/clusters/#installing-applications) | [✅](https://docs.gitlab.com/ee/user/project/clusters/#installing-applications) | [✅](https://docs.gitlab.com/ee/user/project/clusters/#installing-applications) | [✅](https://docs.gitlab.com/ee/user/project/clusters/#installing-applications) | CE & EE | A typical install of GitLab will be on GNU/Linux. It uses Nginx or Apache as a web front end to proxypass the Unicorn web server. By default, communication between Unicorn and the front end is via a Unix domain socket but forwarding requests via TCP is also supported. The web front end accesses `/home/git/gitlab/public` bypassing the Unicorn server to serve static pages, uploads (e.g. avatar images or attachments), and precompiled assets. GitLab serves web pages and a [GitLab API](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/api) using the Unicorn web server. It uses Sidekiq as a job queue which, in turn, uses redis as a non-persistent database backend for job information, meta data, and incoming jobs. diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md index 5f6123b5f9b..8e06aa5d173 100644 --- a/doc/development/fe_guide/graphql.md +++ b/doc/development/fe_guide/graphql.md @@ -43,9 +43,9 @@ new Vue({ Read more about [Vue Apollo][vue-apollo] in the [Vue Apollo documentation][vue-apollo-docs]. -### Local state with `apollo-link-state` +### Local state with Apollo -It is possible to use our Apollo setup with [apollo-link-state][apollo-link-state] by passing +It is possible to manage an application state with Apollo by passing in a resolvers object when creating the default client. The default state can be set by writing to the cache after setting up the default client. @@ -76,6 +76,8 @@ const apolloProvider = new VueApollo({ }); ``` +Read more about local state management with Apollo in the [Vue Apollo documentation](https://vue-apollo.netlify.com/guide/local-state.html#local-state). + ### Testing With [Vue test utils][vue-test-utils] it is easy to quickly test components that @@ -92,6 +94,8 @@ it('tests apollo component', () => { }); ``` +Another possible way is testing queries with mocked GraphQL schema. Read more about this way in [Vue Apollo testing documentation](https://vue-apollo.netlify.com/guide/testing.html#tests-with-mocked-graqhql-schema) + ## Usage outside of Vue It is also possible to use GraphQL outside of Vue by directly importing diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md index f58a8dcbcdc..9bd99e80357 100644 --- a/doc/development/testing_guide/frontend_testing.md +++ b/doc/development/testing_guide/frontend_testing.md @@ -187,6 +187,7 @@ export default function doSomething() { visitUrl('/foo/bar'); } ``` + ```js // my_module_spec.js import doSomething from '~/my_module'; @@ -213,7 +214,187 @@ Further documentation on the babel rewire pluign API can be found on #### Waiting in tests -If you cannot avoid using [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) in tests, please use the [Jasmine mock clock](https://jasmine.github.io/api/2.9/Clock.html). +Sometimes a test needs to wait for something to happen in the application before it continues. +Avoid using [`setTimeout`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout) +because it makes the reason for waiting unclear and if passed a time larger than zero it will slow down our test suite. +Instead use one of the following approaches. + +##### Promises and Ajax calls + +Register handler functions to wait for the `Promise` to be resolved. + +```javascript +const askTheServer = () => { + return axios + .get('/endpoint') + .then(response => { + // do something + }) + .catch(error => { + // do something else + }); +}; +``` + +**in Jest:** + +```javascript +it('waits for an Ajax call', () => { + return askTheServer().then(() => { + expect(something).toBe('done'); + }); +}); +``` + +**in Karma:** + +```javascript +it('waits for an Ajax call', done => { + askTheServer() + .then(() => { + expect(something).toBe('done'); + }) + .then(done) + .catch(done.fail); +}); +``` + +If you are not able to register handlers to the `Promise`—for example because it is executed in a synchronous Vue life +cycle hook—you can flush all pending `Promise`s: + +**in Jest:** + +```javascript +it('waits for an Ajax call', () => { + synchronousFunction(); + jest.runAllTicks(); + + expect(something).toBe('done'); +}); +``` + +**in Karma:** + +You are out of luck. The following only works sometimes and may lead to flaky failures: + +```javascript +it('waits for an Ajax call', done => { + synchronousFunction(); + + // create a new Promise and hope that it resolves after the rest + Promise.resolve() + .then(() => { + expect(something).toBe('done'); + }) + .then(done) + .catch(done.fail); +}); +``` + +##### Vue rendering + +To wait until a Vue component is re-rendered, use either of the equivalent +[`Vue.nextTick()`](https://vuejs.org/v2/api/#Vue-nextTick) or `vm.$nextTick()`. + +**in Jest:** + +```javascript +it('renders something', () => { + wrapper.setProps({ value: 'new value' }); + + return wrapper.vm.$nextTick().then(() => { + expect(wrapper.text()).toBe('new value'); + }); +}); +``` + +**in Karma:** + +```javascript +it('renders something', done => { + wrapper.setProps({ value: 'new value' }); + + wrapper.vm + .$nextTick() + .then(() => { + expect(wrapper.text()).toBe('new value'); + }) + .then(done) + .catch(done.fail); +}); +``` + +##### `setTimeout()` / `setInterval()` in application + +If the application itself is waiting for some time, mock await the waiting. In Jest this is already +[done by default](https://gitlab.com/gitlab-org/gitlab-ce/blob/a2128edfee799e49a8732bfa235e2c5e14949c68/jest.config.js#L47) +(see also [Jest Timer Mocks](https://jestjs.io/docs/en/timer-mocks)). In Karma you can use the +[Jasmine mock clock](https://jasmine.github.io/api/2.9/Clock.html). + +```javascript +const doSomethingLater = () => { + setTimeout(() => { + // do something + }, 4000); +}; +``` + +**in Jest:** + +```javascript +it('does something', () => { + doSomethingLater(); + jest.runAllTimers(); + + expect(something).toBe('done'); +}); +``` + +**in Karma:** + +```javascript +it('does something', () => { + jasmine.clock().install(); + + doSomethingLater(); + jasmine.clock().tick(4000); + + expect(something).toBe('done'); + jasmine.clock().uninstall(); +}); +``` + +##### Events + +If the application triggers an event that you need to wait for in your test, register an event handler which contains +the assertions: + +```javascript +it('waits for an event', done => { + eventHub.$once('someEvent', eventHandler); + + someFunction(); + + function eventHandler() { + expect(something).toBe('done'); + done(); + } +}); +``` + +In Jest you can also use a `Promise` for this: + +```javascript +it('waits for an event', () => { + const eventTriggered = new Promise(resolve => eventHub.$once('someEvent', resolve)); + + someFunction(); + + return eventTriggered.then(() => { + expect(something).toBe('done'); + }); +}); +``` #### Migrating flaky Karma tests to Jest diff --git a/doc/install/installation.md b/doc/install/installation.md index c694f0ed691..f16bc04af34 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -163,9 +163,9 @@ Download Ruby and compile it: ```sh mkdir /tmp/ruby && cd /tmp/ruby -curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.3.tar.gz -echo 'f919a9fbcdb7abecd887157b49833663c5c15fda ruby-2.5.3.tar.gz' | shasum -c - && tar xzf ruby-2.5.3.tar.gz -cd ruby-2.5.3 +curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.3.tar.gz +echo '2347ed6ca5490a104ebd5684d2b9b5eefa6cd33c ruby-2.6.3.tar.gz' | shasum -c - && tar xzf ruby-2.6.3.tar.gz +cd ruby-2.6.3 ./configure --disable-install-rdoc make diff --git a/doc/install/requirements.md b/doc/install/requirements.md index 672723aaf12..f6a52205a0e 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -169,7 +169,7 @@ So for a machine with 2 cores, 3 unicorn workers is ideal. For all machines that have 2GB and up we recommend a minimum of three unicorn workers. If you have a 1GB machine we recommend to configure only two Unicorn workers to prevent excessive swapping. -To change the Unicorn workers when you have the Omnibus package (which defaults to the recommendation above) please see [the Unicorn settings in the Omnibus GitLab documentation](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/unicorn.md#unicorn-settings). +To change the Unicorn workers when you have the Omnibus package (which defaults to the recommendation above) please see [the Unicorn settings in the Omnibus GitLab documentation](https://docs.gitlab.com/omnibus/settings/unicorn.html). ## Redis and Sidekiq @@ -201,14 +201,13 @@ you decide to run GitLab Runner and the GitLab Rails application on the same machine. It is also not safe to install everything on a single machine, because of the -[security reasons] - especially when you plan to use shell executor with GitLab +[security reasons](https://docs.gitlab.com/runner/security/) +- especially when you plan to use shell executor with GitLab Runner. We recommend using a separate machine for each GitLab Runner, if you plan to use the CI features. -[security reasons]: https://gitlab.com/gitlab-org/gitlab-runner/blob/master/docs/security/index.md - ## Supported web browsers We support the current and the previous major release of: diff --git a/doc/integration/salesforce.md b/doc/integration/salesforce.md index 18d42486fd6..8a99641a256 100644 --- a/doc/integration/salesforce.md +++ b/doc/integration/salesforce.md @@ -1,15 +1,15 @@ # SalesForce OmniAuth Provider -You can integrate your GitLab instance with [SalesForce](https://www.salesforce.com/) to enable users to login to your GitLab instance with their SalesForce account. +You can integrate your GitLab instance with [SalesForce](https://www.salesforce.com/) to enable users to login to your GitLab instance with their SalesForce account. ## Create SalesForce Application To enable SalesForce OmniAuth provider, you must use SalesForce's credentials for your GitLab instance. -To get the credentials (a pair of Client ID and Client Secret), you must register an application on UltraAuth. +To get the credentials (a pair of Client ID and Client Secret), you must register an application on SalesForces. 1. Sign in to [SalesForce](https://www.salesforce.com/). -1. Navigate to **Platform Tools/Apps** and click on **New Connected App**. +1. Navigate to **Platform Tools/Apps/App Manager** and click on **New Connected App**. 1. Fill in the application details into the following fields: - **Connected App Name** and **API Name**: Set to any value but consider something like `<Organization>'s GitLab`, `<Your Name>'s GitLab`, or something else that is descriptive. @@ -64,7 +64,7 @@ To get the credentials (a pair of Client ID and Client Secret), you must registe } ``` 1. Change `SALESFORCE_CLIENT_ID` to the Consumer Key from the SalesForce connected application page. -1. Change `SALESFORCE_CLIENT_SECRET` to the Client Secret from the SalesForce connected application page. +1. Change `SALESFORCE_CLIENT_SECRET` to the Consumer Secret from the SalesForce connected application page. ![SalesForce App Secret Details](img/salesforce_app_secret_details.png) 1. Save the configuration file. diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md index fea89669831..5118726cb0a 100644 --- a/doc/update/upgrading_from_source.md +++ b/doc/update/upgrading_from_source.md @@ -52,9 +52,9 @@ Download Ruby and compile it: ```bash mkdir /tmp/ruby && cd /tmp/ruby -curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.3.tar.gz -echo 'f919a9fbcdb7abecd887157b49833663c5c15fda ruby-2.5.3.tar.gz' | shasum -c - && tar xzf ruby-2.5.3.tar.gz -cd ruby-2.5.3 +curl --remote-name --progress https://cache.ruby-lang.org/pub/ruby/2.6/ruby-2.6.3.tar.gz +echo '2347ed6ca5490a104ebd5684d2b9b5eefa6cd33c ruby-2.6.3.tar.gz' | shasum -c - && tar xzf ruby-2.6.3.tar.gz +cd ruby-2.6.3 ./configure --disable-install-rdoc make diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md index 834a1e2423a..42fc4efa4ce 100644 --- a/doc/user/admin_area/settings/continuous_integration.md +++ b/doc/user/admin_area/settings/continuous_integration.md @@ -98,8 +98,7 @@ the group. NOTE: **Note:** Only available on GitLab.com. -If you have a Group with a [paid plan](https://about.gitlab.com/pricing/#gitlab-com) on GitLab.com, -then you can purchase additional CI minutes so your pipelines will not be blocked after you have +You can purchase additional CI minutes so your pipelines will not be blocked after you have used all your CI minutes from your main quota. In order to purchase additional minutes, you should follow these steps: diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md index 8e1603f9ec9..10eb3a4f3b7 100644 --- a/doc/user/project/integrations/webhooks.md +++ b/doc/user/project/integrations/webhooks.md @@ -321,8 +321,14 @@ X-Gitlab-Event: Issue Hook "group_id": 41 }], "changes": { - "updated_by_id": [null, 1], - "updated_at": ["2017-09-15 16:50:55 UTC", "2017-09-15 16:52:00 UTC"], + "updated_by_id": { + "previous": null, + "current": 1 + }, + "updated_at": { + "previous": "2017-09-15 16:50:55 UTC", + "current": "2017-09-15 16:52:00 UTC" + }, "labels": { "previous": [{ "id": 206, @@ -851,8 +857,14 @@ X-Gitlab-Event: Merge Request Hook "group_id": 41 }], "changes": { - "updated_by_id": [null, 1], - "updated_at": ["2017-09-15 16:50:55 UTC", "2017-09-15 16:52:00 UTC"], + "updated_by_id": { + "previous": null, + "current": 1 + }, + "updated_at": { + "previous": "2017-09-15 16:50:55 UTC", + "current":"2017-09-15 16:52:00 UTC" + }, "labels": { "previous": [{ "id": 206, diff --git a/doc/user/project/new_ci_build_permissions_model.md b/doc/user/project/new_ci_build_permissions_model.md index 6c3fa5eb463..d36312c9b8d 100644 --- a/doc/user/project/new_ci_build_permissions_model.md +++ b/doc/user/project/new_ci_build_permissions_model.md @@ -44,14 +44,14 @@ It is important to note that we have a few types of users: - **Administrators**: CI jobs created by Administrators will not have access to all GitLab projects, but only to projects and container images of projects - that the administrator is a member of.That means that if a project is either + that the administrator is a member of. That means that if a project is either public or internal users have access anyway, but if a project is private, the Administrator will have to be a member of it in order to have access to it via another project's job. - **External users**: CI jobs created by [external users](../permissions.md#external-users-permissions) will have access only to projects to which user has at least reporter access. This - rules out accessing all internal projects by default, + rules out accessing all internal projects by default. This allows us to make the CI and permission system more trustworthy. Let's consider the following scenario: diff --git a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md index ea22f3e905b..da1b7c59c8e 100644 --- a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md +++ b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md @@ -145,8 +145,8 @@ Now that your certificate has been issued, let's add it to your Pages site: 1. Visit your website at `https://example.com`. To force `https` connections on your site, navigate to your -project's **Settings > Pages** and check **Force domains with SSL -certificates to use HTTPS**. +project's **Settings > Pages** and check **Force HTTPS (requires +valid certificates)**. ## Renewal diff --git a/lib/gitlab/bitbucket_import/importer.rb b/lib/gitlab/bitbucket_import/importer.rb index 769d3279f91..c9f0ed66a54 100644 --- a/lib/gitlab/bitbucket_import/importer.rb +++ b/lib/gitlab/bitbucket_import/importer.rb @@ -135,7 +135,7 @@ module Gitlab def create_labels LABELS.each do |label_params| - label = ::Labels::CreateService.new(label_params).execute(project: project) + label = ::Labels::FindOrCreateService.new(nil, project, label_params).execute(skip_authorization: true) if label.valid? @labels[label_params[:title]] = label else diff --git a/lib/tasks/gitlab/backup.rake b/lib/tasks/gitlab/backup.rake index 3977fc7ad8c..c531eb1d216 100644 --- a/lib/tasks/gitlab/backup.rake +++ b/lib/tasks/gitlab/backup.rake @@ -20,6 +20,11 @@ namespace :gitlab do backup.pack backup.cleanup backup.remove_old + + puts "Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data \n" \ + "and are not included in this backup. You will need these files to restore a backup.\n" \ + "Please back them up manually.".color(:red) + puts "Backup task is done." end # Restore backup of GitLab system @@ -68,6 +73,9 @@ namespace :gitlab do Rake::Task['cache:clear'].invoke backup.cleanup + puts "Warning: Your gitlab.rb and gitlab-secrets.json files contain sensitive data \n" \ + "and are not included in this backup. You will need to restore these files manually.".color(:red) + puts "Restore task is done." end namespace :repo do diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 6a3184175f4..71ec8bcb9ba 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -7061,6 +7061,9 @@ msgstr "" msgid "Private - The group and its projects can only be viewed by members." msgstr "" +msgid "Private profile" +msgstr "" + msgid "Private projects can be created in your personal namespace with:" msgstr "" @@ -7100,6 +7103,9 @@ msgstr "" msgid "Profiles|Avatar will be removed. Are you sure?" msgstr "" +msgid "Profiles|Bio" +msgstr "" + msgid "Profiles|Change username" msgstr "" @@ -7160,6 +7166,18 @@ msgstr "" msgid "Profiles|Enter your name, so people you know can recognize you" msgstr "" +msgid "Profiles|Feed token was successfully reset" +msgstr "" + +msgid "Profiles|Full name" +msgstr "" + +msgid "Profiles|Include private contributions on my profile" +msgstr "" + +msgid "Profiles|Incoming email token was successfully reset" +msgstr "" + msgid "Profiles|Increase your account's security by enabling Two-Factor Authentication (2FA)" msgstr "" @@ -7172,6 +7190,9 @@ msgstr "" msgid "Profiles|Learn more" msgstr "" +msgid "Profiles|Location" +msgstr "" + msgid "Profiles|Made a private contribution" msgstr "" @@ -7181,6 +7202,9 @@ msgstr "" msgid "Profiles|No file chosen" msgstr "" +msgid "Profiles|Organization" +msgstr "" + msgid "Profiles|Path" msgstr "" @@ -7190,6 +7214,9 @@ msgstr "" msgid "Profiles|Private contributions" msgstr "" +msgid "Profiles|Profile was successfully updated" +msgstr "" + msgid "Profiles|Public Avatar" msgstr "" @@ -7253,6 +7280,9 @@ msgstr "" msgid "Profiles|Use a private email - %{email}" msgstr "" +msgid "Profiles|User ID" +msgstr "" + msgid "Profiles|Username change failed - %{message}" msgstr "" diff --git a/qa/Dockerfile b/qa/Dockerfile index ca7f9accb70..74be373b8e8 100644 --- a/qa/Dockerfile +++ b/qa/Dockerfile @@ -1,4 +1,4 @@ -FROM ruby:2.5-stretch +FROM ruby:2.6-stretch LABEL maintainer "Grzegorz Bizon <grzegorz@gitlab.com>" ENV DEBIAN_FRONTEND noninteractive diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb index 9fabf83e2ce..c395e5f6011 100644 --- a/qa/qa/page/base.rb +++ b/qa/qa/page/base.rb @@ -113,8 +113,8 @@ module QA has_css?(element_selector_css(name), wait: wait, text: text) end - def has_no_element?(name, wait: Capybara.default_max_wait_time) - has_no_css?(element_selector_css(name), wait: wait) + def has_no_element?(name, text: nil, wait: Capybara.default_max_wait_time) + has_no_css?(element_selector_css(name), wait: wait, text: text) end def has_text?(text) @@ -129,8 +129,8 @@ module QA has_no_css?('.fa-spinner', wait: Capybara.default_max_wait_time) end - def within_element(name) - page.within(element_selector_css(name)) do + def within_element(name, text: nil) + page.within(element_selector_css(name), text: text) do yield end end diff --git a/qa/qa/page/project/branches/show.rb b/qa/qa/page/project/branches/show.rb index 922a6ddb086..762eacdab15 100644 --- a/qa/qa/page/project/branches/show.rb +++ b/qa/qa/page/project/branches/show.rb @@ -7,6 +7,7 @@ module QA class Show < Page::Base view 'app/views/projects/branches/_branch.html.haml' do element :remove_btn + element :branch_name end view 'app/views/projects/branches/_panel.html.haml' do element :all_branches @@ -27,11 +28,9 @@ module QA finished_loading? end - def has_branch_title?(branch_title) + def has_no_branch?(branch_name) within_element(:all_branches) do - within(".item-title") do - has_text?(branch_title) - end + has_no_element?(:branch_name, text: branch_name, wait: Support::Waiter::DEFAULT_MAX_WAIT_TIME) end end @@ -48,15 +47,6 @@ module QA click_element(:delete_merged_branches) end end - - def wait_for_texts_not_to_be_visible(texts) - text_not_visible = wait do - texts.all? do |text| - has_no_text?(text) - end - end - raise "Expected text(s) #{texts} not to be visible" unless text_not_visible - end end end end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb index c2c2b6da90a..cf6c24fa873 100644 --- a/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_list_delete_branches_spec.rb @@ -73,10 +73,9 @@ module QA Page::Project::Branches::Show.perform do |branches_view| branches_view.delete_branch(third_branch) + expect(branches_view).to have_no_branch(third_branch) end - expect(page).not_to have_content(third_branch) - Page::Project::Branches::Show.perform(&:delete_merged_branches) expect(page).to have_content( @@ -85,8 +84,7 @@ module QA page.refresh Page::Project::Branches::Show.perform do |branches_view| - branches_view.wait_for_texts_not_to_be_visible([commit_message_of_second_branch]) - expect(branches_view).not_to have_branch_title(second_branch) + expect(branches_view).to have_no_branch(second_branch) end end end diff --git a/qa/qa/support/page/logging.rb b/qa/qa/support/page/logging.rb index 69b6332ecce..ff505fdbddd 100644 --- a/qa/qa/support/page/logging.rb +++ b/qa/qa/support/page/logging.rb @@ -76,23 +76,18 @@ module QA super end - def has_element?(name, text: nil, wait: Capybara.default_max_wait_time) + def has_element?(name, **kwargs) found = super - msg = ["has_element? :#{name}"] - msg << %Q(with text "#{text}") if text - msg << "(wait: #{wait})" - msg << "returned: #{found}" - - log(msg.compact.join(' ')) + log_has_element_or_not('has_element?', name, found, **kwargs) found end - def has_no_element?(name, wait: Capybara.default_max_wait_time) + def has_no_element?(name, **kwargs) found = super - log("has_no_element? :#{name} returned #{found}") + log_has_element_or_not('has_no_element?', name, found, **kwargs) found end @@ -149,6 +144,15 @@ module QA def log(msg) QA::Runtime::Logger.debug(msg) end + + def log_has_element_or_not(method, name, found, **kwargs) + msg = ["#{method} :#{name}"] + msg << %Q(with text "#{kwargs[:text]}") if kwargs[:text] + msg << "(wait: #{kwargs[:wait] || Capybara.default_max_wait_time})" + msg << "returned: #{found}" + + log(msg.compact.join(' ')) + end end end end diff --git a/qa/qa/support/waiter.rb b/qa/qa/support/waiter.rb index 21a399b4a5f..fdcf2d7e157 100644 --- a/qa/qa/support/waiter.rb +++ b/qa/qa/support/waiter.rb @@ -3,9 +3,11 @@ module QA module Support module Waiter + DEFAULT_MAX_WAIT_TIME = 60 + module_function - def wait(max: 60, interval: 0.1) + def wait(max: DEFAULT_MAX_WAIT_TIME, interval: 0.1) QA::Runtime::Logger.debug("with wait: max #{max}; interval #{interval}") start = Time.now diff --git a/qa/spec/page/logging_spec.rb b/qa/spec/page/logging_spec.rb index 707a7ff6d98..99e96b81a51 100644 --- a/qa/spec/page/logging_spec.rb +++ b/qa/spec/page/logging_spec.rb @@ -93,7 +93,14 @@ describe QA::Support::Page::Logging do allow(page).to receive(:has_no_css?).and_return(true) expect { subject.has_no_element?(:element) } - .to output(/has_no_element\? :element returned true/).to_stdout_from_any_process + .to output(/has_no_element\? :element \(wait: 2\) returned: true/).to_stdout_from_any_process + end + + it 'logs has_no_element? with text' do + allow(page).to receive(:has_no_css?).and_return(true) + + expect { subject.has_no_element?(:element, text: "more text") } + .to output(/has_no_element\? :element with text \"more text\" \(wait: 2\) returned: true/).to_stdout_from_any_process end it 'logs has_text?' do diff --git a/spec/controllers/projects/graphs_controller_spec.rb b/spec/controllers/projects/graphs_controller_spec.rb index d390e84c9b0..b5248c7f0c8 100644 --- a/spec/controllers/projects/graphs_controller_spec.rb +++ b/spec/controllers/projects/graphs_controller_spec.rb @@ -28,6 +28,21 @@ describe Projects::GraphsController do end describe 'charts' do + context 'with an anonymous user' do + let(:project) { create(:project, :repository, :public) } + + before do + sign_out(user) + end + + it 'renders charts with 200 status code' do + get(:charts, params: { namespace_id: project.namespace.path, project_id: project.path, id: 'master' }) + + expect(response).to have_gitlab_http_status(:ok) + expect(response).to render_template(:charts) + end + end + context 'when languages were previously detected' do let(:project) { create(:project, :repository, detected_repository_languages: true) } let!(:repository_language) { create(:repository_language, project: project) } diff --git a/spec/features/dashboard/user_filters_projects_spec.rb b/spec/features/dashboard/user_filters_projects_spec.rb index 5b17c49db2d..4410c8f887f 100644 --- a/spec/features/dashboard/user_filters_projects_spec.rb +++ b/spec/features/dashboard/user_filters_projects_spec.rb @@ -151,34 +151,22 @@ describe 'Dashboard > User filters projects' do end describe 'Sorting' do - before do - [ - { name: 'Red ribbon army', created_at: 2.days.ago }, - { name: 'Cell saga', created_at: Time.now }, - { name: 'Frieza saga', created_at: 10.days.ago } - ].each do |item| - project = create(:project, name: item[:name], namespace: user.namespace, created_at: item[:created_at]) - project.add_developer(user) - end + let(:desc_sorted_project_names) { %w[Treasure Victorialand] } + before do user.toggle_star(project) user.toggle_star(project2) user2.toggle_star(project2) end - it 'includes sorting direction' do + it 'has all sorting options', :js do sorting_dropdown = page.find('.filtered-search-block #filtered-search-sorting-dropdown') expect(sorting_dropdown).to have_css '.reverse-sort-btn' - end - - it 'has all sorting options', :js do - sorting_dropdown = page.find('.filtered-search-block #filtered-search-sorting-dropdown') - sorting_option_labels = ['Last updated', 'Created date', 'Name', 'Stars'] sorting_dropdown.click - sorting_option_labels.each do |label| + ['Last updated', 'Created date', 'Name', 'Stars'].each do |label| expect(sorting_dropdown).to have_content(label) end end @@ -194,16 +182,11 @@ describe 'Dashboard > User filters projects' do it 'sorts the project list' do select_dropdown_option '#filtered-search-sorting-dropdown', 'Name' - desc = ['Victorialand', 'Treasure', 'Red ribbon army', 'Frieza saga', 'Cell saga'] - asc = ['Cell saga', 'Frieza saga', 'Red ribbon army', 'Treasure', 'Victorialand'] - - click_sort_direction - - expect_to_see_projects(desc) + expect_to_see_projects(desc_sorted_project_names) click_sort_direction - expect_to_see_projects(asc) + expect_to_see_projects(desc_sorted_project_names.reverse) end end @@ -211,16 +194,11 @@ describe 'Dashboard > User filters projects' do it 'sorts the project list' do select_dropdown_option '#filtered-search-sorting-dropdown', 'Last updated' - desc = ["Frieza saga", "Red ribbon army", "Victorialand", "Treasure", "Cell saga"] - asc = ["Cell saga", "Treasure", "Victorialand", "Red ribbon army", "Frieza saga"] + expect_to_see_projects(desc_sorted_project_names) click_sort_direction - expect_to_see_projects(desc) - - click_sort_direction - - expect_to_see_projects(asc) + expect_to_see_projects(desc_sorted_project_names.reverse) end end @@ -228,16 +206,11 @@ describe 'Dashboard > User filters projects' do it 'sorts the project list' do select_dropdown_option '#filtered-search-sorting-dropdown', 'Created date' - desc = ["Frieza saga", "Red ribbon army", "Victorialand", "Treasure", "Cell saga"] - asc = ["Cell saga", "Treasure", "Victorialand", "Red ribbon army", "Frieza saga"] - - click_sort_direction - - expect_to_see_projects(desc) + expect_to_see_projects(desc_sorted_project_names) click_sort_direction - expect_to_see_projects(asc) + expect_to_see_projects(desc_sorted_project_names.reverse) end end @@ -245,16 +218,11 @@ describe 'Dashboard > User filters projects' do it 'sorts the project list' do select_dropdown_option '#filtered-search-sorting-dropdown', 'Stars' - desc = ["Red ribbon army", "Cell saga", "Frieza saga", "Victorialand", "Treasure"] - asc = ["Treasure", "Victorialand", "Red ribbon army", "Cell saga", "Frieza saga"] - - click_sort_direction - - expect_to_see_projects(desc) + expect_to_see_projects(desc_sorted_project_names) click_sort_direction - expect_to_see_projects(asc) + expect_to_see_projects(desc_sorted_project_names.reverse) end end end diff --git a/spec/features/issuables/markdown_references/jira_spec.rb b/spec/features/issuables/markdown_references/jira_spec.rb index cc04798248c..8eaccfc0949 100644 --- a/spec/features/issuables/markdown_references/jira_spec.rb +++ b/spec/features/issuables/markdown_references/jira_spec.rb @@ -1,6 +1,6 @@ require "rails_helper" -describe "Jira", :js, :quarantine do +describe "Jira", :js do let(:user) { create(:user) } let(:actual_project) { create(:project, :public, :repository) } let(:merge_request) { create(:merge_request, target_project: actual_project, source_project: actual_project) } diff --git a/spec/frontend/notes/components/discussion_notes_spec.js b/spec/frontend/notes/components/discussion_notes_spec.js index 392c1b6533e..7e037beca9d 100644 --- a/spec/frontend/notes/components/discussion_notes_spec.js +++ b/spec/frontend/notes/components/discussion_notes_spec.js @@ -1,4 +1,4 @@ -import { mount, createLocalVue } from '@vue/test-utils'; +import { shallowMount, createLocalVue } from '@vue/test-utils'; import '~/behaviors/markdown/render_gfm'; import { SYSTEM_NOTE } from '~/notes/constants'; import DiscussionNotes from '~/notes/components/discussion_notes.vue'; @@ -8,6 +8,7 @@ import PlaceholderSystemNote from '~/vue_shared/components/notes/placeholder_sys import SystemNote from '~/vue_shared/components/notes/system_note.vue'; import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue'; import createStore from '~/notes/stores'; +import { setTestTimeout } from 'helpers/timeout'; import { noteableDataMock, discussionMock, @@ -17,6 +18,8 @@ import { const localVue = createLocalVue(); describe('DiscussionNotes', () => { + setTestTimeout(500); + let wrapper; const createComponent = props => { @@ -24,7 +27,7 @@ describe('DiscussionNotes', () => { store.dispatch('setNoteableData', noteableDataMock); store.dispatch('setNotesData', notesDataMock); - wrapper = mount(DiscussionNotes, { + wrapper = shallowMount(DiscussionNotes, { localVue, store, propsData: { diff --git a/spec/initializers/secret_token_spec.rb b/spec/initializers/secret_token_spec.rb index 726ce07a2d1..77bc28a6b07 100644 --- a/spec/initializers/secret_token_spec.rb +++ b/spec/initializers/secret_token_spec.rb @@ -45,11 +45,21 @@ describe 'create_tokens' do expect(keys).to all(match(RSA_KEY)) end + it "generates private key for Let's Encrypt" do + create_tokens + + keys = secrets.values_at(:lets_encrypt_private_key) + + expect(keys.uniq).to eq(keys) + expect(keys).to all(match(RSA_KEY)) + end + it 'warns about the secrets to add to secrets.yml' do expect(self).to receive(:warn_missing_secret).with('secret_key_base') expect(self).to receive(:warn_missing_secret).with('otp_key_base') expect(self).to receive(:warn_missing_secret).with('db_key_base') expect(self).to receive(:warn_missing_secret).with('openid_connect_signing_key') + expect(self).to receive(:warn_missing_secret).with('lets_encrypt_private_key') create_tokens end @@ -78,6 +88,7 @@ describe 'create_tokens' do before do secrets.db_key_base = 'db_key_base' secrets.openid_connect_signing_key = 'openid_connect_signing_key' + secrets.lets_encrypt_private_key = 'lets_encrypt_private_key' allow(File).to receive(:exist?).with('.secret').and_return(true) allow(File).to receive(:read).with('.secret').and_return('file_key') diff --git a/spec/javascripts/fixtures/abuse_reports.rb b/spec/javascripts/fixtures/abuse_reports.rb index 54b6419bcdb..e0aaecf626a 100644 --- a/spec/javascripts/fixtures/abuse_reports.rb +++ b/spec/javascripts/fixtures/abuse_reports.rb @@ -18,10 +18,9 @@ describe Admin::AbuseReportsController, '(JavaScript fixtures)', type: :controll sign_in(admin) end - it 'abuse_reports/abuse_reports_list.html' do |example| + it 'abuse_reports/abuse_reports_list.html' do get :index expect(response).to be_success - store_frontend_fixture(response, example.description) end end diff --git a/spec/javascripts/fixtures/admin_users.rb b/spec/javascripts/fixtures/admin_users.rb index 76dbdf603da..22a5de66577 100644 --- a/spec/javascripts/fixtures/admin_users.rb +++ b/spec/javascripts/fixtures/admin_users.rb @@ -17,13 +17,12 @@ describe Admin::UsersController, '(JavaScript fixtures)', type: :controller do clean_frontend_fixtures('admin/users') end - it 'admin/users/new_with_internal_user_regex.html' do |example| + it 'admin/users/new_with_internal_user_regex.html' do stub_application_setting(user_default_external: true) stub_application_setting(user_default_internal_regex: '^(?:(?!\.ext@).)*$\r?') get :new expect(response).to be_success - store_frontend_fixture(response, example.description) end end diff --git a/spec/javascripts/fixtures/application_settings.rb b/spec/javascripts/fixtures/application_settings.rb index c535e598e12..d4651fa6ece 100644 --- a/spec/javascripts/fixtures/application_settings.rb +++ b/spec/javascripts/fixtures/application_settings.rb @@ -23,12 +23,11 @@ describe Admin::ApplicationSettingsController, '(JavaScript fixtures)', type: :c remove_repository(project) end - it 'application_settings/accounts_and_limit.html' do |example| + it 'application_settings/accounts_and_limit.html' do stub_application_setting(user_default_external: false) get :show expect(response).to be_success - store_frontend_fixture(response, example.description) end end diff --git a/spec/javascripts/fixtures/autocomplete_sources.rb b/spec/javascripts/fixtures/autocomplete_sources.rb index c117fb7cd24..b20a0159d7d 100644 --- a/spec/javascripts/fixtures/autocomplete_sources.rb +++ b/spec/javascripts/fixtures/autocomplete_sources.rb @@ -18,7 +18,7 @@ describe Projects::AutocompleteSourcesController, '(JavaScript fixtures)', type: sign_in(admin) end - it 'autocomplete_sources/labels.json' do |example| + it 'autocomplete_sources/labels.json' do issue.labels << create(:label, project: project, title: 'bug') issue.labels << create(:label, project: project, title: 'critical') @@ -35,6 +35,5 @@ describe Projects::AutocompleteSourcesController, '(JavaScript fixtures)', type: } expect(response).to be_success - store_frontend_fixture(response, example.description) end end diff --git a/spec/javascripts/fixtures/balsamiq.rb b/spec/javascripts/fixtures/balsamiq.rb deleted file mode 100644 index 234e246119a..00000000000 --- a/spec/javascripts/fixtures/balsamiq.rb +++ /dev/null @@ -1,18 +0,0 @@ -require 'spec_helper' - -describe 'Balsamiq file', '(JavaScript fixtures)', type: :controller do - include JavaScriptFixturesHelpers - - let(:namespace) { create(:namespace, name: 'frontend-fixtures' )} - let(:project) { create(:project, :repository, namespace: namespace, path: 'balsamiq-project') } - - before(:all) do - clean_frontend_fixtures('blob/balsamiq/') - end - - it 'blob/balsamiq/test.bmpr' do |example| - blob = project.repository.blob_at('b89b56d79', 'files/images/balsamiq.bmpr') - - store_frontend_fixture(blob.data.force_encoding('utf-8'), example.description) - end -end diff --git a/spec/javascripts/fixtures/blob.rb b/spec/javascripts/fixtures/blob.rb index db7749bc000..07670552cd5 100644 --- a/spec/javascripts/fixtures/blob.rb +++ b/spec/javascripts/fixtures/blob.rb @@ -22,7 +22,7 @@ describe Projects::BlobController, '(JavaScript fixtures)', type: :controller do remove_repository(project) end - it 'blob/show.html' do |example| + it 'blob/show.html' do get(:show, params: { namespace_id: project.namespace, project_id: project, @@ -30,6 +30,5 @@ describe Projects::BlobController, '(JavaScript fixtures)', type: :controller do }) expect(response).to be_success - store_frontend_fixture(response, example.description) end end diff --git a/spec/javascripts/fixtures/boards.rb b/spec/javascripts/fixtures/boards.rb index c4390e89578..5835721d3d5 100644 --- a/spec/javascripts/fixtures/boards.rb +++ b/spec/javascripts/fixtures/boards.rb @@ -17,13 +17,12 @@ describe Projects::BoardsController, '(JavaScript fixtures)', type: :controller sign_in(admin) end - it 'boards/show.html' do |example| + it 'boards/show.html' do get(:index, params: { namespace_id: project.namespace, project_id: project }) expect(response).to be_success - store_frontend_fixture(response, example.description) end end diff --git a/spec/javascripts/fixtures/branches.rb b/spec/javascripts/fixtures/branches.rb index 5d2d6c7ec0e..204aa9b7c7a 100644 --- a/spec/javascripts/fixtures/branches.rb +++ b/spec/javascripts/fixtures/branches.rb @@ -21,13 +21,12 @@ describe Projects::BranchesController, '(JavaScript fixtures)', type: :controlle remove_repository(project) end - it 'branches/new_branch.html' do |example| + it 'branches/new_branch.html' do get :new, params: { namespace_id: project.namespace.to_param, project_id: project } expect(response).to be_success - store_frontend_fixture(response, example.description) end end diff --git a/spec/javascripts/fixtures/clusters.rb b/spec/javascripts/fixtures/clusters.rb index 8ebd8a41366..1076404e0e3 100644 --- a/spec/javascripts/fixtures/clusters.rb +++ b/spec/javascripts/fixtures/clusters.rb @@ -22,7 +22,7 @@ describe Projects::ClustersController, '(JavaScript fixtures)', type: :controlle remove_repository(project) end - it 'clusters/show_cluster.html' do |example| + it 'clusters/show_cluster.html' do get :show, params: { namespace_id: project.namespace.to_param, project_id: project, @@ -30,6 +30,5 @@ describe Projects::ClustersController, '(JavaScript fixtures)', type: :controlle } expect(response).to be_success - store_frontend_fixture(response, example.description) end end diff --git a/spec/javascripts/fixtures/commit.rb b/spec/javascripts/fixtures/commit.rb index ab10f559e4b..ff9a4bc1adc 100644 --- a/spec/javascripts/fixtures/commit.rb +++ b/spec/javascripts/fixtures/commit.rb @@ -19,7 +19,7 @@ describe Projects::CommitController, '(JavaScript fixtures)', type: :controller allow(SecureRandom).to receive(:hex).and_return('securerandomhex:thereisnospoon') end - it 'commit/show.html' do |example| + it 'commit/show.html' do params = { namespace_id: project.namespace, project_id: project, @@ -29,6 +29,5 @@ describe Projects::CommitController, '(JavaScript fixtures)', type: :controller get :show, params: params expect(response).to be_success - store_frontend_fixture(response, example.description) end end diff --git a/spec/javascripts/fixtures/deploy_keys.rb b/spec/javascripts/fixtures/deploy_keys.rb index a333d9c0150..38eab853da2 100644 --- a/spec/javascripts/fixtures/deploy_keys.rb +++ b/spec/javascripts/fixtures/deploy_keys.rb @@ -24,7 +24,7 @@ describe Projects::DeployKeysController, '(JavaScript fixtures)', type: :control render_views - it 'deploy_keys/keys.json' do |example| + it 'deploy_keys/keys.json' do create(:rsa_deploy_key_2048, public: true) project_key = create(:deploy_key, key: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCdMHEHyhRjbhEZVddFn6lTWdgEy5Q6Bz4nwGB76xWZI5YT/1WJOMEW+sL5zYd31kk7sd3FJ5L9ft8zWMWrr/iWXQikC2cqZK24H1xy+ZUmrRuJD4qGAaIVoyyzBL+avL+lF8J5lg6YSw8gwJY/lX64/vnJHUlWw2n5BF8IFOWhiw== dummy@gitlab.com') internal_key = create(:deploy_key, key: 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDNd/UJWhPrpb+b/G5oL109y57yKuCxE+WUGJGYaj7WQKsYRJmLYh1mgjrl+KVyfsWpq4ylOxIfFSnN9xBBFN8mlb0Fma5DC7YsSsibJr3MZ19ZNBprwNcdogET7aW9I0In7Wu5f2KqI6e5W/spJHCy4JVxzVMUvk6Myab0LnJ2iQ== dummy@gitlab.com') @@ -39,6 +39,5 @@ describe Projects::DeployKeysController, '(JavaScript fixtures)', type: :control }, format: :json expect(response).to be_success - store_frontend_fixture(response, example.description) end end diff --git a/spec/javascripts/fixtures/groups.rb b/spec/javascripts/fixtures/groups.rb index 16e31028b05..4d0afc3ce1a 100644 --- a/spec/javascripts/fixtures/groups.rb +++ b/spec/javascripts/fixtures/groups.rb @@ -18,20 +18,18 @@ describe 'Groups (JavaScript fixtures)', type: :controller do end describe GroupsController, '(JavaScript fixtures)', type: :controller do - it 'groups/edit.html' do |example| + it 'groups/edit.html' do get :edit, params: { id: group } expect(response).to be_success - store_frontend_fixture(response, example.description) end end describe Groups::Settings::CiCdController, '(JavaScript fixtures)', type: :controller do - it 'groups/ci_cd_settings.html' do |example| + it 'groups/ci_cd_settings.html' do get :show, params: { group_id: group } expect(response).to be_success - store_frontend_fixture(response, example.description) end end end diff --git a/spec/javascripts/fixtures/issues.rb b/spec/javascripts/fixtures/issues.rb index 0f3f9a10f94..d8d77f767de 100644 --- a/spec/javascripts/fixtures/issues.rb +++ b/spec/javascripts/fixtures/issues.rb @@ -21,26 +21,26 @@ describe Projects::IssuesController, '(JavaScript fixtures)', type: :controller remove_repository(project) end - it 'issues/open-issue.html' do |example| - render_issue(example.description, create(:issue, project: project)) + it 'issues/open-issue.html' do + render_issue(create(:issue, project: project)) end - it 'issues/closed-issue.html' do |example| - render_issue(example.description, create(:closed_issue, project: project)) + it 'issues/closed-issue.html' do + render_issue(create(:closed_issue, project: project)) end - it 'issues/issue-with-task-list.html' do |example| + it 'issues/issue-with-task-list.html' do issue = create(:issue, project: project, description: '- [ ] Task List Item') - render_issue(example.description, issue) + render_issue(issue) end - it 'issues/issue_with_comment.html' do |example| + it 'issues/issue_with_comment.html' do issue = create(:issue, project: project) create(:note, project: project, noteable: issue, note: '- [ ] Task List Item').save - render_issue(example.description, issue) + render_issue(issue) end - it 'issues/issue_list.html' do |example| + it 'issues/issue_list.html' do create(:issue, project: project) get :index, params: { @@ -49,12 +49,11 @@ describe Projects::IssuesController, '(JavaScript fixtures)', type: :controller } expect(response).to be_success - store_frontend_fixture(response, example.description) end private - def render_issue(fixture_file_name, issue) + def render_issue(issue) get :show, params: { namespace_id: project.namespace.to_param, project_id: project, @@ -62,7 +61,6 @@ describe Projects::IssuesController, '(JavaScript fixtures)', type: :controller } expect(response).to be_success - store_frontend_fixture(response, fixture_file_name) end end @@ -89,7 +87,7 @@ describe API::Issues, '(JavaScript fixtures)', type: :request do end end - it 'issues/related_merge_requests.json' do |example| + it 'issues/related_merge_requests.json' do user = create(:user) project = create(:project, :public, creator_id: user.id, namespace: user.namespace) issue_title = 'foo' @@ -120,6 +118,5 @@ describe API::Issues, '(JavaScript fixtures)', type: :request do get_related_merge_requests(project.id, issue.iid, user) expect(response).to be_success - store_frontend_fixture(response, example.description) end end diff --git a/spec/javascripts/fixtures/jobs.rb b/spec/javascripts/fixtures/jobs.rb index 941235190b5..46ccd6f8c8a 100644 --- a/spec/javascripts/fixtures/jobs.rb +++ b/spec/javascripts/fixtures/jobs.rb @@ -32,7 +32,7 @@ describe Projects::JobsController, '(JavaScript fixtures)', type: :controller do remove_repository(project) end - it 'builds/build-with-artifacts.html' do |example| + it 'builds/build-with-artifacts.html' do get :show, params: { namespace_id: project.namespace.to_param, project_id: project, @@ -40,10 +40,9 @@ describe Projects::JobsController, '(JavaScript fixtures)', type: :controller do } expect(response).to be_success - store_frontend_fixture(response, example.description) end - it 'jobs/delayed.json' do |example| + it 'jobs/delayed.json' do get :show, params: { namespace_id: project.namespace.to_param, project_id: project, @@ -51,6 +50,5 @@ describe Projects::JobsController, '(JavaScript fixtures)', type: :controller do }, format: :json expect(response).to be_success - store_frontend_fixture(response, example.description) end end diff --git a/spec/javascripts/fixtures/labels.rb b/spec/javascripts/fixtures/labels.rb index 9420194e675..4d1b7317274 100644 --- a/spec/javascripts/fixtures/labels.rb +++ b/spec/javascripts/fixtures/labels.rb @@ -30,13 +30,12 @@ describe 'Labels (JavaScript fixtures)' do sign_in(admin) end - it 'labels/group_labels.json' do |example| + it 'labels/group_labels.json' do get :index, params: { group_id: group }, format: 'json' expect(response).to be_success - store_frontend_fixture(response, example.description) end end @@ -47,14 +46,13 @@ describe 'Labels (JavaScript fixtures)' do sign_in(admin) end - it 'labels/project_labels.json' do |example| + it 'labels/project_labels.json' do get :index, params: { namespace_id: group, project_id: project }, format: 'json' expect(response).to be_success - store_frontend_fixture(response, example.description) end end end diff --git a/spec/javascripts/fixtures/merge_requests.rb b/spec/javascripts/fixtures/merge_requests.rb index 7df1e5cb512..05860be2291 100644 --- a/spec/javascripts/fixtures/merge_requests.rb +++ b/spec/javascripts/fixtures/merge_requests.rb @@ -42,52 +42,52 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont remove_repository(project) end - it 'merge_requests/merge_request_of_current_user.html' do |example| + it 'merge_requests/merge_request_of_current_user.html' do merge_request.update(author: admin) - render_merge_request(example.description, merge_request) + render_merge_request(merge_request) end - it 'merge_requests/merge_request_with_task_list.html' do |example| + it 'merge_requests/merge_request_with_task_list.html' do create(:ci_build, :pending, pipeline: pipeline) - render_merge_request(example.description, merge_request) + render_merge_request(merge_request) end - it 'merge_requests/merged_merge_request.html' do |example| + it 'merge_requests/merged_merge_request.html' do expect_next_instance_of(MergeRequest) do |merge_request| allow(merge_request).to receive(:source_branch_exists?).and_return(true) allow(merge_request).to receive(:can_remove_source_branch?).and_return(true) end - render_merge_request(example.description, merged_merge_request) + render_merge_request(merged_merge_request) end - it 'merge_requests/diff_comment.html' do |example| + it 'merge_requests/diff_comment.html' do create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request) create(:note_on_merge_request, author: admin, project: project, noteable: merge_request) - render_merge_request(example.description, merge_request) + render_merge_request(merge_request) end - it 'merge_requests/merge_request_with_comment.html' do |example| + it 'merge_requests/merge_request_with_comment.html' do create(:note_on_merge_request, author: admin, project: project, noteable: merge_request, note: '- [ ] Task List Item') - render_merge_request(example.description, merge_request) + render_merge_request(merge_request) end - it 'merge_requests/discussions.json' do |example| + it 'merge_requests/discussions.json' do create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request) - render_discussions_json(merge_request, example.description) + render_discussions_json(merge_request) end - it 'merge_requests/diff_discussion.json' do |example| + it 'merge_requests/diff_discussion.json' do create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request) - render_discussions_json(merge_request, example.description) + render_discussions_json(merge_request) end - it 'merge_requests/resolved_diff_discussion.json' do |example| + it 'merge_requests/resolved_diff_discussion.json' do note = create(:discussion_note_on_merge_request, :resolved, project: project, author: admin, position: position, noteable: merge_request) create(:system_note, project: project, author: admin, noteable: merge_request, discussion_id: note.discussion.id) - render_discussions_json(merge_request, example.description) + render_discussions_json(merge_request) end context 'with image diff' do @@ -106,25 +106,23 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont ) end - it 'merge_requests/image_diff_discussion.json' do |example| + it 'merge_requests/image_diff_discussion.json' do create(:diff_note_on_merge_request, project: project, noteable: merge_request2, position: image_position) - render_discussions_json(merge_request2, example.description) + render_discussions_json(merge_request2) end end private - def render_discussions_json(merge_request, fixture_file_name) + def render_discussions_json(merge_request) get :discussions, params: { namespace_id: project.namespace.to_param, project_id: project, id: merge_request.to_param }, format: :json - - store_frontend_fixture(response, fixture_file_name) end - def render_merge_request(fixture_file_name, merge_request) + def render_merge_request(merge_request) get :show, params: { namespace_id: project.namespace.to_param, project_id: project, @@ -132,6 +130,5 @@ describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :cont }, format: :html expect(response).to be_success - store_frontend_fixture(response, fixture_file_name) end end diff --git a/spec/javascripts/fixtures/merge_requests_diffs.rb b/spec/javascripts/fixtures/merge_requests_diffs.rb index 57462e74bb2..03b9b713fd8 100644 --- a/spec/javascripts/fixtures/merge_requests_diffs.rb +++ b/spec/javascripts/fixtures/merge_requests_diffs.rb @@ -34,29 +34,29 @@ describe Projects::MergeRequests::DiffsController, '(JavaScript fixtures)', type remove_repository(project) end - it 'merge_request_diffs/with_commit.json' do |example| + it 'merge_request_diffs/with_commit.json' do # Create a user that matches the selected commit author # This is so that the "author" information will be populated create(:user, email: selected_commit.author_email, name: selected_commit.author_name) - render_merge_request(example.description, merge_request, commit_id: selected_commit.sha) + render_merge_request(merge_request, commit_id: selected_commit.sha) end - it 'merge_request_diffs/inline_changes_tab_with_comments.json' do |example| + it 'merge_request_diffs/inline_changes_tab_with_comments.json' do create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request) create(:note_on_merge_request, author: admin, project: project, noteable: merge_request) - render_merge_request(example.description, merge_request) + render_merge_request(merge_request) end - it 'merge_request_diffs/parallel_changes_tab_with_comments.json' do |example| + it 'merge_request_diffs/parallel_changes_tab_with_comments.json' do create(:diff_note_on_merge_request, project: project, author: admin, position: position, noteable: merge_request) create(:note_on_merge_request, author: admin, project: project, noteable: merge_request) - render_merge_request(example.description, merge_request, view: 'parallel') + render_merge_request(merge_request, view: 'parallel') end private - def render_merge_request(fixture_file_name, merge_request, view: 'inline', **extra_params) + def render_merge_request(merge_request, view: 'inline', **extra_params) get :show, params: { namespace_id: project.namespace.to_param, project_id: project, @@ -66,6 +66,5 @@ describe Projects::MergeRequests::DiffsController, '(JavaScript fixtures)', type }, format: :json expect(response).to be_success - store_frontend_fixture(response, fixture_file_name) end end diff --git a/spec/javascripts/fixtures/pdf.rb b/spec/javascripts/fixtures/pdf.rb deleted file mode 100644 index ef9976b9fd3..00000000000 --- a/spec/javascripts/fixtures/pdf.rb +++ /dev/null @@ -1,18 +0,0 @@ -require 'spec_helper' - -describe 'PDF file', '(JavaScript fixtures)', type: :controller do - include JavaScriptFixturesHelpers - - let(:namespace) { create(:namespace, name: 'frontend-fixtures' )} - let(:project) { create(:project, :repository, namespace: namespace, path: 'pdf-project') } - - before(:all) do - clean_frontend_fixtures('blob/pdf/') - end - - it 'blob/pdf/test.pdf' do |example| - blob = project.repository.blob_at('e774ebd33', 'files/pdf/test.pdf') - - store_frontend_fixture(blob.data.force_encoding("utf-8"), example.description) - end -end diff --git a/spec/javascripts/fixtures/pipeline_schedules.rb b/spec/javascripts/fixtures/pipeline_schedules.rb index e5176a58273..aecd56e6198 100644 --- a/spec/javascripts/fixtures/pipeline_schedules.rb +++ b/spec/javascripts/fixtures/pipeline_schedules.rb @@ -21,7 +21,7 @@ describe Projects::PipelineSchedulesController, '(JavaScript fixtures)', type: : sign_in(admin) end - it 'pipeline_schedules/edit.html' do |example| + it 'pipeline_schedules/edit.html' do get :edit, params: { namespace_id: project.namespace.to_param, project_id: project, @@ -29,10 +29,9 @@ describe Projects::PipelineSchedulesController, '(JavaScript fixtures)', type: : } expect(response).to be_success - store_frontend_fixture(response, example.description) end - it 'pipeline_schedules/edit_with_variables.html' do |example| + it 'pipeline_schedules/edit_with_variables.html' do get :edit, params: { namespace_id: project.namespace.to_param, project_id: project, @@ -40,6 +39,5 @@ describe Projects::PipelineSchedulesController, '(JavaScript fixtures)', type: : } expect(response).to be_success - store_frontend_fixture(response, example.description) end end diff --git a/spec/javascripts/fixtures/pipelines.rb b/spec/javascripts/fixtures/pipelines.rb index 42b552e81c0..de6fcfe10f4 100644 --- a/spec/javascripts/fixtures/pipelines.rb +++ b/spec/javascripts/fixtures/pipelines.rb @@ -23,13 +23,12 @@ describe Projects::PipelinesController, '(JavaScript fixtures)', type: :controll sign_in(admin) end - it 'pipelines/pipelines.json' do |example| + it 'pipelines/pipelines.json' do get :index, params: { namespace_id: namespace, project_id: project }, format: :json expect(response).to be_success - store_frontend_fixture(response, example.description) end end diff --git a/spec/javascripts/fixtures/projects.rb b/spec/javascripts/fixtures/projects.rb index 446da83a7f9..94c59207898 100644 --- a/spec/javascripts/fixtures/projects.rb +++ b/spec/javascripts/fixtures/projects.rb @@ -28,49 +28,45 @@ describe 'Projects (JavaScript fixtures)', type: :controller do end describe ProjectsController, '(JavaScript fixtures)', type: :controller do - it 'projects/dashboard.html' do |example| + it 'projects/dashboard.html' do get :show, params: { namespace_id: project.namespace.to_param, id: project } expect(response).to be_success - store_frontend_fixture(response, example.description) end - it 'projects/overview.html' do |example| + it 'projects/overview.html' do get :show, params: { namespace_id: project_with_repo.namespace.to_param, id: project_with_repo } expect(response).to be_success - store_frontend_fixture(response, example.description) end - it 'projects/edit.html' do |example| + it 'projects/edit.html' do get :edit, params: { namespace_id: project.namespace.to_param, id: project } expect(response).to be_success - store_frontend_fixture(response, example.description) end end describe Projects::Settings::CiCdController, '(JavaScript fixtures)', type: :controller do - it 'projects/ci_cd_settings.html' do |example| + it 'projects/ci_cd_settings.html' do get :show, params: { namespace_id: project.namespace.to_param, project_id: project } expect(response).to be_success - store_frontend_fixture(response, example.description) end - it 'projects/ci_cd_settings_with_variables.html' do |example| + it 'projects/ci_cd_settings_with_variables.html' do create(:ci_variable, project: project_variable_populated) create(:ci_variable, project: project_variable_populated) @@ -80,7 +76,6 @@ describe 'Projects (JavaScript fixtures)', type: :controller do } expect(response).to be_success - store_frontend_fixture(response, example.description) end end end diff --git a/spec/javascripts/fixtures/prometheus_service.rb b/spec/javascripts/fixtures/prometheus_service.rb index 29dc95305b7..f3171fdd97b 100644 --- a/spec/javascripts/fixtures/prometheus_service.rb +++ b/spec/javascripts/fixtures/prometheus_service.rb @@ -22,7 +22,7 @@ describe Projects::ServicesController, '(JavaScript fixtures)', type: :controlle remove_repository(project) end - it 'services/prometheus/prometheus_service.html' do |example| + it 'services/prometheus/prometheus_service.html' do get :edit, params: { namespace_id: namespace, project_id: project, @@ -30,6 +30,5 @@ describe Projects::ServicesController, '(JavaScript fixtures)', type: :controlle } expect(response).to be_success - store_frontend_fixture(response, example.description) end end diff --git a/spec/javascripts/fixtures/raw.rb b/spec/javascripts/fixtures/raw.rb index 82770beb39b..801c80a0112 100644 --- a/spec/javascripts/fixtures/raw.rb +++ b/spec/javascripts/fixtures/raw.rb @@ -1,34 +1,39 @@ require 'spec_helper' -describe 'Raw files', '(JavaScript fixtures)', type: :controller do +describe 'Raw files', '(JavaScript fixtures)' do include JavaScriptFixturesHelpers let(:namespace) { create(:namespace, name: 'frontend-fixtures' )} let(:project) { create(:project, :repository, namespace: namespace, path: 'raw-project') } + let(:response) { @blob.data.force_encoding('UTF-8') } before(:all) do + clean_frontend_fixtures('blob/balsamiq/') clean_frontend_fixtures('blob/notebook/') + clean_frontend_fixtures('blob/pdf/') end after do remove_repository(project) end - it 'blob/notebook/basic.json' do |example| - blob = project.repository.blob_at('6d85bb69', 'files/ipython/basic.ipynb') - - store_frontend_fixture(blob.data, example.description) + it 'blob/balsamiq/test.bmpr' do + @blob = project.repository.blob_at('b89b56d79', 'files/images/balsamiq.bmpr') end - it 'blob/notebook/worksheets.json' do |example| - blob = project.repository.blob_at('6d85bb69', 'files/ipython/worksheets.ipynb') + it 'blob/notebook/basic.json' do + @blob = project.repository.blob_at('6d85bb69', 'files/ipython/basic.ipynb') + end - store_frontend_fixture(blob.data, example.description) + it 'blob/notebook/worksheets.json' do + @blob = project.repository.blob_at('6d85bb69', 'files/ipython/worksheets.ipynb') end - it 'blob/notebook/math.json' do |example| - blob = project.repository.blob_at('93ee732', 'files/ipython/math.ipynb') + it 'blob/notebook/math.json' do + @blob = project.repository.blob_at('93ee732', 'files/ipython/math.ipynb') + end - store_frontend_fixture(blob.data, example.description) + it 'blob/pdf/test.pdf' do + @blob = project.repository.blob_at('e774ebd33', 'files/pdf/test.pdf') end end diff --git a/spec/javascripts/fixtures/search.rb b/spec/javascripts/fixtures/search.rb index 5f5b4d4e60d..22fc546d761 100644 --- a/spec/javascripts/fixtures/search.rb +++ b/spec/javascripts/fixtures/search.rb @@ -9,10 +9,9 @@ describe SearchController, '(JavaScript fixtures)', type: :controller do clean_frontend_fixtures('search/') end - it 'search/show.html' do |example| + it 'search/show.html' do get :show expect(response).to be_success - store_frontend_fixture(response, example.description) end end diff --git a/spec/javascripts/fixtures/services.rb b/spec/javascripts/fixtures/services.rb index dc7ee484c22..2237702ccca 100644 --- a/spec/javascripts/fixtures/services.rb +++ b/spec/javascripts/fixtures/services.rb @@ -22,7 +22,7 @@ describe Projects::ServicesController, '(JavaScript fixtures)', type: :controlle remove_repository(project) end - it 'services/edit_service.html' do |example| + it 'services/edit_service.html' do get :edit, params: { namespace_id: namespace, project_id: project, @@ -30,6 +30,5 @@ describe Projects::ServicesController, '(JavaScript fixtures)', type: :controlle } expect(response).to be_success - store_frontend_fixture(response, example.description) end end diff --git a/spec/javascripts/fixtures/sessions.rb b/spec/javascripts/fixtures/sessions.rb index 8656dea696a..92b74c01c89 100644 --- a/spec/javascripts/fixtures/sessions.rb +++ b/spec/javascripts/fixtures/sessions.rb @@ -16,11 +16,10 @@ describe 'Sessions (JavaScript fixtures)' do set_devise_mapping(context: @request) end - it 'sessions/new.html' do |example| + it 'sessions/new.html' do get :new expect(response).to be_success - store_frontend_fixture(response, example.description) end end end diff --git a/spec/javascripts/fixtures/snippet.rb b/spec/javascripts/fixtures/snippet.rb index ebc5b793166..ace84b14eb7 100644 --- a/spec/javascripts/fixtures/snippet.rb +++ b/spec/javascripts/fixtures/snippet.rb @@ -23,12 +23,11 @@ describe SnippetsController, '(JavaScript fixtures)', type: :controller do remove_repository(project) end - it 'snippets/show.html' do |example| + it 'snippets/show.html' do create(:discussion_note_on_snippet, noteable: snippet, project: project, author: admin, note: '- [ ] Task List Item') get(:show, params: { id: snippet.to_param }) expect(response).to be_success - store_frontend_fixture(response, example.description) end end diff --git a/spec/javascripts/fixtures/todos.rb b/spec/javascripts/fixtures/todos.rb index 6e37a2e5a4c..d0c8a6eca01 100644 --- a/spec/javascripts/fixtures/todos.rb +++ b/spec/javascripts/fixtures/todos.rb @@ -26,11 +26,10 @@ describe 'Todos (JavaScript fixtures)' do sign_in(admin) end - it 'todos/todos.html' do |example| + it 'todos/todos.html' do get :index expect(response).to be_success - store_frontend_fixture(response, example.description) end end @@ -41,7 +40,7 @@ describe 'Todos (JavaScript fixtures)' do sign_in(admin) end - it 'todos/todos.json' do |example| + it 'todos/todos.json' do post :create, params: { namespace_id: namespace, project_id: project, @@ -50,7 +49,6 @@ describe 'Todos (JavaScript fixtures)' do }, format: 'json' expect(response).to be_success - store_frontend_fixture(response, example.description) end end end diff --git a/spec/javascripts/fixtures/u2f.rb b/spec/javascripts/fixtures/u2f.rb index 15866d65a4f..f52832b6efb 100644 --- a/spec/javascripts/fixtures/u2f.rb +++ b/spec/javascripts/fixtures/u2f.rb @@ -18,13 +18,12 @@ context 'U2F' do set_devise_mapping(context: @request) end - it 'u2f/authenticate.html' do |example| + it 'u2f/authenticate.html' do allow(controller).to receive(:find_user).and_return(user) post :create, params: { user: { login: user.username, password: user.password } } expect(response).to be_success - store_frontend_fixture(response, example.description) end end @@ -36,11 +35,10 @@ context 'U2F' do allow_any_instance_of(Profiles::TwoFactorAuthsController).to receive(:build_qr_code).and_return('qrcode:blackandwhitesquares') end - it 'u2f/register.html' do |example| + it 'u2f/register.html' do get :show expect(response).to be_success - store_frontend_fixture(response, example.description) end end end diff --git a/spec/lib/gitlab/bitbucket_import/importer_spec.rb b/spec/lib/gitlab/bitbucket_import/importer_spec.rb index e1a2bae5fe8..a02c00e3340 100644 --- a/spec/lib/gitlab/bitbucket_import/importer_spec.rb +++ b/spec/lib/gitlab/bitbucket_import/importer_spec.rb @@ -222,6 +222,46 @@ describe Gitlab::BitbucketImport::Importer do body: {}.to_json) end + context 'creating labels on project' do + before do + allow(importer).to receive(:import_wiki) + end + + it 'creates labels as expected' do + expect { importer.execute }.to change { Label.count }.from(0).to(Gitlab::BitbucketImport::Importer::LABELS.size) + end + + it 'does not fail if label is already existing' do + label = Gitlab::BitbucketImport::Importer::LABELS.first + ::Labels::CreateService.new(label).execute(project: project) + + expect { importer.execute }.not_to raise_error + end + + it 'does not create new labels' do + Gitlab::BitbucketImport::Importer::LABELS.each do |label| + create(:label, project: project, title: label[:title]) + end + + expect { importer.execute }.not_to change { Label.count } + end + + it 'does not update existing ones' do + label_title = Gitlab::BitbucketImport::Importer::LABELS.first[:title] + existing_label = create(:label, project: project, title: label_title) + # Reload label from database so we avoid timestamp comparison issues related to time precision when comparing + # attributes later. + existing_label.reload + + Timecop.freeze(Time.now + 1.minute) do + importer.execute + + label_after_import = project.labels.find(existing_label.id) + expect(label_after_import.attributes).to eq(existing_label.attributes) + end + end + end + it 'maps statuses to open or closed' do allow(importer).to receive(:import_wiki) diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb index 4e910e67ac2..aa975c8bb0b 100644 --- a/spec/lib/gitlab/usage_data_spec.rb +++ b/spec/lib/gitlab/usage_data_spec.rb @@ -35,7 +35,7 @@ describe Gitlab::UsageData do subject { described_class.data } it "gathers usage data" do - expect(subject.keys).to match_array(%i( + expect(subject.keys).to include(*%i( active_user_count counts recorded_at @@ -68,7 +68,7 @@ describe Gitlab::UsageData do expect(count_data[:boards]).to eq(1) expect(count_data[:projects]).to eq(3) - expect(count_data.keys).to match_array(%i( + expect(count_data.keys).to include(*%i( assignee_lists boards ci_builds diff --git a/spec/models/project_services/jira_service_spec.rb b/spec/models/project_services/jira_service_spec.rb index 4a7eee1fbf3..04ae9390436 100644 --- a/spec/models/project_services/jira_service_spec.rb +++ b/spec/models/project_services/jira_service_spec.rb @@ -166,6 +166,13 @@ describe JiraService do ).once end + it 'does not fail if remote_link.all on issue returns nil' do + allow(JIRA::Resource::Remotelink).to receive(:all).and_return(nil) + + expect { @jira_service.close_issue(resource, ExternalIssue.new('JIRA-123', project)) } + .not_to raise_error(NoMethodError) + end + # Check https://developer.atlassian.com/jiradev/jira-platform/guides/other/guide-jira-remote-issue-links/fields-in-remote-issue-links # for more information it 'creates Remote Link reference in JIRA for comment' do diff --git a/spec/services/members/create_service_spec.rb b/spec/services/members/create_service_spec.rb index 2c4fb131ed9..674fe0f666e 100644 --- a/spec/services/members/create_service_spec.rb +++ b/spec/services/members/create_service_spec.rb @@ -44,7 +44,18 @@ describe Members::CreateService do result = described_class.new(user, params).execute(project) expect(result[:status]).to eq(:error) - expect(result[:message]).to include(project_user.username) + expect(result[:message]).to include("#{project_user.username}: Access level is not included in the list") expect(project.users).not_to include project_user end + + it 'does not add a member with an existing invite' do + invited_member = create(:project_member, :invited, project: project) + + params = { user_ids: invited_member.invite_email, + access_level: Gitlab::Access::GUEST } + result = described_class.new(user, params).execute(project) + + expect(result[:status]).to eq(:error) + expect(result[:message]).to eq('Invite email has already been taken') + end end diff --git a/spec/services/projects/after_import_service_spec.rb b/spec/services/projects/after_import_service_spec.rb index 95c11f71c5e..51d3fd18881 100644 --- a/spec/services/projects/after_import_service_spec.rb +++ b/spec/services/projects/after_import_service_spec.rb @@ -15,7 +15,7 @@ describe Projects::AfterImportService do describe '#execute' do before do allow(Projects::HousekeepingService) - .to receive(:new).with(project, :gc).and_return(housekeeping_service) + .to receive(:new).with(project).and_return(housekeeping_service) allow(housekeeping_service) .to receive(:execute).and_yield diff --git a/spec/services/projects/detect_repository_languages_service_spec.rb b/spec/services/projects/detect_repository_languages_service_spec.rb index e3e561c971c..df5eed18ac0 100644 --- a/spec/services/projects/detect_repository_languages_service_spec.rb +++ b/spec/services/projects/detect_repository_languages_service_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' describe Projects::DetectRepositoryLanguagesService, :clean_gitlab_redis_shared_state do set(:project) { create(:project, :repository) } - subject { described_class.new(project, project.owner) } + subject { described_class.new(project) } describe '#execute' do context 'without previous detection' do diff --git a/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb index d8427d0bf78..80debcd3a7a 100644 --- a/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb +++ b/spec/services/projects/lfs_pointers/lfs_download_link_list_service_spec.rb @@ -33,7 +33,10 @@ describe Projects::LfsPointers::LfsDownloadLinkListService do before do allow(project).to receive(:lfs_enabled?).and_return(true) - allow(Gitlab::HTTP).to receive(:post).and_return(objects_response) + response = instance_double(HTTParty::Response) + allow(response).to receive(:body).and_return(objects_response.to_json) + allow(response).to receive(:success?).and_return(true) + allow(Gitlab::HTTP).to receive(:post).and_return(response) end describe '#execute' do @@ -89,6 +92,21 @@ describe Projects::LfsPointers::LfsDownloadLinkListService do expect { subject.send(:get_download_links, new_oids) }.to raise_error(described_class::DownloadLinksError) end + + shared_examples 'JSON parse errors' do |body| + it 'raises error' do + response = instance_double(HTTParty::Response) + allow(response).to receive(:body).and_return(body) + allow(response).to receive(:success?).and_return(true) + allow(Gitlab::HTTP).to receive(:post).and_return(response) + + expect { subject.send(:get_download_links, new_oids) }.to raise_error(described_class::DownloadLinksError) + end + end + + it_behaves_like 'JSON parse errors', '{' + it_behaves_like 'JSON parse errors', '{}' + it_behaves_like 'JSON parse errors', '{ foo: 123 }' end describe '#parse_response_links' do diff --git a/spec/services/projects/repository_languages_service_spec.rb b/spec/services/projects/repository_languages_service_spec.rb index 09c61363ad2..46c5095327d 100644 --- a/spec/services/projects/repository_languages_service_spec.rb +++ b/spec/services/projects/repository_languages_service_spec.rb @@ -10,7 +10,7 @@ describe Projects::RepositoryLanguagesService do context 'when a project is without detected programming languages' do it 'schedules a worker and returns the empty result' do - expect(::DetectRepositoryLanguagesWorker).to receive(:perform_async).with(project.id, project.owner.id) + expect(::DetectRepositoryLanguagesWorker).to receive(:perform_async).with(project.id) expect(service.execute).to eq([]) end end @@ -19,7 +19,7 @@ describe Projects::RepositoryLanguagesService do let!(:repository_language) { create(:repository_language, project: project) } it 'does not schedule a worker and returns the detected languages' do - expect(::DetectRepositoryLanguagesWorker).not_to receive(:perform_async).with(project.id, project.owner.id) + expect(::DetectRepositoryLanguagesWorker).not_to receive(:perform_async).with(project.id) languages = service.execute diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9266bee34d6..69589c9aa33 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -138,7 +138,7 @@ RSpec.configure do |config| .and_return(false) end - config.before(:example, :quarantine) do + config.around(:example, :quarantine) do # Skip tests in quarantine unless we explicitly focus on them. skip('In quarantine') unless config.inclusion_filter[:quarantine] end diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb index f15944652fd..44ed9da25fc 100644 --- a/spec/support/helpers/graphql_helpers.rb +++ b/spec/support/helpers/graphql_helpers.rb @@ -197,3 +197,7 @@ module GraphqlHelpers allow(GitlabSchema).to receive(:max_query_depth).with(any_args).and_return nil end end + +# This warms our schema, doing this as part of loading the helpers to avoid +# duplicate loading error when Rails tries autoload the types. +GitlabSchema.graphql_definition diff --git a/spec/support/helpers/javascript_fixtures_helpers.rb b/spec/support/helpers/javascript_fixtures_helpers.rb index 494398dc4de..cdd7724cc13 100644 --- a/spec/support/helpers/javascript_fixtures_helpers.rb +++ b/spec/support/helpers/javascript_fixtures_helpers.rb @@ -11,6 +11,10 @@ module JavaScriptFixturesHelpers base.around do |example| # pick an arbitrary date from the past, so tests are not time dependent Timecop.freeze(Time.utc(2015, 7, 3, 10)) { example.run } + + raise NoMethodError.new('You need to set `response` for the fixture generator! This will automatically happen with `type: :controller` or `type: :request`.', 'response') unless respond_to?(:response) + + store_frontend_fixture(response, example.description) end end @@ -29,7 +33,13 @@ module JavaScriptFixturesHelpers end end - # Public: Store a response object as fixture file + def remove_repository(project) + Gitlab::Shell.new.remove_repository(project.repository_storage, project.disk_path) + end + + private + + # Private: Store a response object as fixture file # # response - string or response object to store # fixture_file_name - file name to store the fixture in (relative to .fixture_root_path) @@ -42,12 +52,6 @@ module JavaScriptFixturesHelpers File.write(full_fixture_path, fixture) end - def remove_repository(project) - Gitlab::Shell.new.remove_repository(project.repository_storage, project.disk_path) - end - - private - # Private: Prepare a response object for use as a frontend fixture # # response - response object to prepare diff --git a/spec/support/helpers/project_forks_helper.rb b/spec/support/helpers/project_forks_helper.rb index 9a86560da2a..bcb11a09b36 100644 --- a/spec/support/helpers/project_forks_helper.rb +++ b/spec/support/helpers/project_forks_helper.rb @@ -1,5 +1,11 @@ module ProjectForksHelper def fork_project(project, user = nil, params = {}) + Gitlab::GitalyClient.allow_n_plus_1_calls do + fork_project_direct(project, user, params) + end + end + + def fork_project_direct(project, user = nil, params = {}) # Load the `fork_network` for the project to fork as there might be one that # wasn't loaded yet. project.reload unless project.fork_network @@ -44,11 +50,16 @@ module ProjectForksHelper end def fork_project_with_submodules(project, user = nil, params = {}) - forked_project = fork_project(project, user, params) - TestEnv.copy_repo(forked_project, - bare_repo: TestEnv.forked_repo_path_bare, - refs: TestEnv::FORKED_BRANCH_SHA) - forked_project.repository.after_import - forked_project + Gitlab::GitalyClient.allow_n_plus_1_calls do + forked_project = fork_project_direct(project, user, params) + TestEnv.copy_repo( + forked_project, + bare_repo: TestEnv.forked_repo_path_bare, + refs: TestEnv::FORKED_BRANCH_SHA + ) + forked_project.repository.after_import + + forked_project + end end end diff --git a/spec/workers/detect_repository_languages_worker_spec.rb b/spec/workers/detect_repository_languages_worker_spec.rb index dbf32555985..755eb8dbf6b 100644 --- a/spec/workers/detect_repository_languages_worker_spec.rb +++ b/spec/workers/detect_repository_languages_worker_spec.rb @@ -4,7 +4,6 @@ require 'spec_helper' describe DetectRepositoryLanguagesWorker do set(:project) { create(:project) } - let(:user) { project.owner } subject { described_class.new } @@ -14,19 +13,13 @@ describe DetectRepositoryLanguagesWorker do allow(::Projects::DetectRepositoryLanguagesService).to receive(:new).and_return(service) expect(service).to receive(:execute) - subject.perform(project.id, user.id) + subject.perform(project.id) end context 'when invalid ids are used' do it 'does not raise when the project could not be found' do expect do - subject.perform(-1, user.id) - end.not_to raise_error - end - - it 'does not raise when the user could not be found' do - expect do - subject.perform(project.id, -1) + subject.perform(-1) end.not_to raise_error end end |