Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md38
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--Gemfile16
-rw-r--r--Gemfile.lock126
-rw-r--r--app/assets/javascripts/boards/components/issue_due_date.vue9
-rw-r--r--app/assets/javascripts/diffs/components/compare_versions_dropdown.vue2
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js17
-rw-r--r--app/assets/javascripts/notes/components/discussion_filter.vue20
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue2
-rw-r--r--app/assets/javascripts/notes/components/toggle_replies_widget.vue8
-rw-r--r--app/assets/javascripts/notes/constants.js1
-rw-r--r--app/assets/javascripts/pages/users/user_overview_block.js15
-rw-r--r--app/assets/stylesheets/bootstrap_migration.scss15
-rw-r--r--app/assets/stylesheets/framework/issue_box.scss5
-rw-r--r--app/assets/stylesheets/framework/modal.scss4
-rw-r--r--app/assets/stylesheets/pages/milestone.scss3
-rw-r--r--app/controllers/admin/application_settings_controller.rb2
-rw-r--r--app/controllers/application_controller.rb2
-rw-r--r--app/controllers/groups/milestones_controller.rb21
-rw-r--r--app/controllers/groups/settings/ci_cd_controller.rb6
-rw-r--r--app/controllers/projects/snippets_controller.rb9
-rw-r--r--app/controllers/projects_controller.rb1
-rw-r--r--app/controllers/sherlock/transactions_controller.rb2
-rw-r--r--app/controllers/snippets_controller.rb8
-rw-r--r--app/helpers/milestones_helper.rb15
-rw-r--r--app/helpers/snippets_helper.rb8
-rw-r--r--app/helpers/sorting_helper.rb2
-rw-r--r--app/models/ci/build.rb9
-rw-r--r--app/models/ci/pipeline.rb13
-rw-r--r--app/models/clusters/applications/ingress.rb2
-rw-r--r--app/models/clusters/applications/knative.rb2
-rw-r--r--app/models/clusters/applications/runner.rb2
-rw-r--r--app/models/concerns/has_ref.rb17
-rw-r--r--app/models/concerns/milestoneish.rb2
-rw-r--r--app/models/dashboard_group_milestone.rb20
-rw-r--r--app/models/dashboard_milestone.rb10
-rw-r--r--app/models/global_milestone.rb116
-rw-r--r--app/models/group_milestone.rb29
-rw-r--r--app/models/merge_request.rb2
-rw-r--r--app/models/milestone.rb6
-rw-r--r--app/models/project.rb26
-rw-r--r--app/models/project_services/kubernetes_service.rb2
-rw-r--r--app/models/remote_mirror.rb2
-rw-r--r--app/models/repository.rb13
-rw-r--r--app/models/snippet.rb6
-rw-r--r--app/models/todo.rb5
-rw-r--r--app/policies/issuable_policy.rb2
-rw-r--r--app/services/ci/create_pipeline_service.rb3
-rw-r--r--app/services/git_push_service.rb3
-rw-r--r--app/services/git_tag_push_service.rb3
-rw-r--r--app/services/groups/update_service.rb2
-rw-r--r--app/services/issues/update_service.rb2
-rw-r--r--app/services/members/base_service.rb6
-rw-r--r--app/services/members/destroy_service.rb8
-rw-r--r--app/services/members/update_service.rb9
-rw-r--r--app/services/merge_requests/build_service.rb24
-rw-r--r--app/services/merge_requests/update_service.rb6
-rw-r--r--app/services/notification_service.rb2
-rw-r--r--app/services/projects/lfs_pointers/lfs_download_service.rb35
-rw-r--r--app/services/projects/update_service.rb4
-rw-r--r--app/views/dashboard/milestones/_milestone.html.haml2
-rw-r--r--app/views/events/_events.html.haml5
-rw-r--r--app/views/projects/services/prometheus/_metrics.html.haml2
-rw-r--r--app/views/projects/services/prometheus/_show.html.haml2
-rw-r--r--app/views/shared/milestones/_milestone.html.haml14
-rw-r--r--app/views/shared/milestones/_top.html.haml11
-rw-r--r--app/views/shared/snippets/_header.html.haml2
-rw-r--r--app/views/users/show.html.haml2
-rw-r--r--app/workers/mail_scheduler/notification_service_worker.rb23
-rw-r--r--app/workers/post_receive.rb20
-rw-r--r--changelogs/unreleased/18667-handle-push-opts.yml5
-rw-r--r--changelogs/unreleased/51668-fix-line-numbers.yml5
-rw-r--r--changelogs/unreleased/54206-show-the-activity-filter-dropdown-in-discussion-tab-only.yml5
-rw-r--r--changelogs/unreleased/54427-label-xss.yml5
-rw-r--r--changelogs/unreleased/54844-report-syntax-dep-scan-ado.yml5
-rw-r--r--changelogs/unreleased/54953-fix-commit_email_hostname-accessor-in-fake_application_settings.yml5
-rw-r--r--changelogs/unreleased/55103-hide-group-cluster-features.yml5
-rw-r--r--changelogs/unreleased/55266-fix-incorrect-due-date-parsing.yml5
-rw-r--r--changelogs/unreleased/55369-update-milestone-sort-to-say-say-milestone-due-date.yml5
-rw-r--r--changelogs/unreleased/55755-user-activity-is-stuck-loading-when-there-is-none.yml5
-rw-r--r--changelogs/unreleased/55836-docs-fix-navigation-style-in-docs.yml5
-rw-r--r--changelogs/unreleased/55838-remove-gem-install-bundler-from-docker-based-ruby-environments.yml5
-rw-r--r--changelogs/unreleased/55883-modal-header-titles-have-an-unnecessary-top-margin.yml5
-rw-r--r--changelogs/unreleased/allow-basic-auth-on-go-get-middleware.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-bump-rails-cve-2018-16476.yml5
-rw-r--r--changelogs/unreleased/ccr-49289_milestone_link.yml5
-rw-r--r--changelogs/unreleased/deprecated-insert-sql.yml5
-rw-r--r--changelogs/unreleased/deprecated-positional-spec-arguments.yml5
-rw-r--r--changelogs/unreleased/deprecated-redirect-back.yml5
-rw-r--r--changelogs/unreleased/fj-55781-fix-api-blob-content-disposition.yml5
-rw-r--r--changelogs/unreleased/markdown-toolbar-btn-fix.yml5
-rw-r--r--changelogs/unreleased/s3-directories-get.yml6
-rw-r--r--changelogs/unreleased/security-48259-private-snippet.yml5
-rw-r--r--changelogs/unreleased/security-53543-user-keeps-access-to-mr-issue-when-removed-from-team.yml5
-rw-r--r--changelogs/unreleased/security-54377-label-milestone-name-xss.yml5
-rw-r--r--changelogs/unreleased/security-bvl-fix-cross-project-mr-exposure.yml5
-rw-r--r--changelogs/unreleased/security-fix-ssrf-import-url-remote-mirror.yml5
-rw-r--r--changelogs/unreleased/security-master-group-cicd-settings-accessible-to-maintainer.yml5
-rw-r--r--changelogs/unreleased/security-master-guests-jobs-api.yml5
-rw-r--r--changelogs/unreleased/security-master-secret-ci-variables-exposed.yml5
-rw-r--r--changelogs/unreleased/security-master-url-rel.yml5
-rw-r--r--changelogs/unreleased/security-refs-available-to-project-guest.yml5
-rw-r--r--changelogs/unreleased/security-todos_not_redacted_for_guests.yml5
-rw-r--r--changelogs/unreleased/sh-bump-omniauth-google-gem.yml5
-rw-r--r--changelogs/unreleased/sh-drop-webhooks-project-export.yml5
-rw-r--r--changelogs/unreleased/sh-fix-clone-geo-dropdown.yml5
-rw-r--r--changelogs/unreleased/sh-fix-http-clone-panel.yml5
-rw-r--r--changelogs/unreleased/sh-fix-issue-55822.yml5
-rw-r--r--changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-1-43.yml5
-rw-r--r--db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb2
-rw-r--r--doc/administration/job_artifacts.md12
-rw-r--r--doc/administration/monitoring/performance/request_profiling.md4
-rw-r--r--doc/api/lint.md2
-rw-r--r--doc/api/services.md2
-rw-r--r--doc/api/templates/gitlab_ci_ymls.md2
-rw-r--r--doc/ci/caching/index.md1
-rw-r--r--doc/ci/docker/using_kaniko.md23
-rw-r--r--doc/ci/examples/test-and-deploy-python-application-to-heroku.md2
-rw-r--r--doc/ci/quick_start/README.md2
-rw-r--r--doc/ci/services/mysql.md4
-rw-r--r--doc/ci/yaml/README.md9
-rw-r--r--doc/install/installation.md2
-rw-r--r--doc/install/openshift_and_gitlab/index.md4
-rw-r--r--doc/integration/google.md1
-rw-r--r--doc/topics/authentication/index.md2
-rw-r--r--doc/topics/autodevops/index.md6
-rw-r--r--doc/update/10.0-to-10.1.md2
-rw-r--r--doc/update/10.1-to-10.2.md2
-rw-r--r--doc/update/10.2-to-10.3.md2
-rw-r--r--doc/update/10.3-to-10.4.md2
-rw-r--r--doc/update/10.4-to-10.5.md2
-rw-r--r--doc/update/10.5-to-10.6.md2
-rw-r--r--doc/update/10.6-to-10.7.md2
-rw-r--r--doc/update/10.7-to-10.8.md2
-rw-r--r--doc/update/10.8-to-11.0.md2
-rw-r--r--doc/update/11.0-to-11.1.md2
-rw-r--r--doc/update/11.1-to-11.2.md2
-rw-r--r--doc/update/11.2-to-11.3.md2
-rw-r--r--doc/update/11.3-to-11.4.md2
-rw-r--r--doc/update/11.4-to-11.5.md2
-rw-r--r--doc/update/11.5-to-11.6.md2
-rw-r--r--doc/update/6.9-to-7.0.md2
-rw-r--r--doc/update/6.x-or-7.x-to-7.14.md2
-rw-r--r--doc/update/7.0-to-7.1.md2
-rw-r--r--doc/update/8.10-to-8.11.md2
-rw-r--r--doc/update/8.11-to-8.12.md2
-rw-r--r--doc/update/8.12-to-8.13.md2
-rw-r--r--doc/update/8.13-to-8.14.md2
-rw-r--r--doc/update/8.14-to-8.15.md2
-rw-r--r--doc/update/8.15-to-8.16.md2
-rw-r--r--doc/update/8.16-to-8.17.md2
-rw-r--r--doc/update/8.17-to-9.0.md2
-rw-r--r--doc/update/9.0-to-9.1.md2
-rw-r--r--doc/update/9.1-to-9.2.md2
-rw-r--r--doc/update/9.2-to-9.3.md2
-rw-r--r--doc/update/9.3-to-9.4.md2
-rw-r--r--doc/update/9.4-to-9.5.md2
-rw-r--r--doc/update/9.5-to-10.0.md2
-rw-r--r--doc/user/project/clusters/index.md2
-rw-r--r--doc/user/project/integrations/prometheus.md4
-rw-r--r--doc/user/project/settings/import_export.md1
-rw-r--r--doc/workflow/todos.md3
-rw-r--r--lib/api/internal.rb3
-rw-r--r--lib/api/jobs.rb5
-rw-r--r--lib/backup/manager.rb2
-rw-r--r--lib/banzai/filter/external_link_filter.rb12
-rw-r--r--lib/banzai/filter/label_reference_filter.rb6
-rw-r--r--lib/gitlab/ci/pipeline/chain/command.rb10
-rw-r--r--lib/gitlab/ci/pipeline/chain/skip.rb7
-rw-r--r--lib/gitlab/ci/pipeline/chain/validate/repository.rb4
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml3
-rw-r--r--lib/gitlab/ci/templates/Ruby.gitlab-ci.yml1
-rw-r--r--lib/gitlab/cleanup/remote_uploads.rb2
-rw-r--r--lib/gitlab/data_builder/push.rb13
-rw-r--r--lib/gitlab/git.rb4
-rw-r--r--lib/gitlab/git_post_receive.rb5
-rw-r--r--lib/gitlab/import_export/import_export.yml7
-rw-r--r--lib/gitlab/middleware/go.rb21
-rw-r--r--lib/json_web_token/hmac_token.rb2
-rw-r--r--lib/json_web_token/rsa_token.rb3
-rw-r--r--locale/gitlab.pot5
-rw-r--r--qa/Dockerfile2
-rw-r--r--qa/Gemfile3
-rw-r--r--qa/Gemfile.lock13
-rw-r--r--qa/qa.rb1
-rw-r--r--qa/qa/page/component/note.rb51
-rw-r--r--qa/qa/page/merge_request/show.rb27
-rw-r--r--qa/qa/page/project/issue/show.rb1
-rw-r--r--qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb37
-rw-r--r--qa/qa/support/page/logging.rb7
-rw-r--r--qa/spec/page/logging_spec.rb9
-rw-r--r--spec/controllers/dashboard/milestones_controller_spec.rb2
-rw-r--r--spec/controllers/groups/milestones_controller_spec.rb2
-rw-r--r--spec/controllers/groups/settings/ci_cd_controller_spec.rb55
-rw-r--r--spec/controllers/projects/ci/lints_controller_spec.rb1
-rw-r--r--spec/controllers/projects/merge_requests_controller_spec.rb8
-rw-r--r--spec/controllers/projects/snippets_controller_spec.rb40
-rw-r--r--spec/controllers/projects_controller_spec.rb24
-rw-r--r--spec/controllers/snippets_controller_spec.rb19
-rw-r--r--spec/features/group_variables_spec.rb2
-rw-r--r--spec/features/groups/milestone_spec.rb5
-rw-r--r--spec/features/groups/milestones_sorting_spec.rb1
-rw-r--r--spec/features/issues/gfm_autocomplete_spec.rb44
-rw-r--r--spec/features/merge_request/user_sees_versions_spec.rb11
-rw-r--r--spec/features/merge_request/user_tries_to_access_private_repository_through_new_mr_spec.rb37
-rw-r--r--spec/features/runners_spec.rb3
-rw-r--r--spec/features/users/overview_spec.rb3
-rw-r--r--spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml1
-rw-r--r--spec/javascripts/notes/components/discussion_filter_spec.js36
-rw-r--r--spec/lib/banzai/filter/external_link_filter_spec.rb8
-rw-r--r--spec/lib/banzai/filter/label_reference_filter_spec.rb18
-rw-r--r--spec/lib/gitlab/ci/config/external/file/local_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/config/external/file/remote_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/config/external/processor_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/command_spec.rb20
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb21
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/build_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb3
-rw-r--r--spec/lib/gitlab/cleanup/remote_uploads_spec.rb2
-rw-r--r--spec/lib/gitlab/middleware/go_spec.rb43
-rw-r--r--spec/lib/json_web_token/rsa_token_spec.rb4
-rw-r--r--spec/models/ci/build_spec.rb12
-rw-r--r--spec/models/ci/pipeline_spec.rb4
-rw-r--r--spec/models/clusters/applications/runner_spec.rb6
-rw-r--r--spec/models/concerns/has_ref_spec.rb59
-rw-r--r--spec/models/event_spec.rb18
-rw-r--r--spec/models/global_milestone_spec.rb119
-rw-r--r--spec/models/group_milestone_spec.rb27
-rw-r--r--spec/models/project_spec.rb138
-rw-r--r--spec/models/remote_mirror_spec.rb14
-rw-r--r--spec/models/repository_spec.rb61
-rw-r--r--spec/models/snippet_spec.rb37
-rw-r--r--spec/policies/issuable_policy_spec.rb27
-rw-r--r--spec/requests/api/internal_spec.rb10
-rw-r--r--spec/requests/api/jobs_spec.rb32
-rw-r--r--spec/requests/api/runner_spec.rb2
-rw-r--r--spec/requests/lfs_http_spec.rb2
-rw-r--r--spec/services/auth/container_registry_authentication_service_spec.rb2
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb34
-rw-r--r--spec/services/groups/update_service_spec.rb2
-rw-r--r--spec/services/issuable/bulk_update_service_spec.rb27
-rw-r--r--spec/services/issues/update_service_spec.rb2
-rw-r--r--spec/services/members/destroy_service_spec.rb2
-rw-r--r--spec/services/members/update_service_spec.rb17
-rw-r--r--spec/services/merge_requests/build_service_spec.rb55
-rw-r--r--spec/services/projects/lfs_pointers/lfs_download_service_spec.rb59
-rw-r--r--spec/services/projects/update_service_spec.rb4
-rw-r--r--spec/services/todo_service_spec.rb1
-rw-r--r--spec/support/gitlab_stubs/gitlab_ci.yml3
-rw-r--r--spec/uploaders/file_uploader_spec.rb2
-rw-r--r--spec/uploaders/object_storage_spec.rb2
-rw-r--r--spec/workers/mail_scheduler/notification_service_worker_spec.rb17
254 files changed, 2013 insertions, 658 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b4fa22ad70e..56ac809b548 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,44 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 11.6.2 (2019-01-02)
+
+### Fixed (7 changes)
+
+- Hide cluster features that don't work yet with Group Clusters. !23935
+- Fix a 500 error that could occur until all migrations are done. !23939
+- Fix missing Git clone button when protocol restriction setting enabled. !24015
+- Fix clone dropdown parent inheritance issues in HAML. !24029
+- Fix content-disposition in blobs and files API endpoint. !24078
+- Fixed markdown toolbar buttons.
+- Adjust line-height of blame view line numbers.
+
+
+## 11.6.1 (2018-12-28)
+
+### Security (15 changes)
+
+- Escape label and milestone titles to prevent XSS in GFM autocomplete. !2740
+- Prevent private snippets from being embeddable.
+- Add subresources removal to member destroy service.
+- Escape html entities in LabelReferenceFilter when no label found.
+- Allow changing group CI/CD settings only for owners.
+- Authorize before reading job information via API.
+- Prevent leaking protected variables for ambiguous refs.
+- Ensure that build token is only used when running.
+- Issuable no longer is visible to users when project can't be viewed.
+- Don't expose cross project repositories through diffs when creating merge reqeusts.
+- Fix SSRF with import_url and remote mirror url.
+- Fix persistent symlink in project import.
+- Set URL rel attribute for broken URLs.
+- Project guests no longer are able to see refs page.
+- Delete confidential todos for user when downgraded to Guest.
+
+### Other (1 change)
+
+- Fix due date test. !23845
+
+
## 11.6.0 (2018-12-22)
### Security (24 changes, 1 of them is from the community)
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index 016dac34bf9..917d38ec9f9 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-8.4.3
+8.4.4
diff --git a/Gemfile b/Gemfile
index e2ba0477353..8d5fd8bbbcb 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,6 +1,6 @@
source 'https://rubygems.org'
-gem 'rails', '5.0.7'
+gem 'rails', '5.0.7.1'
gem 'rails-deprecated_sanitizer', '~> 1.0.3'
# Improves copy-on-write performance for MRI
@@ -34,7 +34,7 @@ gem 'omniauth-cas3', '~> 1.1.4'
gem 'omniauth-facebook', '~> 4.0.0'
gem 'omniauth-github', '~> 1.3'
gem 'omniauth-gitlab', '~> 1.0.2'
-gem 'omniauth-google-oauth2', '~> 0.5.3'
+gem 'omniauth-google-oauth2', '~> 0.6.0'
gem 'omniauth-kerberos', '~> 0.3.0', group: :kerberos
gem 'omniauth-oauth2-generic', '~> 0.2.2'
gem 'omniauth-saml', '~> 1.10'
@@ -43,7 +43,7 @@ gem 'omniauth-twitter', '~> 1.4'
gem 'omniauth_crowd', '~> 2.2.0'
gem 'omniauth-authentiq', '~> 0.3.3'
gem 'rack-oauth2', '~> 1.2.1'
-gem 'jwt', '~> 1.5.6'
+gem 'jwt', '~> 2.1.0'
# Spam and anti-bot protection
gem 'recaptcha', '~> 3.0', require: 'recaptcha/rails'
@@ -127,7 +127,7 @@ gem 'asciidoctor-plantuml', '0.0.8'
gem 'rouge', '~> 3.1'
gem 'truncato', '~> 0.7.9'
gem 'bootstrap_form', '~> 2.7.0'
-gem 'nokogiri', '~> 1.8.4'
+gem 'nokogiri', '~> 1.8.5'
gem 'escape_utils', '~> 1.1'
# Calendar rendering
@@ -322,7 +322,7 @@ end
group :development, :test do
gem 'bootsnap', '~> 1.3'
gem 'bullet', '~> 5.5.0', require: !!ENV['ENABLE_BULLET']
- gem 'pry-byebug', '~> 3.4.1', platform: :mri
+ gem 'pry-byebug', '~> 3.5.1', platform: :mri
gem 'pry-rails', '~> 0.3.4'
gem 'awesome_print', require: false
@@ -337,13 +337,13 @@ group :development, :test do
gem 'rspec-parameterized', require: false
# Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826)
- gem 'minitest', '~> 5.7.0'
+ gem 'minitest', '~> 5.11.0'
# Generate Fake data
gem 'ffaker', '~> 2.10'
- gem 'capybara', '~> 2.15'
- gem 'capybara-screenshot', '~> 1.0.0'
+ gem 'capybara', '~> 2.16.1'
+ gem 'capybara-screenshot', '~> 1.0.18'
gem 'selenium-webdriver', '~> 3.12'
gem 'spring', '~> 2.0.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index f70f24da248..4dda0bcad18 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -4,41 +4,41 @@ GEM
RedCloth (4.3.2)
abstract_type (0.0.7)
ace-rails-ap (4.1.2)
- actioncable (5.0.7)
- actionpack (= 5.0.7)
+ actioncable (5.0.7.1)
+ actionpack (= 5.0.7.1)
nio4r (>= 1.2, < 3.0)
websocket-driver (~> 0.6.1)
- actionmailer (5.0.7)
- actionpack (= 5.0.7)
- actionview (= 5.0.7)
- activejob (= 5.0.7)
+ actionmailer (5.0.7.1)
+ actionpack (= 5.0.7.1)
+ actionview (= 5.0.7.1)
+ activejob (= 5.0.7.1)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
- actionpack (5.0.7)
- actionview (= 5.0.7)
- activesupport (= 5.0.7)
+ actionpack (5.0.7.1)
+ actionview (= 5.0.7.1)
+ activesupport (= 5.0.7.1)
rack (~> 2.0)
rack-test (~> 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
- actionview (5.0.7)
- activesupport (= 5.0.7)
+ actionview (5.0.7.1)
+ activesupport (= 5.0.7.1)
builder (~> 3.1)
erubis (~> 2.7.0)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
- activejob (5.0.7)
- activesupport (= 5.0.7)
+ activejob (5.0.7.1)
+ activesupport (= 5.0.7.1)
globalid (>= 0.3.6)
- activemodel (5.0.7)
- activesupport (= 5.0.7)
- activerecord (5.0.7)
- activemodel (= 5.0.7)
- activesupport (= 5.0.7)
+ activemodel (5.0.7.1)
+ activesupport (= 5.0.7.1)
+ activerecord (5.0.7.1)
+ activemodel (= 5.0.7.1)
+ activesupport (= 5.0.7.1)
arel (~> 7.0)
activerecord_sane_schema_dumper (1.0)
rails (>= 5, < 6)
- activesupport (5.0.7)
+ activesupport (5.0.7.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 0.7, < 2)
minitest (~> 5.1)
@@ -97,16 +97,16 @@ GEM
bundler-audit (0.5.0)
bundler (~> 1.2)
thor (~> 0.18)
- byebug (9.0.6)
- capybara (2.15.1)
+ byebug (9.1.0)
+ capybara (2.16.1)
addressable
mini_mime (>= 0.1.3)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
- capybara-screenshot (1.0.14)
- capybara (>= 1.0, < 3)
+ capybara-screenshot (1.0.22)
+ capybara (>= 1.0, < 4)
launchy
carrierwave (1.3.0)
activemodel (>= 4.0.0)
@@ -381,7 +381,7 @@ GEM
json (~> 1.8)
multi_xml (>= 0.5.2)
httpclient (2.8.3)
- i18n (1.1.1)
+ i18n (1.2.0)
concurrent-ruby (~> 1.0)
icalendar (2.4.1)
ice_nine (0.11.2)
@@ -403,7 +403,7 @@ GEM
bindata
json-schema (2.8.0)
addressable (>= 2.4)
- jwt (1.5.6)
+ jwt (2.1.0)
kaminari (1.0.1)
activesupport (>= 4.1.0)
kaminari-actionview (= 1.0.1)
@@ -449,7 +449,7 @@ GEM
loofah (2.2.3)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
- mail (2.7.0)
+ mail (2.7.1)
mini_mime (>= 0.1.1)
mail_room (0.9.1)
memoist (0.16.0)
@@ -463,7 +463,7 @@ GEM
mini_magick (4.8.0)
mini_mime (1.0.1)
mini_portile2 (2.3.0)
- minitest (5.7.0)
+ minitest (5.11.3)
msgpack (1.2.4)
multi_json (1.13.1)
multi_xml (0.6.0)
@@ -483,24 +483,24 @@ GEM
nokogiri
numerizer (0.1.1)
oauth (0.5.4)
- oauth2 (1.4.0)
- faraday (>= 0.8, < 0.13)
- jwt (~> 1.0)
+ oauth2 (1.4.1)
+ faraday (>= 0.8, < 0.16.0)
+ jwt (>= 1.0, < 3.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
octokit (4.9.0)
sawyer (~> 0.8.0, >= 0.5.3)
- omniauth (1.8.1)
- hashie (>= 3.4.6, < 3.6.0)
+ omniauth (1.9.0)
+ hashie (>= 3.4.6, < 3.7.0)
rack (>= 1.6.2, < 3)
omniauth-auth0 (2.0.0)
omniauth-oauth2 (~> 1.4)
omniauth-authentiq (0.3.3)
jwt (>= 1.5)
omniauth-oauth2 (>= 1.5)
- omniauth-azure-oauth2 (0.0.9)
- jwt (~> 1.0)
+ omniauth-azure-oauth2 (0.0.10)
+ jwt (>= 1.0, < 3.0)
omniauth (~> 1.0)
omniauth-oauth2 (~> 1.4)
omniauth-cas3 (1.1.4)
@@ -515,8 +515,8 @@ GEM
omniauth-gitlab (1.0.3)
omniauth (~> 1.0)
omniauth-oauth2 (~> 1.0)
- omniauth-google-oauth2 (0.5.3)
- jwt (>= 1.5)
+ omniauth-google-oauth2 (0.6.0)
+ jwt (>= 2.0)
omniauth (>= 1.1.1)
omniauth-oauth2 (>= 1.5)
omniauth-kerberos (0.3.0)
@@ -527,9 +527,9 @@ GEM
omniauth-oauth (1.1.0)
oauth
omniauth (~> 1.0)
- omniauth-oauth2 (1.5.0)
+ omniauth-oauth2 (1.6.0)
oauth2 (~> 1.1)
- omniauth (~> 1.2)
+ omniauth (~> 1.9)
omniauth-oauth2-generic (0.2.2)
omniauth-oauth2 (~> 1.0)
omniauth-saml (1.10.0)
@@ -595,8 +595,8 @@ GEM
pry (0.11.3)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
- pry-byebug (3.4.3)
- byebug (>= 9.0, < 9.1)
+ pry-byebug (3.5.1)
+ byebug (~> 9.1)
pry (~> 0.10)
pry-rails (0.3.6)
pry (>= 0.10.4)
@@ -624,17 +624,17 @@ GEM
rack
rack-test (0.6.3)
rack (>= 1.0)
- rails (5.0.7)
- actioncable (= 5.0.7)
- actionmailer (= 5.0.7)
- actionpack (= 5.0.7)
- actionview (= 5.0.7)
- activejob (= 5.0.7)
- activemodel (= 5.0.7)
- activerecord (= 5.0.7)
- activesupport (= 5.0.7)
+ rails (5.0.7.1)
+ actioncable (= 5.0.7.1)
+ actionmailer (= 5.0.7.1)
+ actionpack (= 5.0.7.1)
+ actionview (= 5.0.7.1)
+ activejob (= 5.0.7.1)
+ activemodel (= 5.0.7.1)
+ activerecord (= 5.0.7.1)
+ activesupport (= 5.0.7.1)
bundler (>= 1.3.0)
- railties (= 5.0.7)
+ railties (= 5.0.7.1)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.2)
actionpack (~> 5.x, >= 5.0.1)
@@ -650,15 +650,15 @@ GEM
rails-i18n (5.1.1)
i18n (>= 0.7, < 2)
railties (>= 5.0, < 6)
- railties (5.0.7)
- actionpack (= 5.0.7)
- activesupport (= 5.0.7)
+ railties (5.0.7.1)
+ actionpack (= 5.0.7.1)
+ activesupport (= 5.0.7.1)
method_source
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (3.0.0)
raindrops (0.18.0)
- rake (12.3.1)
+ rake (12.3.2)
rb-fsevent (0.10.2)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
@@ -963,8 +963,8 @@ DEPENDENCIES
browser (~> 2.5)
bullet (~> 5.5.0)
bundler-audit (~> 0.5.0)
- capybara (~> 2.15)
- capybara-screenshot (~> 1.0.0)
+ capybara (~> 2.16.1)
+ capybara-screenshot (~> 1.0.18)
carrierwave (~> 1.3)
charlock_holmes (~> 0.7.5)
chronic (~> 0.10.2)
@@ -1041,7 +1041,7 @@ DEPENDENCIES
jquery-atwho-rails (~> 1.3.2)
js_regex (~> 2.2.1)
json-schema (~> 2.8.0)
- jwt (~> 1.5.6)
+ jwt (~> 2.1.0)
kaminari (~> 1.0)
knapsack (~> 1.17)
kubeclient (~> 4.0.0)
@@ -1054,12 +1054,12 @@ DEPENDENCIES
method_source (~> 0.8)
mimemagic (~> 0.3.2)
mini_magick
- minitest (~> 5.7.0)
+ minitest (~> 5.11.0)
mysql2 (~> 0.4.10)
nakayoshi_fork (~> 0.0.4)
net-ldap
net-ssh (~> 5.0)
- nokogiri (~> 1.8.4)
+ nokogiri (~> 1.8.5)
oauth2 (~> 1.4)
octokit (~> 4.9)
omniauth (~> 1.8)
@@ -1070,7 +1070,7 @@ DEPENDENCIES
omniauth-facebook (~> 4.0.0)
omniauth-github (~> 1.3)
omniauth-gitlab (~> 1.0.2)
- omniauth-google-oauth2 (~> 0.5.3)
+ omniauth-google-oauth2 (~> 0.6.0)
omniauth-kerberos (~> 0.3.0)
omniauth-oauth2-generic (~> 0.2.2)
omniauth-saml (~> 1.10)
@@ -1087,7 +1087,7 @@ DEPENDENCIES
pg (~> 0.18.2)
premailer-rails (~> 1.9.7)
prometheus-client-mmap (~> 0.9.4)
- pry-byebug (~> 3.4.1)
+ pry-byebug (~> 3.5.1)
pry-rails (~> 0.3.4)
puma (~> 3.12)
puma_worker_killer
@@ -1096,7 +1096,7 @@ DEPENDENCIES
rack-cors (~> 1.0.0)
rack-oauth2 (~> 1.2.1)
rack-proxy (~> 0.6.0)
- rails (= 5.0.7)
+ rails (= 5.0.7.1)
rails-controller-testing
rails-deprecated_sanitizer (~> 1.0.3)
rails-i18n (~> 5.1)
@@ -1171,4 +1171,4 @@ DEPENDENCIES
wikicloth (= 0.8.1)
BUNDLED WITH
- 1.17.1
+ 1.17.3
diff --git a/app/assets/javascripts/boards/components/issue_due_date.vue b/app/assets/javascripts/boards/components/issue_due_date.vue
index e038198e6f0..9c4c6632976 100644
--- a/app/assets/javascripts/boards/components/issue_due_date.vue
+++ b/app/assets/javascripts/boards/components/issue_due_date.vue
@@ -3,7 +3,12 @@ import dateFormat from 'dateformat';
import { GlTooltip } from '@gitlab/ui';
import Icon from '~/vue_shared/components/icon.vue';
import { __ } from '~/locale';
-import { getDayDifference, getTimeago, dateInWords } from '~/lib/utils/datetime_utility';
+import {
+ getDayDifference,
+ getTimeago,
+ dateInWords,
+ parsePikadayDate,
+} from '~/lib/utils/datetime_utility';
export default {
components: {
@@ -54,7 +59,7 @@ export default {
return standardDateFormat;
},
issueDueDate() {
- return new Date(this.date);
+ return parsePikadayDate(this.date);
},
timeDifference() {
const today = new Date();
diff --git a/app/assets/javascripts/diffs/components/compare_versions_dropdown.vue b/app/assets/javascripts/diffs/components/compare_versions_dropdown.vue
index 8da02ed0b7c..b9b1ee02697 100644
--- a/app/assets/javascripts/diffs/components/compare_versions_dropdown.vue
+++ b/app/assets/javascripts/diffs/components/compare_versions_dropdown.vue
@@ -129,7 +129,7 @@ export default {
</strong>
</div>
<div>
- <small class="commit-sha"> {{ version.truncated_commit_sha }} </small>
+ <small class="commit-sha"> {{ version.short_commit_sha }} </small>
</div>
<div>
<small>
diff --git a/app/assets/javascripts/gfm_auto_complete.js b/app/assets/javascripts/gfm_auto_complete.js
index c14eb936930..8178821be3d 100644
--- a/app/assets/javascripts/gfm_auto_complete.js
+++ b/app/assets/javascripts/gfm_auto_complete.js
@@ -256,7 +256,7 @@ class GfmAutoComplete {
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
if (value.title != null) {
- tmpl = GfmAutoComplete.Milestones.template;
+ tmpl = GfmAutoComplete.Milestones.templateFunction(value.title);
}
return tmpl;
},
@@ -323,7 +323,7 @@ class GfmAutoComplete {
searchKey: 'search',
data: GfmAutoComplete.defaultLoadingData,
displayTpl(value) {
- let tmpl = GfmAutoComplete.Labels.template;
+ let tmpl = GfmAutoComplete.Labels.templateFunction(value.color, value.title);
if (GfmAutoComplete.isLoading(value)) {
tmpl = GfmAutoComplete.Loading.template;
}
@@ -588,9 +588,11 @@ GfmAutoComplete.Members = {
},
};
GfmAutoComplete.Labels = {
- template:
- // eslint-disable-next-line no-template-curly-in-string
- '<li><span class="dropdown-label-box" style="background: ${color}"></span> ${title}</li>',
+ templateFunction(color, title) {
+ return `<li><span class="dropdown-label-box" style="background: ${_.escape(
+ color,
+ )}"></span> ${_.escape(title)}</li>`;
+ },
};
// Issues, MergeRequests and Snippets
GfmAutoComplete.Issues = {
@@ -600,8 +602,9 @@ GfmAutoComplete.Issues = {
};
// Milestones
GfmAutoComplete.Milestones = {
- // eslint-disable-next-line no-template-curly-in-string
- template: '<li>${title}</li>',
+ templateFunction(title) {
+ return `<li>${_.escape(title)}</li>`;
+ },
};
GfmAutoComplete.Loading = {
template:
diff --git a/app/assets/javascripts/notes/components/discussion_filter.vue b/app/assets/javascripts/notes/components/discussion_filter.vue
index 86c114a761a..f5c410211b6 100644
--- a/app/assets/javascripts/notes/components/discussion_filter.vue
+++ b/app/assets/javascripts/notes/components/discussion_filter.vue
@@ -2,7 +2,11 @@
import $ from 'jquery';
import { mapGetters, mapActions } from 'vuex';
import Icon from '~/vue_shared/components/icon.vue';
-import { DISCUSSION_FILTERS_DEFAULT_VALUE, HISTORY_ONLY_FILTER_VALUE } from '../constants';
+import {
+ DISCUSSION_FILTERS_DEFAULT_VALUE,
+ HISTORY_ONLY_FILTER_VALUE,
+ DISCUSSION_TAB_LABEL,
+} from '../constants';
export default {
components: {
@@ -23,6 +27,7 @@ export default {
return {
currentValue: this.selectedValue,
defaultValue: DISCUSSION_FILTERS_DEFAULT_VALUE,
+ displayFilters: true,
};
},
computed: {
@@ -32,6 +37,14 @@ export default {
return this.filters.find(filter => filter.value === this.currentValue);
},
},
+ created() {
+ if (window.mrTabs) {
+ const { eventHub, currentTab } = window.mrTabs;
+
+ eventHub.$on('MergeRequestTabChange', this.toggleFilters);
+ this.toggleFilters(currentTab);
+ }
+ },
mounted() {
this.toggleCommentsForm();
},
@@ -51,12 +64,15 @@ export default {
toggleCommentsForm() {
this.setCommentsDisabled(this.currentValue === HISTORY_ONLY_FILTER_VALUE);
},
+ toggleFilters(tab) {
+ this.displayFilters = tab === DISCUSSION_TAB_LABEL;
+ },
},
};
</script>
<template>
- <div class="discussion-filter-container d-inline-block align-bottom">
+ <div v-if="displayFilters" class="discussion-filter-container d-inline-block align-bottom">
<button
id="discussion-filter-dropdown"
ref="dropdownToggle"
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index 9b7f3d3588d..e78596f8b52 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -226,7 +226,7 @@ export default {
<button
:disabled="isDisabled"
type="button"
- class="js-vue-issue-save btn btn-success js-comment-button"
+ class="js-vue-issue-save btn btn-success js-comment-button qa-reply-comment-button"
@click="handleUpdate();"
>
{{ saveButtonTitle }}
diff --git a/app/assets/javascripts/notes/components/toggle_replies_widget.vue b/app/assets/javascripts/notes/components/toggle_replies_widget.vue
index 72a8ff28466..f1b0b12bdce 100644
--- a/app/assets/javascripts/notes/components/toggle_replies_widget.vue
+++ b/app/assets/javascripts/notes/components/toggle_replies_widget.vue
@@ -57,7 +57,7 @@ export default {
tooltip-placement="bottom"
/>
</div>
- <button class="btn btn-link js-replies-text" type="button" @click="toggle">
+ <button class="btn btn-link js-replies-text qa-expand-replies" type="button" @click="toggle">
{{ replies.length }} {{ n__('reply', 'replies', replies.length) }}
</button>
{{ __('Last reply by') }}
@@ -66,7 +66,11 @@ export default {
</a>
<time-ago-tooltip :time="lastReply.created_at" tooltip-placement="bottom" />
</template>
- <span v-else class="collapse-replies-btn js-collapse-replies" @click="toggle">
+ <span
+ v-else
+ class="collapse-replies-btn js-collapse-replies qa-collapse-replies"
+ @click="toggle"
+ >
<icon name="chevron-down" /> {{ s__('Notes|Collapse replies') }}
</span>
</li>
diff --git a/app/assets/javascripts/notes/constants.js b/app/assets/javascripts/notes/constants.js
index 3147dc64c27..78d365fe94b 100644
--- a/app/assets/javascripts/notes/constants.js
+++ b/app/assets/javascripts/notes/constants.js
@@ -17,6 +17,7 @@ export const RESOLVE_NOTE_METHOD_NAME = 'post';
export const DESCRIPTION_TYPE = 'changed the description';
export const HISTORY_ONLY_FILTER_VALUE = 2;
export const DISCUSSION_FILTERS_DEFAULT_VALUE = 0;
+export const DISCUSSION_TAB_LABEL = 'show';
export const NOTEABLE_TYPE_MAPPING = {
Issue: ISSUE_NOTEABLE_TYPE,
diff --git a/app/assets/javascripts/pages/users/user_overview_block.js b/app/assets/javascripts/pages/users/user_overview_block.js
index eec2b5ca8e5..e9ecec717d6 100644
--- a/app/assets/javascripts/pages/users/user_overview_block.js
+++ b/app/assets/javascripts/pages/users/user_overview_block.js
@@ -29,18 +29,21 @@ export default class UserOverviewBlock {
render(data) {
const { html, count } = data;
- const contentList = document.querySelector(`${this.container} .overview-content-list`);
+ const containerEl = document.querySelector(this.container);
+ const contentList = containerEl.querySelector('.overview-content-list');
contentList.innerHTML += html;
- const loadingEl = document.querySelector(`${this.container} .loading`);
+ const loadingEl = containerEl.querySelector('.loading');
if (count && count > 0) {
- document.querySelector(`${this.container} .js-view-all`).classList.remove('hide');
+ containerEl.querySelector('.js-view-all').classList.remove('hide');
} else {
- document
- .querySelector(`${this.container} .nothing-here-block`)
- .classList.add('text-left', 'p-0');
+ const nothingHereBlock = containerEl.querySelector('.nothing-here-block');
+
+ if (nothingHereBlock) {
+ nothingHereBlock.classList.add('text-left', 'p-0');
+ }
}
loadingEl.classList.add('hide');
diff --git a/app/assets/stylesheets/bootstrap_migration.scss b/app/assets/stylesheets/bootstrap_migration.scss
index f0671e36130..b7dbb48632e 100644
--- a/app/assets/stylesheets/bootstrap_migration.scss
+++ b/app/assets/stylesheets/bootstrap_migration.scss
@@ -70,6 +70,17 @@ h6,
margin-bottom: 10px;
}
+/* Our adjustments to hx & .hx above add unnecessary margins to modal-title
+ and page-title in modals, so we set them to 0 in order to have properly
+ formatted modal headers. */
+.modal-header {
+ .modal-title,
+ .page-title {
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+}
+
h5,
.h5 {
font-size: $gl-font-size;
@@ -142,7 +153,9 @@ table {
@include media-breakpoint-up($breakpoint) {
$infix: breakpoint-infix($breakpoint, $grid-breakpoints);
- .d#{$infix}-table-header-group { display: table-header-group !important; }
+ .d#{$infix}-table-header-group {
+ display: table-header-group !important;
+ }
}
}
diff --git a/app/assets/stylesheets/framework/issue_box.scss b/app/assets/stylesheets/framework/issue_box.scss
index a66604e56ff..e51f230a680 100644
--- a/app/assets/stylesheets/framework/issue_box.scss
+++ b/app/assets/stylesheets/framework/issue_box.scss
@@ -45,9 +45,4 @@
&.status-box-upcoming {
background: $gl-text-color-secondary;
}
-
- &.status-box-milestone {
- color: $gl-text-color;
- background: $gray-darker;
- }
}
diff --git a/app/assets/stylesheets/framework/modal.scss b/app/assets/stylesheets/framework/modal.scss
index 95291b4a9ad..46d40ea7aa5 100644
--- a/app/assets/stylesheets/framework/modal.scss
+++ b/app/assets/stylesheets/framework/modal.scss
@@ -29,10 +29,6 @@
padding-right: 28px;
}
}
-
- .page-title {
- margin-top: 0;
- }
}
.modal-body {
diff --git a/app/assets/stylesheets/pages/milestone.scss b/app/assets/stylesheets/pages/milestone.scss
index 1e92582d6d9..94bf32945fc 100644
--- a/app/assets/stylesheets/pages/milestone.scss
+++ b/app/assets/stylesheets/pages/milestone.scss
@@ -1,3 +1,5 @@
+$status-box-line-height: 26px;
+
.issues-sortable-list .str-truncated {
max-width: 90%;
}
@@ -38,6 +40,7 @@
font-size: $tooltip-font-size;
margin-top: 0;
margin-right: $gl-padding-4;
+ line-height: $status-box-line-height;
@include media-breakpoint-down(xs) {
line-height: unset;
diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb
index 8f683ca06ad..8f267eccc8a 100644
--- a/app/controllers/admin/application_settings_controller.rb
+++ b/app/controllers/admin/application_settings_controller.rb
@@ -77,7 +77,7 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController
def reset_health_check_token
@application_setting.reset_health_check_access_token!
flash[:notice] = 'New health check access token has been generated!'
- redirect_to :back
+ redirect_back_or_default
end
def clear_repository_check_states
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 140a625d333..a8fc848c879 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -76,7 +76,7 @@ class ApplicationController < ActionController::Base
end
def redirect_back_or_default(default: root_path, options: {})
- redirect_to request.referer.present? ? :back : default, options
+ redirect_back(fallback_location: default, **options)
end
def not_found
diff --git a/app/controllers/groups/milestones_controller.rb b/app/controllers/groups/milestones_controller.rb
index b42116b0f36..868deea3f01 100644
--- a/app/controllers/groups/milestones_controller.rb
+++ b/app/controllers/groups/milestones_controller.rb
@@ -43,14 +43,7 @@ class Groups::MilestonesController < Groups::ApplicationController
def update
# Keep this compatible with legacy group milestones where we have to update
# all projects milestones states at once.
- if @milestone.legacy_group_milestone?
- update_params = milestone_params.select { |key| key == "state_event" }
- milestones = @milestone.milestones
- else
- update_params = milestone_params
- milestones = [@milestone]
- end
-
+ milestones, update_params = get_milestones_for_update
milestones.each do |milestone|
Milestones::UpdateService.new(milestone.parent, current_user, update_params).execute(milestone)
end
@@ -71,6 +64,14 @@ class Groups::MilestonesController < Groups::ApplicationController
private
+ def get_milestones_for_update
+ if @milestone.legacy_group_milestone?
+ [@milestone.milestones, legacy_milestone_params]
+ else
+ [[@milestone], milestone_params]
+ end
+ end
+
def authorize_admin_milestones!
return render_404 unless can?(current_user, :admin_milestone, group)
end
@@ -79,6 +80,10 @@ class Groups::MilestonesController < Groups::ApplicationController
params.require(:milestone).permit(:title, :description, :start_date, :due_date, :state_event)
end
+ def legacy_milestone_params
+ params.require(:milestone).permit(:state_event)
+ end
+
def milestone_path
if @milestone.legacy_group_milestone?
group_milestone_path(group, @milestone.safe_title, title: @milestone.title)
diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb
index c1dcc463de7..f476f428fdb 100644
--- a/app/controllers/groups/settings/ci_cd_controller.rb
+++ b/app/controllers/groups/settings/ci_cd_controller.rb
@@ -4,7 +4,7 @@ module Groups
module Settings
class CiCdController < Groups::ApplicationController
skip_cross_project_access_check :show
- before_action :authorize_admin_pipeline!
+ before_action :authorize_admin_group!
def show
define_ci_variables
@@ -26,8 +26,8 @@ module Groups
.map { |variable| variable.present(current_user: current_user) }
end
- def authorize_admin_pipeline!
- return render_404 unless can?(current_user, :admin_pipeline, group)
+ def authorize_admin_group!
+ return render_404 unless can?(current_user, :admin_group, group)
end
end
end
diff --git a/app/controllers/projects/snippets_controller.rb b/app/controllers/projects/snippets_controller.rb
index a44acb12bdf..255f1f3569a 100644
--- a/app/controllers/projects/snippets_controller.rb
+++ b/app/controllers/projects/snippets_controller.rb
@@ -75,7 +75,14 @@ class Projects::SnippetsController < Projects::ApplicationController
format.json do
render_blob_json(blob)
end
- format.js { render 'shared/snippets/show'}
+
+ format.js do
+ if @snippet.embeddable?
+ render 'shared/snippets/show'
+ else
+ head :not_found
+ end
+ end
end
end
diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 8bf93bfd68d..878816475b2 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -19,6 +19,7 @@ class ProjectsController < Projects::ApplicationController
before_action :lfs_blob_ids, only: [:show], if: [:repo_exists?, :project_view_files?]
before_action :project_export_enabled, only: [:export, :download_export, :remove_export, :generate_new_export]
before_action :present_project, only: [:edit]
+ before_action :authorize_download_code!, only: [:refs]
# Authorize
before_action :authorize_admin_project!, only: [:edit, :update, :housekeeping, :download_export, :export, :remove_export, :generate_new_export]
diff --git a/app/controllers/sherlock/transactions_controller.rb b/app/controllers/sherlock/transactions_controller.rb
index 46e382e594e..8d1847507cc 100644
--- a/app/controllers/sherlock/transactions_controller.rb
+++ b/app/controllers/sherlock/transactions_controller.rb
@@ -15,7 +15,7 @@ module Sherlock
def destroy_all
Gitlab::Sherlock.collection.clear
- redirect_to :back, status: :found
+ redirect_back_or_default(options: { status: :found })
end
end
end
diff --git a/app/controllers/snippets_controller.rb b/app/controllers/snippets_controller.rb
index dd9bf17cf0c..8ea5450b4e8 100644
--- a/app/controllers/snippets_controller.rb
+++ b/app/controllers/snippets_controller.rb
@@ -80,7 +80,13 @@ class SnippetsController < ApplicationController
render_blob_json(blob)
end
- format.js { render 'shared/snippets/show' }
+ format.js do
+ if @snippet.embeddable?
+ render 'shared/snippets/show'
+ else
+ head :not_found
+ end
+ end
end
end
diff --git a/app/helpers/milestones_helper.rb b/app/helpers/milestones_helper.rb
index 327b69e5110..50aec83b867 100644
--- a/app/helpers/milestones_helper.rb
+++ b/app/helpers/milestones_helper.rb
@@ -231,12 +231,15 @@ module MilestonesHelper
end
end
- def group_or_dashboard_milestone_path(milestone)
- if milestone.group_milestone?
- group_milestone_path(milestone.group, milestone.iid, milestone: { title: milestone.title })
- else
- dashboard_milestone_path(milestone.safe_title, title: milestone.title)
- end
+ def group_or_project_milestone_path(milestone)
+ params =
+ if milestone.group_milestone?
+ { milestone: { title: milestone.title } }
+ else
+ { title: milestone.title }
+ end
+
+ milestone_path(milestone.milestone, params)
end
def can_admin_project_milestones?
diff --git a/app/helpers/snippets_helper.rb b/app/helpers/snippets_helper.rb
index 8fded0efe4d..ecb2b2d707b 100644
--- a/app/helpers/snippets_helper.rb
+++ b/app/helpers/snippets_helper.rb
@@ -130,12 +130,4 @@ module SnippetsHelper
link_to external_snippet_icon('download'), download_url, class: 'btn', target: '_blank', title: 'Download', rel: 'noopener noreferrer'
end
-
- def public_snippet?
- if @snippet.project_id?
- can?(nil, :read_project_snippet, @snippet)
- else
- can?(nil, :read_personal_snippet, @snippet)
- end
- end
end
diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb
index 6ac1f42c321..02762897c89 100644
--- a/app/helpers/sorting_helper.rb
+++ b/app/helpers/sorting_helper.rb
@@ -234,7 +234,7 @@ module SortingHelper
end
def sort_title_milestone
- s_('SortOptions|Milestone')
+ s_('SortOptions|Milestone due date')
end
def sort_title_milestone_later
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 16a72c680fa..aeb35538d67 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -10,6 +10,7 @@ module Ci
include Importable
include Gitlab::Utils::StrongMemoize
include Deployable
+ include HasRef
belongs_to :project, inverse_of: :builds
belongs_to :runner
@@ -220,6 +221,10 @@ module Ci
next unless build.project
build.deployment&.drop
+ end
+
+ after_transition any => [:failed] do |build|
+ next unless build.project
if build.retry_failure?
begin
@@ -640,11 +645,11 @@ module Ci
def secret_group_variables
return [] unless project.group
- project.group.ci_variables_for(ref, project)
+ project.group.ci_variables_for(git_ref, project)
end
def secret_project_variables(environment: persisted_environment)
- project.ci_variables_for(ref: ref, environment: environment)
+ project.ci_variables_for(ref: git_ref, environment: environment)
end
def steps
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 25937065011..1f5017cc3c3 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -11,6 +11,7 @@ module Ci
include Gitlab::Utils::StrongMemoize
include AtomicInternalId
include EnumWithNil
+ include HasRef
belongs_to :project, inverse_of: :all_pipelines
belongs_to :user
@@ -380,7 +381,7 @@ module Ci
end
def branch?
- !tag? && !merge_request?
+ super && !merge_request?
end
def stuck?
@@ -580,7 +581,7 @@ module Ci
end
def protected_ref?
- strong_memoize(:protected_ref) { project.protected_for?(ref) }
+ strong_memoize(:protected_ref) { project.protected_for?(git_ref) }
end
def legacy_trigger
@@ -712,14 +713,10 @@ module Ci
end
def git_ref
- if branch?
+ if merge_request?
Gitlab::Git::BRANCH_REF_PREFIX + ref.to_s
- elsif merge_request?
- Gitlab::Git::BRANCH_REF_PREFIX + ref.to_s
- elsif tag?
- Gitlab::Git::TAG_REF_PREFIX + ref.to_s
else
- raise ArgumentError, 'Invalid pipeline type!'
+ super
end
end
diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb
index 8f8790585a3..7799f069742 100644
--- a/app/models/clusters/applications/ingress.rb
+++ b/app/models/clusters/applications/ingress.rb
@@ -23,7 +23,7 @@ module Clusters
FETCH_IP_ADDRESS_DELAY = 30.seconds
state_machine :status do
- before_transition any => [:installed] do |application|
+ after_transition any => [:installed] do |application|
application.run_after_commit do
ClusterWaitForIngressIpAddressWorker.perform_in(
FETCH_IP_ADDRESS_DELAY, application.name, application.id)
diff --git a/app/models/clusters/applications/knative.rb b/app/models/clusters/applications/knative.rb
index 0c72d7d8340..5ac152278da 100644
--- a/app/models/clusters/applications/knative.rb
+++ b/app/models/clusters/applications/knative.rb
@@ -20,7 +20,7 @@ module Clusters
self.reactive_cache_key = ->(knative) { [knative.class.model_name.singular, knative.id] }
state_machine :status do
- before_transition any => [:installed] do |application|
+ after_transition any => [:installed] do |application|
application.run_after_commit do
ClusterWaitForIngressIpAddressWorker.perform_in(
FETCH_IP_ADDRESS_DELAY, application.name, application.id)
diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb
index c931b340b24..0c0247da1fb 100644
--- a/app/models/clusters/applications/runner.rb
+++ b/app/models/clusters/applications/runner.rb
@@ -3,7 +3,7 @@
module Clusters
module Applications
class Runner < ActiveRecord::Base
- VERSION = '0.1.39'.freeze
+ VERSION = '0.1.43'.freeze
self.table_name = 'clusters_applications_runners'
diff --git a/app/models/concerns/has_ref.rb b/app/models/concerns/has_ref.rb
new file mode 100644
index 00000000000..d7089294efc
--- /dev/null
+++ b/app/models/concerns/has_ref.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+module HasRef
+ extend ActiveSupport::Concern
+
+ def branch?
+ !tag?
+ end
+
+ def git_ref
+ if branch?
+ Gitlab::Git::BRANCH_REF_PREFIX + ref.to_s
+ elsif tag?
+ Gitlab::Git::TAG_REF_PREFIX + ref.to_s
+ end
+ end
+end
diff --git a/app/models/concerns/milestoneish.rb b/app/models/concerns/milestoneish.rb
index e44a069b730..055ffe04646 100644
--- a/app/models/concerns/milestoneish.rb
+++ b/app/models/concerns/milestoneish.rb
@@ -42,7 +42,7 @@ module Milestoneish
def issues_visible_to_user(user)
memoize_per_user(user, :issues_visible_to_user) do
IssuesFinder.new(user, issues_finder_params)
- .execute.preload(:assignees).where(milestone_id: milestoneish_ids)
+ .execute.preload(:assignees).where(milestone_id: milestoneish_id)
end
end
diff --git a/app/models/dashboard_group_milestone.rb b/app/models/dashboard_group_milestone.rb
index ad0bb55f0a7..9bcc95e35a5 100644
--- a/app/models/dashboard_group_milestone.rb
+++ b/app/models/dashboard_group_milestone.rb
@@ -6,7 +6,7 @@ class DashboardGroupMilestone < GlobalMilestone
attr_reader :group_name
def initialize(milestone)
- super(milestone.title, Array(milestone))
+ super
@group_name = milestone.group.full_name
end
@@ -18,22 +18,4 @@ class DashboardGroupMilestone < GlobalMilestone
.active
.map { |m| new(m) }
end
-
- override :group_milestone?
- def group_milestone?
- @first_milestone.group_milestone?
- end
-
- override :milestoneish_ids
- def milestoneish_ids
- milestones.map(&:id)
- end
-
- def group
- @first_milestone.group
- end
-
- def iid
- @first_milestone.iid
- end
end
diff --git a/app/models/dashboard_milestone.rb b/app/models/dashboard_milestone.rb
index 96bc8090b81..9b377b70e5b 100644
--- a/app/models/dashboard_milestone.rb
+++ b/app/models/dashboard_milestone.rb
@@ -1,11 +1,15 @@
# frozen_string_literal: true
class DashboardMilestone < GlobalMilestone
- def issues_finder_params
- { authorized_only: true }
+ attr_reader :project_name
+
+ def initialize(milestone)
+ super
+
+ @project_name = milestone.project.full_name
end
- def dashboard_milestone?
+ def project_milestone?
true
end
end
diff --git a/app/models/global_milestone.rb b/app/models/global_milestone.rb
index 085ffd16c6a..4e82f3fed27 100644
--- a/app/models/global_milestone.rb
+++ b/app/models/global_milestone.rb
@@ -3,69 +3,78 @@
class GlobalMilestone
include Milestoneish
- EPOCH = DateTime.parse('1970-01-01')
STATE_COUNT_HASH = { opened: 0, closed: 0, all: 0 }.freeze
- attr_accessor :title, :milestones
+ attr_reader :milestone
alias_attribute :name, :title
+ delegate :title, :state, :due_date, :start_date, :participants, :project, :group, :expires_at, :closed?, :iid, :group_milestone?, :safe_title, :milestoneish_id, to: :milestone
+
+ def to_hash
+ {
+ name: title,
+ title: title,
+ group_name: group&.full_name,
+ project_name: project&.full_name
+ }
+ end
+
def for_display
- @first_milestone
+ @milestone
end
def self.build_collection(projects, params)
- params =
- { project_ids: projects.map(&:id), state: params[:state] }
-
- child_milestones = MilestonesFinder.new(params).execute # rubocop: disable CodeReuse/Finder
-
- milestones = child_milestones.select(:id, :title).group_by(&:title).map do |title, grouped|
- milestones_relation = Milestone.where(id: grouped.map(&:id))
- new(title, milestones_relation)
- end
+ items = Milestone.of_projects(projects)
+ .reorder_by_due_date_asc
+ .order_by_name_asc
- milestones.sort_by { |milestone| milestone.due_date || EPOCH }
+ Milestone.filter_by_state(items, params[:state]).map { |m| new(m) }
end
+ # necessary for legacy milestones
def self.build(projects, title)
- child_milestones = Milestone.of_projects(projects).where(title: title)
- return if child_milestones.blank?
+ milestones = Milestone.of_projects(projects).where(title: title)
+ return if milestones.blank?
- new(title, child_milestones)
+ new(milestones.first)
end
- def self.count_by_state(milestones_by_state_and_title, state)
- milestones_by_state_and_title.count do |(milestone_state, _), _|
- milestone_state == state
+ def self.states_count(projects, group = nil)
+ legacy_group_milestones_count = legacy_group_milestone_states_count(projects)
+ group_milestones_count = group_milestones_states_count(group)
+
+ legacy_group_milestones_count.merge(group_milestones_count) do |k, legacy_group_milestones_count, group_milestones_count|
+ legacy_group_milestones_count + group_milestones_count
end
end
- private_class_method :count_by_state
- def initialize(title, milestones)
- @title = title
- @name = title
- @milestones = milestones
- @first_milestone = milestones.find {|m| m.description.present? } || milestones.first
- end
+ def self.group_milestones_states_count(group)
+ return STATE_COUNT_HASH unless group
- def milestoneish_ids
- milestones.select(:id)
- end
+ counts_by_state = Milestone.of_groups(group).count_by_state
- def safe_title
- @title.to_slug.normalize.to_s
+ {
+ opened: counts_by_state['active'] || 0,
+ closed: counts_by_state['closed'] || 0,
+ all: counts_by_state.values.sum
+ }
end
- def projects
- @projects ||= Project.for_milestones(milestoneish_ids)
- end
+ def self.legacy_group_milestone_states_count(projects)
+ return STATE_COUNT_HASH unless projects
- def state
- milestones.each do |milestone|
- return 'active' if milestone.state != 'closed'
- end
+ # We need to reorder(nil) on the projects, because the controller passes them in sorted.
+ relation = Milestone.of_projects(projects.reorder(nil)).count_by_state
- 'closed'
+ {
+ opened: relation['active'] || 0,
+ closed: relation['closed'] || 0,
+ all: relation.values.sum
+ }
+ end
+
+ def initialize(milestone)
+ @milestone = milestone
end
def active?
@@ -77,37 +86,14 @@ class GlobalMilestone
end
def issues
- @issues ||= Issue.of_milestones(milestoneish_ids).includes(:project, :assignees, :labels)
+ @issues ||= Issue.of_milestones(milestone).includes(:project, :assignees, :labels)
end
def merge_requests
- @merge_requests ||= MergeRequest.of_milestones(milestoneish_ids).includes(:target_project, :assignee, :labels)
- end
-
- def participants
- @participants ||= milestones.map(&:participants).flatten.uniq
+ @merge_requests ||= MergeRequest.of_milestones(milestone).includes(:target_project, :assignee, :labels)
end
def labels
- @labels ||= GlobalLabel.build_collection(milestones.includes(:labels).map(&:labels).flatten)
- .sort_by!(&:title)
- end
-
- def due_date
- return @due_date if defined?(@due_date)
-
- @due_date =
- if @milestones.all? { |x| x.due_date == @milestones.first.due_date }
- @milestones.first.due_date
- end
- end
-
- def start_date
- return @start_date if defined?(@start_date)
-
- @start_date =
- if @milestones.all? { |x| x.start_date == @milestones.first.start_date }
- @milestones.first.start_date
- end
+ @labels ||= GlobalLabel.build_collection(milestone.labels).sort_by!(&:title)
end
end
diff --git a/app/models/group_milestone.rb b/app/models/group_milestone.rb
index 9dfaebacc83..a58537de319 100644
--- a/app/models/group_milestone.rb
+++ b/app/models/group_milestone.rb
@@ -1,18 +1,35 @@
# frozen_string_literal: true
# Group Milestones are milestones that can be shared among many projects within the same group
class GroupMilestone < GlobalMilestone
- attr_accessor :group
+ attr_reader :group, :milestones
def self.build_collection(group, projects, params)
- super(projects, params).each do |milestone|
- milestone.group = group
+ params =
+ { state: params[:state] }
+
+ project_milestones = Milestone.of_projects(projects)
+ child_milestones = Milestone.filter_by_state(project_milestones, params[:state])
+ grouped_milestones = child_milestones.group_by(&:title)
+
+ grouped_milestones.map do |title, grouped|
+ new(title, grouped, group)
end
end
def self.build(group, projects, title)
- super(projects, title).tap do |milestone|
- milestone&.group = group
- end
+ child_milestones = Milestone.of_projects(projects).where(title: title)
+ return if child_milestones.blank?
+
+ new(title, child_milestones, group)
+ end
+
+ def initialize(title, milestones, group)
+ @milestones = milestones
+ @group = group
+ end
+
+ def milestone
+ @milestone ||= milestones.find { |m| m.description.present? } || milestones.first
end
def issues_finder_params
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index b937bef100b..6092c56b925 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -105,7 +105,9 @@ class MergeRequest < ActiveRecord::Base
before_transition any => :opened do |merge_request|
merge_request.merge_jid = nil
+ end
+ after_transition any => :opened do |merge_request|
merge_request.run_after_commit do
UpdateHeadPipelineForMergeRequestWorker.perform_async(merge_request.id)
end
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 6dc0fca68e6..f55c39d9912 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -94,6 +94,10 @@ class Milestone < ActiveRecord::Base
end
end
+ def count_by_state
+ reorder(nil).group(:state).count
+ end
+
def predefined?(milestone)
milestone == Any ||
milestone == None ||
@@ -215,7 +219,7 @@ class Milestone < ActiveRecord::Base
self.class.reference_prefix + self.title
end
- def milestoneish_ids
+ def milestoneish_id
id
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 09e2a6114fe..cd558752080 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -324,10 +324,9 @@ class Project < ActiveRecord::Base
validates :namespace, presence: true
validates :name, uniqueness: { scope: :namespace_id }
- validates :import_url, url: { protocols: ->(project) { project.persisted? ? VALID_MIRROR_PROTOCOLS : VALID_IMPORT_PROTOCOLS },
- ports: ->(project) { project.persisted? ? VALID_MIRROR_PORTS : VALID_IMPORT_PORTS },
- allow_localhost: false,
- enforce_user: true }, if: [:external_import?, :import_url_changed?]
+ validates :import_url, public_url: { protocols: ->(project) { project.persisted? ? VALID_MIRROR_PROTOCOLS : VALID_IMPORT_PROTOCOLS },
+ ports: ->(project) { project.persisted? ? VALID_MIRROR_PORTS : VALID_IMPORT_PORTS },
+ enforce_user: true }, if: [:external_import?, :import_url_changed?]
validates :star_count, numericality: { greater_than_or_equal_to: 0 }
validate :check_limit, on: :create
validate :check_repository_path_availability, on: :update, if: ->(project) { project.renamed? }
@@ -1734,10 +1733,21 @@ class Project < ActiveRecord::Base
end
def protected_for?(ref)
- if repository.branch_exists?(ref)
- ProtectedBranch.protected?(self, ref)
- elsif repository.tag_exists?(ref)
- ProtectedTag.protected?(self, ref)
+ raise Repository::AmbiguousRefError if repository.ambiguous_ref?(ref)
+
+ resolved_ref = repository.expand_ref(ref) || ref
+ return false unless Gitlab::Git.tag_ref?(resolved_ref) || Gitlab::Git.branch_ref?(resolved_ref)
+
+ ref_name = if resolved_ref == ref
+ Gitlab::Git.ref_name(resolved_ref)
+ else
+ ref
+ end
+
+ if Gitlab::Git.branch_ref?(resolved_ref)
+ ProtectedBranch.protected?(self, ref_name)
+ elsif Gitlab::Git.tag_ref?(resolved_ref)
+ ProtectedTag.protected?(self, ref_name)
end
end
diff --git a/app/models/project_services/kubernetes_service.rb b/app/models/project_services/kubernetes_service.rb
index b801fd84a07..f69edd60003 100644
--- a/app/models/project_services/kubernetes_service.rb
+++ b/app/models/project_services/kubernetes_service.rb
@@ -53,7 +53,7 @@ class KubernetesService < DeploymentService
end
def description
- 'Kubernetes / Openshift integration'
+ 'Kubernetes / OpenShift integration'
end
def help
diff --git a/app/models/remote_mirror.rb b/app/models/remote_mirror.rb
index 5a6895aefab..a3fa67c72bf 100644
--- a/app/models/remote_mirror.rb
+++ b/app/models/remote_mirror.rb
@@ -17,7 +17,7 @@ class RemoteMirror < ActiveRecord::Base
belongs_to :project, inverse_of: :remote_mirrors
- validates :url, presence: true, url: { protocols: %w(ssh git http https), allow_blank: true, enforce_user: true }
+ validates :url, presence: true, public_url: { protocols: %w(ssh git http https), allow_blank: true, enforce_user: true }
before_save :set_new_remote_name, if: :mirror_url_changed?
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 015a179f374..b19ae2e0e6a 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -25,6 +25,7 @@ class Repository
delegate :bundle_to_disk, to: :raw_repository
CreateTreeError = Class.new(StandardError)
+ AmbiguousRefError = Class.new(StandardError)
# Methods that cache data from the Git repository.
#
@@ -181,6 +182,18 @@ class Repository
tags.find { |tag| tag.name == name }
end
+ def ambiguous_ref?(ref)
+ tag_exists?(ref) && branch_exists?(ref)
+ end
+
+ def expand_ref(ref)
+ if tag_exists?(ref)
+ Gitlab::Git::TAG_REF_PREFIX + ref
+ elsif branch_exists?(ref)
+ Gitlab::Git::BRANCH_REF_PREFIX + ref
+ end
+ end
+
def add_branch(user, branch_name, ref)
branch = raw_repository.add_branch(branch_name, user: user, target: ref)
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index 11856b55902..f9b23bbbf6c 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -175,6 +175,12 @@ class Snippet < ActiveRecord::Base
:visibility_level
end
+ def embeddable?
+ ability = project_id? ? :read_project_snippet : :read_personal_snippet
+
+ Ability.allowed?(nil, ability, self)
+ end
+
def notes_with_associations
notes.includes(:author)
end
diff --git a/app/models/todo.rb b/app/models/todo.rb
index 7b64615f699..d9b86d941b6 100644
--- a/app/models/todo.rb
+++ b/app/models/todo.rb
@@ -4,6 +4,11 @@ class Todo < ActiveRecord::Base
include Sortable
include FromUnion
+ # Time to wait for todos being removed when not visible for user anymore.
+ # Prevents TODOs being removed by mistake, for example, removing access from a user
+ # and giving it back again.
+ WAIT_FOR_DELETE = 1.hour
+
ASSIGNED = 1
MENTIONED = 2
BUILD_FAILED = 3
diff --git a/app/policies/issuable_policy.rb b/app/policies/issuable_policy.rb
index 6d8b575102e..ecb2797d1d9 100644
--- a/app/policies/issuable_policy.rb
+++ b/app/policies/issuable_policy.rb
@@ -11,7 +11,7 @@ class IssuablePolicy < BasePolicy
@user && @subject.assignee_or_author?(@user)
end
- rule { assignee_or_author }.policy do
+ rule { can?(:guest_access) & assignee_or_author }.policy do
enable :read_issue
enable :update_issue
enable :reopen_issue
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index 19b5552887f..f8d8ef04001 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -31,7 +31,8 @@ module Ci
seeds_block: block,
variables_attributes: params[:variables_attributes],
project: project,
- current_user: current_user)
+ current_user: current_user,
+ push_options: params[:push_options])
sequence = Gitlab::Ci::Pipeline::Chain::Sequence
.new(pipeline, command, SEQUENCE)
diff --git a/app/services/git_push_service.rb b/app/services/git_push_service.rb
index f1883877d56..9ecee7c6156 100644
--- a/app/services/git_push_service.rb
+++ b/app/services/git_push_service.rb
@@ -174,7 +174,8 @@ class GitPushService < BaseService
params[:newrev],
params[:ref],
@push_commits,
- commits_count: commits_count)
+ commits_count: commits_count,
+ push_options: params[:push_options] || [])
end
def push_to_existing_branch?
diff --git a/app/services/git_tag_push_service.rb b/app/services/git_tag_push_service.rb
index dbadafc0f52..03fcf614c64 100644
--- a/app/services/git_tag_push_service.rb
+++ b/app/services/git_tag_push_service.rb
@@ -45,7 +45,8 @@ class GitTagPushService < BaseService
params[:newrev],
params[:ref],
commits,
- message)
+ message,
+ push_options: params[:push_options] || [])
end
def build_system_push_data
diff --git a/app/services/groups/update_service.rb b/app/services/groups/update_service.rb
index 31d3c844ad5..de78a3f7b27 100644
--- a/app/services/groups/update_service.rb
+++ b/app/services/groups/update_service.rb
@@ -31,7 +31,7 @@ module Groups
def after_update
if group.previous_changes.include?(:visibility_level) && group.private?
# don't enqueue immediately to prevent todos removal in case of a mistake
- TodosDestroyer::GroupPrivateWorker.perform_in(1.hour, group.id)
+ TodosDestroyer::GroupPrivateWorker.perform_in(Todo::WAIT_FOR_DELETE, group.id)
end
end
diff --git a/app/services/issues/update_service.rb b/app/services/issues/update_service.rb
index a1d0cc0e568..e992d682c79 100644
--- a/app/services/issues/update_service.rb
+++ b/app/services/issues/update_service.rb
@@ -44,7 +44,7 @@ module Issues
if issue.previous_changes.include?('confidential')
# don't enqueue immediately to prevent todos removal in case of a mistake
- TodosDestroyer::ConfidentialIssueWorker.perform_in(1.hour, issue.id) if issue.confidential?
+ TodosDestroyer::ConfidentialIssueWorker.perform_in(Todo::WAIT_FOR_DELETE, issue.id) if issue.confidential?
create_confidentiality_note(issue)
end
diff --git a/app/services/members/base_service.rb b/app/services/members/base_service.rb
index d734571f835..e78affff797 100644
--- a/app/services/members/base_service.rb
+++ b/app/services/members/base_service.rb
@@ -47,5 +47,11 @@ module Members
raise "Unknown action '#{action}' on #{member}!"
end
end
+
+ def enqueue_delete_todos(member)
+ type = member.is_a?(GroupMember) ? 'Group' : 'Project'
+ # don't enqueue immediately to prevent todos removal in case of a mistake
+ TodosDestroyer::EntityLeaveWorker.perform_in(Todo::WAIT_FOR_DELETE, member.user_id, member.source_id, type)
+ end
end
end
diff --git a/app/services/members/destroy_service.rb b/app/services/members/destroy_service.rb
index c186a5971dc..ae0c644e6c0 100644
--- a/app/services/members/destroy_service.rb
+++ b/app/services/members/destroy_service.rb
@@ -15,7 +15,7 @@ module Members
notification_service.decline_access_request(member)
end
- enqeue_delete_todos(member)
+ enqueue_delete_todos(member)
after_execute(member: member)
@@ -24,12 +24,6 @@ module Members
private
- def enqeue_delete_todos(member)
- type = member.is_a?(GroupMember) ? 'Group' : 'Project'
- # don't enqueue immediately to prevent todos removal in case of a mistake
- TodosDestroyer::EntityLeaveWorker.perform_in(1.hour, member.user_id, member.source_id, type)
- end
-
def can_destroy_member?(member)
can?(current_user, destroy_member_permission(member), member)
end
diff --git a/app/services/members/update_service.rb b/app/services/members/update_service.rb
index 1f5618dae53..ff8d5c1d8c9 100644
--- a/app/services/members/update_service.rb
+++ b/app/services/members/update_service.rb
@@ -10,9 +10,18 @@ module Members
if member.update(params)
after_execute(action: permission, old_access_level: old_access_level, member: member)
+
+ # Deletes only confidential issues todos for guests
+ enqueue_delete_todos(member) if downgrading_to_guest?
end
member
end
+
+ private
+
+ def downgrading_to_guest?
+ params[:access_level] == Gitlab::Access::GUEST
+ end
end
end
diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb
index 36767621d74..48419da98ad 100644
--- a/app/services/merge_requests/build_service.rb
+++ b/app/services/merge_requests/build_service.rb
@@ -18,7 +18,7 @@ module MergeRequests
merge_request.source_project = find_source_project
merge_request.target_project = find_target_project
merge_request.target_branch = find_target_branch
- merge_request.can_be_created = branches_valid?
+ merge_request.can_be_created = projects_and_branches_valid?
# compare branches only if branches are valid, otherwise
# compare_branches may raise an error
@@ -49,15 +49,19 @@ module MergeRequests
to: :merge_request
def find_source_project
- return source_project if source_project.present? && can?(current_user, :read_project, source_project)
+ return source_project if source_project.present? && can?(current_user, :create_merge_request_from, source_project)
project
end
def find_target_project
- return target_project if target_project.present? && can?(current_user, :read_project, target_project)
+ return target_project if target_project.present? && can?(current_user, :create_merge_request_in, target_project)
- project.default_merge_request_target
+ target_project = project.default_merge_request_target
+
+ return target_project if target_project.present? && can?(current_user, :create_merge_request_in, target_project)
+
+ project
end
def find_target_branch
@@ -72,10 +76,11 @@ module MergeRequests
params[:target_branch].present?
end
- def branches_valid?
+ def projects_and_branches_valid?
+ return false if source_project.nil? || target_project.nil?
return false unless source_branch_specified? || target_branch_specified?
- validate_branches
+ validate_projects_and_branches
errors.blank?
end
@@ -94,7 +99,12 @@ module MergeRequests
end
end
- def validate_branches
+ def validate_projects_and_branches
+ merge_request.validate_target_project
+ merge_request.validate_fork
+
+ return if errors.any?
+
add_error('You must select source and target branch') unless branches_present?
add_error('You must select different branches') if same_source_and_target?
add_error("Source branch \"#{source_branch}\" does not exist") unless source_branch_exists?
diff --git a/app/services/merge_requests/update_service.rb b/app/services/merge_requests/update_service.rb
index 33d8299c8b6..86a04587f79 100644
--- a/app/services/merge_requests/update_service.rb
+++ b/app/services/merge_requests/update_service.rb
@@ -46,11 +46,13 @@ module MergeRequests
end
if merge_request.previous_changes.include?('assignee_id')
+ reassigned_merge_request_args = [merge_request, current_user]
+
old_assignee_id = merge_request.previous_changes['assignee_id'].first
- old_assignee = User.find(old_assignee_id) if old_assignee_id
+ reassigned_merge_request_args << User.find(old_assignee_id) if old_assignee_id
create_assignee_note(merge_request)
- notification_service.async.reassigned_merge_request(merge_request, current_user, old_assignee)
+ notification_service.async.reassigned_merge_request(*reassigned_merge_request_args)
todo_service.reassigned_merge_request(merge_request, current_user)
end
diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb
index ff035fea216..e1cf327209b 100644
--- a/app/services/notification_service.rb
+++ b/app/services/notification_service.rb
@@ -188,7 +188,7 @@ class NotificationService
# * merge_request assignee if their notification level is not Disabled
# * users with custom level checked with "reassign merge request"
#
- def reassigned_merge_request(merge_request, current_user, previous_assignee)
+ def reassigned_merge_request(merge_request, current_user, previous_assignee = nil)
recipients = NotificationRecipientService.build_recipients(
merge_request,
current_user,
diff --git a/app/services/projects/lfs_pointers/lfs_download_service.rb b/app/services/projects/lfs_pointers/lfs_download_service.rb
index f9b9781ad5f..b5128443435 100644
--- a/app/services/projects/lfs_pointers/lfs_download_service.rb
+++ b/app/services/projects/lfs_pointers/lfs_download_service.rb
@@ -12,28 +12,43 @@ module Projects
return if LfsObject.exists?(oid: oid)
- sanitized_uri = Gitlab::UrlSanitizer.new(url)
- Gitlab::UrlBlocker.validate!(sanitized_uri.sanitized_url, protocols: VALID_PROTOCOLS)
+ sanitized_uri = sanitize_url!(url)
with_tmp_file(oid) do |file|
- size = download_and_save_file(file, sanitized_uri)
- lfs_object = LfsObject.new(oid: oid, size: size, file: file)
+ download_and_save_file(file, sanitized_uri)
+ lfs_object = LfsObject.new(oid: oid, size: file.size, file: file)
project.all_lfs_objects << lfs_object
end
+ rescue Gitlab::UrlBlocker::BlockedUrlError => e
+ Rails.logger.error("LFS file with oid #{oid} couldn't be downloaded: #{e.message}")
rescue StandardError => e
- Rails.logger.error("LFS file with oid #{oid} could't be downloaded from #{sanitized_uri.sanitized_url}: #{e.message}")
+ Rails.logger.error("LFS file with oid #{oid} couldn't be downloaded from #{sanitized_uri.sanitized_url}: #{e.message}")
end
# rubocop: enable CodeReuse/ActiveRecord
private
+ def sanitize_url!(url)
+ Gitlab::UrlSanitizer.new(url).tap do |sanitized_uri|
+ # Just validate that HTTP/HTTPS protocols are used. The
+ # subsequent Gitlab::HTTP.get call will do network checks
+ # based on the settings.
+ Gitlab::UrlBlocker.validate!(sanitized_uri.sanitized_url,
+ protocols: VALID_PROTOCOLS)
+ end
+ end
+
def download_and_save_file(file, sanitized_uri)
- IO.copy_stream(open(sanitized_uri.sanitized_url, headers(sanitized_uri)), file) # rubocop:disable Security/Open
+ response = Gitlab::HTTP.get(sanitized_uri.sanitized_url, headers(sanitized_uri)) do |fragment|
+ file.write(fragment)
+ end
+
+ raise StandardError, "Received error code #{response.code}" unless response.success?
end
def headers(sanitized_uri)
- {}.tap do |headers|
+ query_options.tap do |headers|
credentials = sanitized_uri.credentials
if credentials[:user].present? || credentials[:password].present?
@@ -43,10 +58,14 @@ module Projects
end
end
+ def query_options
+ { stream_body: true }
+ end
+
def with_tmp_file(oid)
create_tmp_storage_dir
- File.open(File.join(tmp_storage_dir, oid), 'w') { |file| yield file }
+ File.open(File.join(tmp_storage_dir, oid), 'wb') { |file| yield file }
end
def create_tmp_storage_dir
diff --git a/app/services/projects/update_service.rb b/app/services/projects/update_service.rb
index 93e48fc0199..dd1b9680ece 100644
--- a/app/services/projects/update_service.rb
+++ b/app/services/projects/update_service.rb
@@ -61,9 +61,9 @@ module Projects
if project.previous_changes.include?(:visibility_level) && project.private?
# don't enqueue immediately to prevent todos removal in case of a mistake
- TodosDestroyer::ProjectPrivateWorker.perform_in(1.hour, project.id)
+ TodosDestroyer::ProjectPrivateWorker.perform_in(Todo::WAIT_FOR_DELETE, project.id)
elsif (project_changed_feature_keys & todos_features_changes).present?
- TodosDestroyer::PrivateFeaturesWorker.perform_in(1.hour, project.id)
+ TodosDestroyer::PrivateFeaturesWorker.perform_in(Todo::WAIT_FOR_DELETE, project.id)
end
if project.previous_changes.include?('path')
diff --git a/app/views/dashboard/milestones/_milestone.html.haml b/app/views/dashboard/milestones/_milestone.html.haml
index b876d6fd1f3..89212eb6bf9 100644
--- a/app/views/dashboard/milestones/_milestone.html.haml
+++ b/app/views/dashboard/milestones/_milestone.html.haml
@@ -1,5 +1,5 @@
= render 'shared/milestones/milestone',
- milestone_path: group_or_dashboard_milestone_path(milestone),
+ milestone_path: group_or_project_milestone_path(milestone),
issues_path: issues_dashboard_path(milestone_title: milestone.title),
merge_requests_path: merge_requests_dashboard_path(milestone_title: milestone.title),
milestone: milestone,
diff --git a/app/views/events/_events.html.haml b/app/views/events/_events.html.haml
index 68c19df092d..6ae4c334f7f 100644
--- a/app/views/events/_events.html.haml
+++ b/app/views/events/_events.html.haml
@@ -1 +1,4 @@
-= render partial: 'events/event', collection: @events
+- if @events.present?
+ = render partial: 'events/event', collection: @events
+- else
+ .nothing-here-block= _("No activities found")
diff --git a/app/views/projects/services/prometheus/_metrics.html.haml b/app/views/projects/services/prometheus/_metrics.html.haml
index 597c029f755..a1d74b91002 100644
--- a/app/views/projects/services/prometheus/_metrics.html.haml
+++ b/app/views/projects/services/prometheus/_metrics.html.haml
@@ -1,6 +1,6 @@
- project = local_assigns.fetch(:project)
-.card.js-panel-monitored-metrics{ data: { active_metrics: active_common_project_prometheus_metrics_path(project, :json), metrics_help_path: help_page_path('user/project/integrations/prometheus_library/metrics') } }
+.card.js-panel-monitored-metrics{ data: { active_metrics: active_common_project_prometheus_metrics_path(project, :json), metrics_help_path: help_page_path('user/project/integrations/prometheus_library/index') } }
.card-header
= s_('PrometheusService|Common metrics')
%span.badge.badge-pill.js-monitored-count 0
diff --git a/app/views/projects/services/prometheus/_show.html.haml b/app/views/projects/services/prometheus/_show.html.haml
index 1d0b0265bb7..9d4574c4590 100644
--- a/app/views/projects/services/prometheus/_show.html.haml
+++ b/app/views/projects/services/prometheus/_show.html.haml
@@ -4,7 +4,7 @@
= s_('PrometheusService|Metrics')
%p
= s_('PrometheusService|Common metrics are automatically monitored based on a library of metrics from popular exporters.')
- = link_to s_('PrometheusService|More information'), help_page_path('user/project/integrations/prometheus_library/metrics'), target: '_blank', rel: "noopener noreferrer"
+ = link_to s_('PrometheusService|More information'), help_page_path('user/project/integrations/prometheus_library/index'), target: '_blank', rel: "noopener noreferrer"
.col-lg-9
= render 'projects/services/prometheus/metrics', project: @project
diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml
index ed7fefba56d..40b8374848e 100644
--- a/app/views/shared/milestones/_milestone.html.haml
+++ b/app/views/shared/milestones/_milestone.html.haml
@@ -1,5 +1,5 @@
- dashboard = local_assigns[:dashboard]
-- custom_dom_id = dom_id(milestone.try(:milestones) ? milestone.milestones.first : milestone)
+- custom_dom_id = dom_id(milestone.try(:milestone) ? milestone.milestone : milestone)
- milestone_type = milestone.group_milestone? ? 'Group Milestone' : 'Project Milestone'
%li{ class: "milestone milestone-#{milestone.closed? ? 'closed' : 'open'}", id: custom_dom_id }
@@ -21,10 +21,12 @@
= milestone.group.full_name
- if milestone.legacy_group_milestone?
.projects
- - milestone.milestones.each do |milestone|
- = link_to milestone_path(milestone) do
- %span.label-badge.label-badge-blue.d-inline-block.append-bottom-5
- = dashboard ? milestone.project.full_name : milestone.project.name
+ - link_to milestone_path(milestone.milestone) do
+ %span.label-badge.label-badge-blue.d-inline-block.append-bottom-5
+ = dashboard ? milestone.project.full_name : milestone.project.name
+ - if milestone.project
+ .label-badge.label-badge-gray.d-inline-block
+ = milestone.project.full_name
.col-sm-4.milestone-progress
= milestone_progress_bar(milestone)
@@ -58,5 +60,5 @@
- else
= link_to 'Close Milestone', group_milestone_route(milestone, {state_event: :close }), method: :put, class: "btn btn-sm btn-grouped btn-close"
- if dashboard
- .status-box.status-box-milestone
+ .label-badge.label-badge-gray
= milestone_type
diff --git a/app/views/shared/milestones/_top.html.haml b/app/views/shared/milestones/_top.html.haml
index 0499b04a482..55b1c14022f 100644
--- a/app/views/shared/milestones/_top.html.haml
+++ b/app/views/shared/milestones/_top.html.haml
@@ -62,20 +62,19 @@
%th Open issues
%th State
%th Due date
- - milestone.milestones.each do |ms|
%tr
%td
- - project_name = group ? ms.project.name : ms.project.full_name
- = link_to project_name, project_milestone_path(ms.project, ms)
+ - project_name = group ? milestone.project.name : milestone.project.full_name
+ = link_to project_name, milestone_path(milestone.milestone)
%td
- = ms.issues_visible_to_user(current_user).opened.count
+ = milestone.milestone.issues_visible_to_user(current_user).opened.count
%td
- - if ms.closed?
+ - if milestone.closed?
Closed
- else
Open
%td
- = ms.expires_at
+ = milestone.expires_at
- elsif milestone.group_milestone?
%br
View
diff --git a/app/views/shared/snippets/_header.html.haml b/app/views/shared/snippets/_header.html.haml
index 10bfc30492a..a43296aa806 100644
--- a/app/views/shared/snippets/_header.html.haml
+++ b/app/views/shared/snippets/_header.html.haml
@@ -30,7 +30,7 @@
- if @snippet.updated_at != @snippet.created_at
= edited_time_ago_with_tooltip(@snippet, placement: 'bottom', html_class: 'snippet-edited-ago', exclude_author: true)
- - if public_snippet?
+ - if @snippet.embeddable?
.embed-snippet
.input-group
.input-group-prepend
diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml
index dd2cd36eac2..8da63a29ca6 100644
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -71,7 +71,7 @@
= icon('twitter-square')
- unless @user.website_url.blank?
.profile-link-holder.middle-dot-divider
- = link_to @user.short_website_url, @user.full_website_url, class: 'text-link', target: '_blank', rel: 'noopener noreferrer nofollow'
+ = link_to @user.short_website_url, @user.full_website_url, class: 'text-link', target: '_blank', rel: 'me noopener noreferrer nofollow'
- unless @user.location.blank?
.profile-link-holder.middle-dot-divider
= icon('map-marker')
diff --git a/app/workers/mail_scheduler/notification_service_worker.rb b/app/workers/mail_scheduler/notification_service_worker.rb
index 4726e416182..c8ccaf0c487 100644
--- a/app/workers/mail_scheduler/notification_service_worker.rb
+++ b/app/workers/mail_scheduler/notification_service_worker.rb
@@ -8,14 +8,35 @@ module MailScheduler
include MailSchedulerQueue
def perform(meth, *args)
- deserialized_args = ActiveJob::Arguments.deserialize(args)
+ check_arguments!(args)
+ deserialized_args = ActiveJob::Arguments.deserialize(args)
notification_service.public_send(meth, *deserialized_args) # rubocop:disable GitlabSecurity/PublicSend
rescue ActiveJob::DeserializationError
+ # No-op.
+ # This exception gets raised when an argument
+ # is correct (deserializeable), but it still cannot be deserialized.
+ # This can happen when an object has been deleted after
+ # rails passes this job to sidekiq, but before
+ # sidekiq gets it for execution.
+ # In this case just do nothing.
end
def self.perform_async(*args)
super(*ActiveJob::Arguments.serialize(args))
end
+
+ private
+
+ # If an argument is in the ActiveJob::Arguments::TYPE_WHITELIST list,
+ # it means the argument cannot be deserialized.
+ # Which means there's something wrong with our code.
+ def check_arguments!(args)
+ args.each do |arg|
+ if arg.class.in?(ActiveJob::Arguments::TYPE_WHITELIST)
+ raise(ArgumentError, "Argument `#{arg}` cannot be deserialized because of its type")
+ end
+ end
+ end
end
end
diff --git a/app/workers/post_receive.rb b/app/workers/post_receive.rb
index 72a1733a2a8..bbd4ab159e4 100644
--- a/app/workers/post_receive.rb
+++ b/app/workers/post_receive.rb
@@ -3,7 +3,7 @@
class PostReceive
include ApplicationWorker
- def perform(gl_repository, identifier, changes)
+ def perform(gl_repository, identifier, changes, push_options = [])
project, is_wiki = Gitlab::GlRepository.parse(gl_repository)
if project.nil?
@@ -15,7 +15,7 @@ class PostReceive
# Use Sidekiq.logger so arguments can be correlated with execution
# time and thread ID's.
Sidekiq.logger.info "changes: #{changes.inspect}" if ENV['SIDEKIQ_LOG_ARGUMENTS']
- post_received = Gitlab::GitPostReceive.new(project, identifier, changes)
+ post_received = Gitlab::GitPostReceive.new(project, identifier, changes, push_options)
if is_wiki
process_wiki_changes(post_received)
@@ -38,9 +38,21 @@ class PostReceive
post_received.changes_refs do |oldrev, newrev, ref|
if Gitlab::Git.tag_ref?(ref)
- GitTagPushService.new(post_received.project, @user, oldrev: oldrev, newrev: newrev, ref: ref).execute
+ GitTagPushService.new(
+ post_received.project,
+ @user,
+ oldrev: oldrev,
+ newrev: newrev,
+ ref: ref,
+ push_options: post_received.push_options).execute
elsif Gitlab::Git.branch_ref?(ref)
- GitPushService.new(post_received.project, @user, oldrev: oldrev, newrev: newrev, ref: ref).execute
+ GitPushService.new(
+ post_received.project,
+ @user,
+ oldrev: oldrev,
+ newrev: newrev,
+ ref: ref,
+ push_options: post_received.push_options).execute
end
changes << Gitlab::DataBuilder::Repository.single_change(oldrev, newrev, ref)
diff --git a/changelogs/unreleased/18667-handle-push-opts.yml b/changelogs/unreleased/18667-handle-push-opts.yml
new file mode 100644
index 00000000000..204293476f6
--- /dev/null
+++ b/changelogs/unreleased/18667-handle-push-opts.yml
@@ -0,0 +1,5 @@
+---
+title: Handle ci.skip push option
+merge_request: 15643
+author: Jonathon Reinhart
+type: added
diff --git a/changelogs/unreleased/51668-fix-line-numbers.yml b/changelogs/unreleased/51668-fix-line-numbers.yml
deleted file mode 100644
index ac6e45e3cc7..00000000000
--- a/changelogs/unreleased/51668-fix-line-numbers.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Adjust line-height of blame view line numbers
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/54206-show-the-activity-filter-dropdown-in-discussion-tab-only.yml b/changelogs/unreleased/54206-show-the-activity-filter-dropdown-in-discussion-tab-only.yml
new file mode 100644
index 00000000000..e29987b0935
--- /dev/null
+++ b/changelogs/unreleased/54206-show-the-activity-filter-dropdown-in-discussion-tab-only.yml
@@ -0,0 +1,5 @@
+---
+title: Discussion filter only displayed in discussions tab for merge requests
+merge_request: 24082
+author:
+type: changed
diff --git a/changelogs/unreleased/54427-label-xss.yml b/changelogs/unreleased/54427-label-xss.yml
new file mode 100644
index 00000000000..090d1832af2
--- /dev/null
+++ b/changelogs/unreleased/54427-label-xss.yml
@@ -0,0 +1,5 @@
+---
+title: Escape html entities in LabelReferenceFilter when no label found
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/54844-report-syntax-dep-scan-ado.yml b/changelogs/unreleased/54844-report-syntax-dep-scan-ado.yml
new file mode 100644
index 00000000000..95fc5cb804d
--- /dev/null
+++ b/changelogs/unreleased/54844-report-syntax-dep-scan-ado.yml
@@ -0,0 +1,5 @@
+---
+title: Use reports syntax for Dependency scanning in Auto DevOps
+merge_request: 24081
+author:
+type: added
diff --git a/changelogs/unreleased/54953-fix-commit_email_hostname-accessor-in-fake_application_settings.yml b/changelogs/unreleased/54953-fix-commit_email_hostname-accessor-in-fake_application_settings.yml
deleted file mode 100644
index 623b3a7319c..00000000000
--- a/changelogs/unreleased/54953-fix-commit_email_hostname-accessor-in-fake_application_settings.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix a 500 error that could occur until all migrations are done
-merge_request: 23939
-author:
-type: fixed
diff --git a/changelogs/unreleased/55103-hide-group-cluster-features.yml b/changelogs/unreleased/55103-hide-group-cluster-features.yml
deleted file mode 100644
index fbe780d6f01..00000000000
--- a/changelogs/unreleased/55103-hide-group-cluster-features.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Hide cluster features that don't work yet with Group Clusters
-merge_request: 23935
-author:
-type: fixed
diff --git a/changelogs/unreleased/55266-fix-incorrect-due-date-parsing.yml b/changelogs/unreleased/55266-fix-incorrect-due-date-parsing.yml
new file mode 100644
index 00000000000..62a57085192
--- /dev/null
+++ b/changelogs/unreleased/55266-fix-incorrect-due-date-parsing.yml
@@ -0,0 +1,5 @@
+---
+title: Use 'parsePikadayDate' to parse due date string
+merge_request: 24045
+author:
+type: fixed
diff --git a/changelogs/unreleased/55369-update-milestone-sort-to-say-say-milestone-due-date.yml b/changelogs/unreleased/55369-update-milestone-sort-to-say-say-milestone-due-date.yml
new file mode 100644
index 00000000000..7476b9caa93
--- /dev/null
+++ b/changelogs/unreleased/55369-update-milestone-sort-to-say-say-milestone-due-date.yml
@@ -0,0 +1,5 @@
+---
+title: Renames Milestone sort into Milestone due date
+merge_request: 24080
+author: Jacopo Beschi @jacopo-beschi
+type: changed
diff --git a/changelogs/unreleased/55755-user-activity-is-stuck-loading-when-there-is-none.yml b/changelogs/unreleased/55755-user-activity-is-stuck-loading-when-there-is-none.yml
new file mode 100644
index 00000000000..5362a781281
--- /dev/null
+++ b/changelogs/unreleased/55755-user-activity-is-stuck-loading-when-there-is-none.yml
@@ -0,0 +1,5 @@
+---
+title: Hide spinner on empty activites list on user profile overview
+merge_request: 24063
+author:
+type: other
diff --git a/changelogs/unreleased/55836-docs-fix-navigation-style-in-docs.yml b/changelogs/unreleased/55836-docs-fix-navigation-style-in-docs.yml
new file mode 100644
index 00000000000..2ac3599175b
--- /dev/null
+++ b/changelogs/unreleased/55836-docs-fix-navigation-style-in-docs.yml
@@ -0,0 +1,5 @@
+---
+title: Fix navigation style in docs
+merge_request: 24090
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/55838-remove-gem-install-bundler-from-docker-based-ruby-environments.yml b/changelogs/unreleased/55838-remove-gem-install-bundler-from-docker-based-ruby-environments.yml
new file mode 100644
index 00000000000..08f60d205df
--- /dev/null
+++ b/changelogs/unreleased/55838-remove-gem-install-bundler-from-docker-based-ruby-environments.yml
@@ -0,0 +1,5 @@
+---
+title: Remove gem install bundler from Docker-based Ruby environments
+merge_request: 24093
+author: Takuya Noguchi
+type: other
diff --git a/changelogs/unreleased/55883-modal-header-titles-have-an-unnecessary-top-margin.yml b/changelogs/unreleased/55883-modal-header-titles-have-an-unnecessary-top-margin.yml
new file mode 100644
index 00000000000..7dc783cc2b8
--- /dev/null
+++ b/changelogs/unreleased/55883-modal-header-titles-have-an-unnecessary-top-margin.yml
@@ -0,0 +1,5 @@
+---
+title: Remove top margin in modal header titles
+merge_request: 24108
+author:
+type: fixed
diff --git a/changelogs/unreleased/allow-basic-auth-on-go-get-middleware.yml b/changelogs/unreleased/allow-basic-auth-on-go-get-middleware.yml
new file mode 100644
index 00000000000..fda3fdc28cf
--- /dev/null
+++ b/changelogs/unreleased/allow-basic-auth-on-go-get-middleware.yml
@@ -0,0 +1,5 @@
+---
+title: Allow basic authentication on go get middleware
+merge_request: 23497
+author: Morty Choi @mortyccp
+type: changed
diff --git a/changelogs/unreleased/blackst0ne-bump-rails-cve-2018-16476.yml b/changelogs/unreleased/blackst0ne-bump-rails-cve-2018-16476.yml
new file mode 100644
index 00000000000..dfa94c69ce0
--- /dev/null
+++ b/changelogs/unreleased/blackst0ne-bump-rails-cve-2018-16476.yml
@@ -0,0 +1,5 @@
+---
+title: Bump Ruby on Rails to 5.0.7.1
+merge_request: 23396
+author: "@blackst0ne"
+type: security
diff --git a/changelogs/unreleased/ccr-49289_milestone_link.yml b/changelogs/unreleased/ccr-49289_milestone_link.yml
new file mode 100644
index 00000000000..14c09752a24
--- /dev/null
+++ b/changelogs/unreleased/ccr-49289_milestone_link.yml
@@ -0,0 +1,5 @@
+---
+title: Add project milestone link
+merge_request: 22552
+author:
+type: added
diff --git a/changelogs/unreleased/deprecated-insert-sql.yml b/changelogs/unreleased/deprecated-insert-sql.yml
new file mode 100644
index 00000000000..ad21fbd9dde
--- /dev/null
+++ b/changelogs/unreleased/deprecated-insert-sql.yml
@@ -0,0 +1,5 @@
+---
+title: 'Fix deprecation: insert_sql is deprecated and will be removed'
+merge_request: 23944
+author: Jasper Maes
+type: other
diff --git a/changelogs/unreleased/deprecated-positional-spec-arguments.yml b/changelogs/unreleased/deprecated-positional-spec-arguments.yml
new file mode 100644
index 00000000000..8e541df1ad4
--- /dev/null
+++ b/changelogs/unreleased/deprecated-positional-spec-arguments.yml
@@ -0,0 +1,5 @@
+---
+title: 'Fix deprecation: Using positional arguments in integration tests'
+merge_request: 24110
+author: Jasper Maes
+type: other
diff --git a/changelogs/unreleased/deprecated-redirect-back.yml b/changelogs/unreleased/deprecated-redirect-back.yml
new file mode 100644
index 00000000000..7fc567fbdb5
--- /dev/null
+++ b/changelogs/unreleased/deprecated-redirect-back.yml
@@ -0,0 +1,5 @@
+---
+title: 'Fix deprecation: redirect_to :back is deprecated'
+merge_request: 23943
+author: Jasper Maes
+type: other
diff --git a/changelogs/unreleased/fj-55781-fix-api-blob-content-disposition.yml b/changelogs/unreleased/fj-55781-fix-api-blob-content-disposition.yml
deleted file mode 100644
index 2e1d9889b22..00000000000
--- a/changelogs/unreleased/fj-55781-fix-api-blob-content-disposition.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix content-disposition in blobs and files API endpoint
-merge_request: 24078
-author:
-type: fixed
diff --git a/changelogs/unreleased/markdown-toolbar-btn-fix.yml b/changelogs/unreleased/markdown-toolbar-btn-fix.yml
deleted file mode 100644
index eefb4d19f86..00000000000
--- a/changelogs/unreleased/markdown-toolbar-btn-fix.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fixed markdown toolbar buttons
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/s3-directories-get.yml b/changelogs/unreleased/s3-directories-get.yml
new file mode 100644
index 00000000000..9f76af2bb09
--- /dev/null
+++ b/changelogs/unreleased/s3-directories-get.yml
@@ -0,0 +1,6 @@
+---
+title: Allow 'rake gitlab:cleanup:remote_upload_files' to read bucket files without
+ having permissions to see all buckets.
+merge_request: 23981
+author:
+type: fixed
diff --git a/changelogs/unreleased/security-48259-private-snippet.yml b/changelogs/unreleased/security-48259-private-snippet.yml
new file mode 100644
index 00000000000..6cf1e5dc694
--- /dev/null
+++ b/changelogs/unreleased/security-48259-private-snippet.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent private snippets from being embeddable
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-53543-user-keeps-access-to-mr-issue-when-removed-from-team.yml b/changelogs/unreleased/security-53543-user-keeps-access-to-mr-issue-when-removed-from-team.yml
new file mode 100644
index 00000000000..ab12ba539c1
--- /dev/null
+++ b/changelogs/unreleased/security-53543-user-keeps-access-to-mr-issue-when-removed-from-team.yml
@@ -0,0 +1,5 @@
+---
+title: Issuable no longer is visible to users when project can't be viewed
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-54377-label-milestone-name-xss.yml b/changelogs/unreleased/security-54377-label-milestone-name-xss.yml
new file mode 100644
index 00000000000..76589b2eb4f
--- /dev/null
+++ b/changelogs/unreleased/security-54377-label-milestone-name-xss.yml
@@ -0,0 +1,5 @@
+---
+title: Escape label and milestone titles to prevent XSS in GFM autocomplete
+merge_request: 2693
+author:
+type: security
diff --git a/changelogs/unreleased/security-bvl-fix-cross-project-mr-exposure.yml b/changelogs/unreleased/security-bvl-fix-cross-project-mr-exposure.yml
new file mode 100644
index 00000000000..11aae4428fb
--- /dev/null
+++ b/changelogs/unreleased/security-bvl-fix-cross-project-mr-exposure.yml
@@ -0,0 +1,5 @@
+---
+title: Don't expose cross project repositories through diffs when creating merge reqeusts
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-fix-ssrf-import-url-remote-mirror.yml b/changelogs/unreleased/security-fix-ssrf-import-url-remote-mirror.yml
new file mode 100644
index 00000000000..7ba7aa21090
--- /dev/null
+++ b/changelogs/unreleased/security-fix-ssrf-import-url-remote-mirror.yml
@@ -0,0 +1,5 @@
+---
+title: Fix SSRF with import_url and remote mirror url
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-master-group-cicd-settings-accessible-to-maintainer.yml b/changelogs/unreleased/security-master-group-cicd-settings-accessible-to-maintainer.yml
new file mode 100644
index 00000000000..5586fa6cd8e
--- /dev/null
+++ b/changelogs/unreleased/security-master-group-cicd-settings-accessible-to-maintainer.yml
@@ -0,0 +1,5 @@
+---
+title: Allow changing group CI/CD settings only for owners.
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-master-guests-jobs-api.yml b/changelogs/unreleased/security-master-guests-jobs-api.yml
new file mode 100644
index 00000000000..83022e91aca
--- /dev/null
+++ b/changelogs/unreleased/security-master-guests-jobs-api.yml
@@ -0,0 +1,5 @@
+---
+title: Authorize before reading job information via API.
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-master-secret-ci-variables-exposed.yml b/changelogs/unreleased/security-master-secret-ci-variables-exposed.yml
new file mode 100644
index 00000000000..702181065f5
--- /dev/null
+++ b/changelogs/unreleased/security-master-secret-ci-variables-exposed.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent leaking protected variables for ambiguous refs.
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-master-url-rel.yml b/changelogs/unreleased/security-master-url-rel.yml
new file mode 100644
index 00000000000..75f599f6bcd
--- /dev/null
+++ b/changelogs/unreleased/security-master-url-rel.yml
@@ -0,0 +1,5 @@
+---
+title: Set URL rel attribute for broken URLs.
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-refs-available-to-project-guest.yml b/changelogs/unreleased/security-refs-available-to-project-guest.yml
new file mode 100644
index 00000000000..eb6804c52d3
--- /dev/null
+++ b/changelogs/unreleased/security-refs-available-to-project-guest.yml
@@ -0,0 +1,5 @@
+---
+title: Project guests no longer are able to see refs page
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/security-todos_not_redacted_for_guests.yml b/changelogs/unreleased/security-todos_not_redacted_for_guests.yml
new file mode 100644
index 00000000000..be0ae9a7193
--- /dev/null
+++ b/changelogs/unreleased/security-todos_not_redacted_for_guests.yml
@@ -0,0 +1,5 @@
+---
+title: Delete confidential todos for user when downgraded to Guest
+merge_request:
+author:
+type: security
diff --git a/changelogs/unreleased/sh-bump-omniauth-google-gem.yml b/changelogs/unreleased/sh-bump-omniauth-google-gem.yml
new file mode 100644
index 00000000000..2b31a55f8b2
--- /dev/null
+++ b/changelogs/unreleased/sh-bump-omniauth-google-gem.yml
@@ -0,0 +1,5 @@
+---
+title: Upgrade Omniauth and JWT gems to switch away from Google+ API
+merge_request: 24068
+author:
+type: changed
diff --git a/changelogs/unreleased/sh-drop-webhooks-project-export.yml b/changelogs/unreleased/sh-drop-webhooks-project-export.yml
new file mode 100644
index 00000000000..217373bce66
--- /dev/null
+++ b/changelogs/unreleased/sh-drop-webhooks-project-export.yml
@@ -0,0 +1,5 @@
+---
+title: Drop Webhooks from project import/export config
+merge_request: 24121
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-fix-clone-geo-dropdown.yml b/changelogs/unreleased/sh-fix-clone-geo-dropdown.yml
deleted file mode 100644
index 1c0cbdc3a2c..00000000000
--- a/changelogs/unreleased/sh-fix-clone-geo-dropdown.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix clone dropdown parent inheritance issues in HAML
-merge_request: 24029
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-http-clone-panel.yml b/changelogs/unreleased/sh-fix-http-clone-panel.yml
deleted file mode 100644
index ab220bd5076..00000000000
--- a/changelogs/unreleased/sh-fix-http-clone-panel.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix missing Git clone button when protocol restriction setting enabled
-merge_request: 24015
-author:
-type: fixed
diff --git a/changelogs/unreleased/sh-fix-issue-55822.yml b/changelogs/unreleased/sh-fix-issue-55822.yml
new file mode 100644
index 00000000000..1267b2ace2f
--- /dev/null
+++ b/changelogs/unreleased/sh-fix-issue-55822.yml
@@ -0,0 +1,5 @@
+---
+title: Fix commit SHA not showing in merge request compare dropdown
+merge_request: 24084
+author:
+type: fixed
diff --git a/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-1-43.yml b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-1-43.yml
new file mode 100644
index 00000000000..24471b028b1
--- /dev/null
+++ b/changelogs/unreleased/update-gitlab-runner-helm-chart-to-0-1-43.yml
@@ -0,0 +1,5 @@
+---
+title: Update GitLab Runner Helm Chart to 0.1.43
+merge_request: 24083
+author:
+type: other
diff --git a/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb b/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb
index 90d869a8c10..8de8b3bcc2e 100644
--- a/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb
+++ b/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb
@@ -46,7 +46,7 @@ class CreateMissingNamespaceForInternalUsers < ActiveRecord::Migration[4.2]
end
insert_query = "INSERT INTO namespaces(owner_id, path, name, created_at, updated_at) VALUES(#{user_id}, '#{path}', '#{path}', NOW(), NOW())"
- namespace_id = connection.insert_sql(insert_query)
+ namespace_id = connection.insert(insert_query)
create_route(namespace_id)
end
diff --git a/doc/administration/job_artifacts.md b/doc/administration/job_artifacts.md
index a1ea78b64bd..25ae535d1ec 100644
--- a/doc/administration/job_artifacts.md
+++ b/doc/administration/job_artifacts.md
@@ -165,12 +165,6 @@ _The artifacts are stored by default in
gitlab-rake gitlab:artifacts:migrate
```
- Currently this has to be executed manually and it will allow you to
- migrate the existing artifacts to the object storage, but all new
- artifacts will still be stored on the local disk. In the future
- you will be given an option to define a default storage artifacts for all
- new files.
-
---
**In installations from source:**
@@ -201,12 +195,6 @@ _The artifacts are stored by default in
sudo -u git -H bundle exec rake gitlab:artifacts:migrate RAILS_ENV=production
```
- Currently this has to be executed manually and it will allow you to
- migrate the existing artifacts to the object storage, but all new
- artifacts will still be stored on the local disk. In the future
- you will be given an option to define a default storage artifacts for all
- new files.
-
## Expiring artifacts
If an expiry date is used for the artifacts, they are marked for deletion
diff --git a/doc/administration/monitoring/performance/request_profiling.md b/doc/administration/monitoring/performance/request_profiling.md
index dfd9be3d04c..726882fbb87 100644
--- a/doc/administration/monitoring/performance/request_profiling.md
+++ b/doc/administration/monitoring/performance/request_profiling.md
@@ -2,14 +2,14 @@
## Procedure
-1. Grab the profiling token from `Monitoring > Requests Profiles` admin page
+1. Grab the profiling token from **Monitoring > Requests Profiles** admin page
(highlighted in a blue in the image below).
![Profile token](img/request_profiling_token.png)
1. Pass the header `X-Profile-Token: <token>` to the request you want to profile. You can use:
- Browser extensions. For example, [ModHeader](https://chrome.google.com/webstore/detail/modheader/idgpnmonknjnojddfkpgkljpfnnfcklj) Chrome extension.
- `curl`. For example, `curl --header 'X-Profile-Token: <token>' https://gitlab.example.com/group/project`.
1. Once request is finished (which will take a little longer than usual), you can
- view the profiling output from `Monitoring > Requests Profiles` admin page.
+ view the profiling output from **Monitoring > Requests Profiles** admin page.
![Profiling output](img/request_profile_result.png)
## Cleaning up
diff --git a/doc/api/lint.md b/doc/api/lint.md
index bd5a216a99d..c37a8bff749 100644
--- a/doc/api/lint.md
+++ b/doc/api/lint.md
@@ -13,7 +13,7 @@ POST /lint
| `content` | string | yes | the .gitlab-ci.yaml content|
```bash
-curl --header "Content-Type: application/json" https://gitlab.example.com/api/v4/ci/lint --data '{"content": "{ \"image\": \"ruby:2.1\", \"services\": [\"postgres\"], \"before_script\": [\"gem install bundler\", \"bundle install\", \"bundle exec rake db:create\"], \"variables\": {\"DB_NAME\": \"postgres\"}, \"types\": [\"test\", \"deploy\", \"notify\"], \"rspec\": { \"script\": \"rake spec\", \"tags\": [\"ruby\", \"postgres\"], \"only\": [\"branches\"]}}"}'
+curl --header "Content-Type: application/json" https://gitlab.example.com/api/v4/ci/lint --data '{"content": "{ \"image\": \"ruby:2.6\", \"services\": [\"postgres\"], \"before_script\": [\"bundle install\", \"bundle exec rake db:create\"], \"variables\": {\"DB_NAME\": \"postgres\"}, \"types\": [\"test\", \"deploy\", \"notify\"], \"rspec\": { \"script\": \"rake spec\", \"tags\": [\"ruby\", \"postgres\"], \"only\": [\"branches\"]}}"}'
```
Be sure to copy paste the exact contents of `.gitlab-ci.yml` as YAML is very picky about indentation and spaces.
diff --git a/doc/api/services.md b/doc/api/services.md
index f122bac6f1f..c4edaa17815 100644
--- a/doc/api/services.md
+++ b/doc/api/services.md
@@ -573,7 +573,7 @@ DELETE /projects/:id/services/jira
## Kubernetes
-Kubernetes / Openshift integration
+Kubernetes / OpenShift integration
CAUTION: **Warning:**
Kubernetes service integration has been deprecated in GitLab 10.3. API service endpoints will continue to work as long as the Kubernetes service is active, however if the service is inactive API endpoints will automatically return a `400 Bad Request`. Read [GitLab 10.3 release post](https://about.gitlab.com/2017/12/22/gitlab-10-3-released/#kubernetes-integration-service) for more information.
diff --git a/doc/api/templates/gitlab_ci_ymls.md b/doc/api/templates/gitlab_ci_ymls.md
index cecfc8cd9b9..11ec7360e06 100644
--- a/doc/api/templates/gitlab_ci_ymls.md
+++ b/doc/api/templates/gitlab_ci_ymls.md
@@ -120,6 +120,6 @@ Example response:
```json
{
"name": "Ruby",
- "content": "# This file is a template, and might need editing before it works on your project.\n# Official language image. Look for the different tagged releases at:\n# https://hub.docker.com/r/library/ruby/tags/\nimage: \"ruby:2.3\"\n\n# Pick zero or more services to be used on all builds.\n# Only needed when using a docker container to run your tests in.\n# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-service\nservices:\n - mysql:latest\n - redis:latest\n - postgres:latest\n\nvariables:\n POSTGRES_DB: database_name\n\n# Cache gems in between builds\ncache:\n paths:\n - vendor/ruby\n\n# This is a basic example for a gem or script which doesn't use\n# services such as redis or postgres\nbefore_script:\n - ruby -v # Print out ruby version for debugging\n # Uncomment next line if your rails app needs a JS runtime:\n # - apt-get update -q && apt-get install nodejs -yqq\n - gem install bundler --no-ri --no-rdoc # Bundler is not installed with the image\n - bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby\n\n# Optional - Delete if not using `rubocop`\nrubocop:\n script:\n - rubocop\n\nrspec:\n script:\n - rspec spec\n\nrails:\n variables:\n DATABASE_URL: \"postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB\"\n script:\n - bundle exec rake db:migrate\n - bundle exec rake db:seed\n - bundle exec rake test\n"
+ "content": "# This file is a template, and might need editing before it works on your project.\n# Official language image. Look for the different tagged releases at:\n# https://hub.docker.com/r/library/ruby/tags/\nimage: \"ruby:2.5\"\n\n# Pick zero or more services to be used on all builds.\n# Only needed when using a docker container to run your tests in.\n# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service\nservices:\n - mysql:latest\n - redis:latest\n - postgres:latest\n\nvariables:\n POSTGRES_DB: database_name\n\n# Cache gems in between builds\ncache:\n paths:\n - vendor/ruby\n\n# This is a basic example for a gem or script which doesn't use\n# services such as redis or postgres\nbefore_script:\n - ruby -v # Print out ruby version for debugging\n # Uncomment next line if your rails app needs a JS runtime:\n # - apt-get update -q && apt-get install nodejs -yqq\n - bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby\n\n# Optional - Delete if not using `rubocop`\nrubocop:\n script:\n - rubocop\n\nrspec:\n script:\n - rspec spec\n\nrails:\n variables:\n DATABASE_URL: \"postgresql://postgres:postgres@postgres:5432/$POSTGRES_DB\"\n script:\n - rails db:migrate\n - rails db:seed\n - rails test\n\n# This deploy job uses a simple deploy flow to Heroku, other providers, e.g. AWS Elastic Beanstalk\n# are supported too: https://github.com/travis-ci/dpl\ndeploy:\n type: deploy\n environment: production\n script:\n - gem install dpl\n - dpl --provider=heroku --app=$HEROKU_APP_NAME --api-key=$HEROKU_PRODUCTION_KEY\n"
}
```
diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md
index f93ccc4e3c1..495ec099111 100644
--- a/doc/ci/caching/index.md
+++ b/doc/ci/caching/index.md
@@ -300,7 +300,6 @@ cache:
before_script:
- ruby -v # Print out ruby version for debugging
- - gem install bundler --no-ri --no-rdoc # Bundler is not installed with the image
- bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby
rspec:
diff --git a/doc/ci/docker/using_kaniko.md b/doc/ci/docker/using_kaniko.md
index 66f0d429165..aa6b387bc58 100644
--- a/doc/ci/docker/using_kaniko.md
+++ b/doc/ci/docker/using_kaniko.md
@@ -57,3 +57,26 @@ build:
only:
- tags
```
+
+## Using a registry with a custom certificate
+
+When trying to push to a Docker registry that uses a certificate that is signed
+by a custom CA, you might get the following error:
+
+```sh
+$ /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --no-push
+INFO[0000] Downloading base image registry.gitlab.example.com/group/docker-image
+error building image: getting stage builder for stage 0: Get https://registry.gitlab.example.com/v2/: x509: certificate signed by unknown authority
+```
+
+This can be solved by adding your CA's certificate to the kaniko certificate
+store:
+
+```yaml
+ before_script:
+ - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
+ - |
+ echo "-----BEGIN CERTIFICATE-----
+ ...
+ -----END CERTIFICATE-----" >> /kaniko/ssl/certs/ca-certificates.crt
+```
diff --git a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
index ec0b5aaed09..b59271e400f 100644
--- a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
+++ b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
@@ -47,7 +47,7 @@ This project has three jobs:
## Store API keys
-You'll need to create two variables in `Settings > CI/CD > Variables` on your GitLab project settings:
+You'll need to create two variables in **Settings > CI/CD > Variables** in your GitLab project:
- `HEROKU_STAGING_API_KEY` - Heroku API key used to deploy staging app.
- `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app.
diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md
index bdc593493ea..1ec8a8c89c9 100644
--- a/doc/ci/quick_start/README.md
+++ b/doc/ci/quick_start/README.md
@@ -77,7 +77,7 @@ before_script:
- apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- ruby -v
- which ruby
- - gem install bundler --no-ri --no-rdoc
+ - gem install bundler --no-document
- bundle install --jobs $(nproc) "${FLAGS[@]}"
rspec:
diff --git a/doc/ci/services/mysql.md b/doc/ci/services/mysql.md
index b76f9618fc9..2902c30c7c0 100644
--- a/doc/ci/services/mysql.md
+++ b/doc/ci/services/mysql.md
@@ -16,7 +16,7 @@ services:
- mysql:latest
variables:
- # Configure mysql environment variables (https://hub.docker.com/r/_/mysql/)
+ # Configure mysql environment variables (https://hub.docker.com/_/mysql/)
MYSQL_DATABASE: el_duderino
MYSQL_ROOT_PASSWORD: mysql_strong_password
```
@@ -114,5 +114,5 @@ available [shared runners](../runners/README.md).
Want to hack on it? Simply fork it, commit and push your changes. Within a few
moments the changes will be picked by a public runner and the job will begin.
-[hub-mysql]: https://hub.docker.com/r/_/mysql/
+[hub-mysql]: https://hub.docker.com/_/mysql/
[mysql-example-repo]: https://gitlab.com/gitlab-examples/mysql
diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md
index 440254e58bd..5d87a5c0a1f 100644
--- a/doc/ci/yaml/README.md
+++ b/doc/ci/yaml/README.md
@@ -1660,7 +1660,7 @@ automatically fetched and evaluated along with the content of `.gitlab-ci.yml`:
before_script:
- apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- - gem install bundler --no-ri --no-rdoc
+ - gem install bundler --no-document
- bundle install --jobs $(nproc) "${FLAGS[@]}"
```
@@ -2200,6 +2200,12 @@ with an API call.
If your commit message contains `[ci skip]` or `[skip ci]`, using any
capitalization, the commit will be created but the pipeline will be skipped.
+Alternatively, one can pass the `ci.skip` [Git push option][push-option] if
+using Git 2.10 or newer:
+```
+$ git push -o ci.skip
+```
+
## Validate the .gitlab-ci.yml
Each instance of GitLab CI has an embedded debug tool called Lint, which validates the
@@ -2224,3 +2230,4 @@ GitLab CI/CD with various languages.
[environment]: ../environments.md "CI/CD environments"
[schedules]: ../../user/project/pipelines/schedules.md "Pipelines schedules"
[variables]: ../variables/README.md "CI/CD variables"
+[push-option]: https://git-scm.com/docs/git-push#git-push--oltoptiongt
diff --git a/doc/install/installation.md b/doc/install/installation.md
index d041bfa863a..b7781dea384 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -142,7 +142,7 @@ Download Ruby and compile it:
Then install the Bundler Gem:
- sudo gem install bundler --no-ri --no-rdoc
+ sudo gem install bundler --no-document
## 3. Go
diff --git a/doc/install/openshift_and_gitlab/index.md b/doc/install/openshift_and_gitlab/index.md
index 4c88b6f97fc..25a87dbd9de 100644
--- a/doc/install/openshift_and_gitlab/index.md
+++ b/doc/install/openshift_and_gitlab/index.md
@@ -18,7 +18,7 @@ In this tutorial, we will see how to deploy GitLab in OpenShift using GitLab's
official Docker image while getting familiar with the web interface and CLI
tools that will help us achieve our goal.
-For a video demonstration on installing GitLab on Openshift, check the article [In 13 minutes from Kubernetes to a complete application development tool](https://about.gitlab.com/2016/11/14/idea-to-production/).
+For a video demonstration on installing GitLab on OpenShift, check the article [In 13 minutes from Kubernetes to a complete application development tool](https://about.gitlab.com/2016/11/14/idea-to-production/).
---
@@ -518,7 +518,7 @@ PaaS and managing your applications with the ease of containers.
[templates]: https://docs.openshift.org/latest/architecture/core_concepts/templates.html "Documentation - OpenShift templates"
[old-post]: https://blog.openshift.com/deploy-gitlab-openshift/ "Old post - Deploy GitLab on OpenShift"
[line]: https://gitlab.com/gitlab-org/omnibus-gitlab/blob/658c065c8d022ce858dd63eaeeadb0b2ddc8deea/docker/openshift-template.json#L239 "GitLab - OpenShift template"
-[oc-gh]: https://github.com/openshift/origin/releases/tag/v1.3.0 "Openshift 1.3.0 release on GitHub"
+[oc-gh]: https://github.com/openshift/origin/releases/tag/v1.3.0 "OpenShift Origin 1.3.0 release on GitHub"
[ha]: ../../administration/high_availability/gitlab.html "Documentation - GitLab High Availability"
[replicas]: https://docs.openshift.org/latest/architecture/core_concepts/deployments.html#replication-controllers "Documentation - Replication controller"
[autoscaling]: https://docs.openshift.org/latest/dev_guide/pod_autoscaling.html "Documentation - Autoscale"
diff --git a/doc/integration/google.md b/doc/integration/google.md
index b91d40d4bd4..d2b4e119978 100644
--- a/doc/integration/google.md
+++ b/doc/integration/google.md
@@ -35,7 +35,6 @@ In Google's side:
1. You should now be able to see a Client ID and Client secret. Note them down
or keep this page open as you will need them later.
-1. From the **Dashboard** select **ENABLE APIS AND SERVICES > Social > Google+ API > Enable**
1. To enable projects to access [Google Kubernetes Engine](../user/project/clusters/index.md), you must also
enable these APIs:
- Google Kubernetes Engine API
diff --git a/doc/topics/authentication/index.md b/doc/topics/authentication/index.md
index 766a23c419d..a354d3e7884 100644
--- a/doc/topics/authentication/index.md
+++ b/doc/topics/authentication/index.md
@@ -45,4 +45,4 @@ This page gathers all the resources for the topic **Authentication** within GitL
- [Kanboard Plugin GitLab Authentication](https://github.com/kanboard/plugin-gitlab-auth)
- [Jenkins GitLab OAuth Plugin](https://wiki.jenkins.io/display/JENKINS/GitLab+OAuth+Plugin)
- [How to customize GitLab to support OpenID authentication](http://eric.van-der-vlist.com/blog/2013/11/23/how-to-customize-gitlab-to-support-openid-authentication/)
-- [Openshift - Configuring Authentication and User Agent](https://docs.openshift.org/latest/install_config/configuring_authentication.html#GitLab)
+- [OKD - Configuring Authentication and User Agent](https://docs.okd.io/latest/install_config/configuring_authentication.html#GitLab)
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index b41f401e14c..e937d372384 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -340,6 +340,9 @@ Any security warnings are also
NOTE: **Note:**
The Auto SAST stage will be skipped on licenses other than Ultimate.
+NOTE: **Note:**
+The Auto SAST job requires GitLab Runner 11.5 or above.
+
### Auto Dependency Scanning **[ULTIMATE]**
> Introduced in [GitLab Ultimate][ee] 10.7.
@@ -356,6 +359,9 @@ Any security warnings are also
NOTE: **Note:**
The Auto Dependency Scanning stage will be skipped on licenses other than Ultimate.
+NOTE: **Note:**
+The Auto Dependency Scanning job requires GitLab Runner 11.5 or above.
+
### Auto License Management **[ULTIMATE]**
> Introduced in [GitLab Ultimate][ee] 11.0.
diff --git a/doc/update/10.0-to-10.1.md b/doc/update/10.0-to-10.1.md
index af815d26a74..10cf02a984f 100644
--- a/doc/update/10.0-to-10.1.md
+++ b/doc/update/10.0-to-10.1.md
@@ -49,7 +49,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/10.1-to-10.2.md b/doc/update/10.1-to-10.2.md
index 632e8befa74..20895a05567 100644
--- a/doc/update/10.1-to-10.2.md
+++ b/doc/update/10.1-to-10.2.md
@@ -49,7 +49,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/10.2-to-10.3.md b/doc/update/10.2-to-10.3.md
index f8fe4a4b6bf..441a241d053 100644
--- a/doc/update/10.2-to-10.3.md
+++ b/doc/update/10.2-to-10.3.md
@@ -49,7 +49,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/10.3-to-10.4.md b/doc/update/10.3-to-10.4.md
index 083f6090a8a..9f3efdd790e 100644
--- a/doc/update/10.3-to-10.4.md
+++ b/doc/update/10.3-to-10.4.md
@@ -51,7 +51,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/10.4-to-10.5.md b/doc/update/10.4-to-10.5.md
index 313419ed13d..3766645a141 100644
--- a/doc/update/10.4-to-10.5.md
+++ b/doc/update/10.4-to-10.5.md
@@ -51,7 +51,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/10.5-to-10.6.md b/doc/update/10.5-to-10.6.md
index 2f90fb62c4a..986ecbf5ef0 100644
--- a/doc/update/10.5-to-10.6.md
+++ b/doc/update/10.5-to-10.6.md
@@ -51,7 +51,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/10.6-to-10.7.md b/doc/update/10.6-to-10.7.md
index b9c14395a3a..10d29837bfb 100644
--- a/doc/update/10.6-to-10.7.md
+++ b/doc/update/10.6-to-10.7.md
@@ -51,7 +51,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/10.7-to-10.8.md b/doc/update/10.7-to-10.8.md
index 7bb628f9740..0cc46fc5aa9 100644
--- a/doc/update/10.7-to-10.8.md
+++ b/doc/update/10.7-to-10.8.md
@@ -52,7 +52,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/10.8-to-11.0.md b/doc/update/10.8-to-11.0.md
index 22a0c9f950c..ad3305d8ebd 100644
--- a/doc/update/10.8-to-11.0.md
+++ b/doc/update/10.8-to-11.0.md
@@ -51,7 +51,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/11.0-to-11.1.md b/doc/update/11.0-to-11.1.md
index 3f10a7edb8a..5b2dd48a744 100644
--- a/doc/update/11.0-to-11.1.md
+++ b/doc/update/11.0-to-11.1.md
@@ -51,7 +51,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/11.1-to-11.2.md b/doc/update/11.1-to-11.2.md
index 3edc7e6923e..cb09d0a2505 100644
--- a/doc/update/11.1-to-11.2.md
+++ b/doc/update/11.1-to-11.2.md
@@ -51,7 +51,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/11.2-to-11.3.md b/doc/update/11.2-to-11.3.md
index f2b8efc3e6e..228ff6cb70e 100644
--- a/doc/update/11.2-to-11.3.md
+++ b/doc/update/11.2-to-11.3.md
@@ -51,7 +51,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/11.3-to-11.4.md b/doc/update/11.3-to-11.4.md
index fddec45e57a..5f64bf81127 100644
--- a/doc/update/11.3-to-11.4.md
+++ b/doc/update/11.3-to-11.4.md
@@ -51,7 +51,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/11.4-to-11.5.md b/doc/update/11.4-to-11.5.md
index 44105348d14..fd7a8e5c2ae 100644
--- a/doc/update/11.4-to-11.5.md
+++ b/doc/update/11.4-to-11.5.md
@@ -51,7 +51,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/11.5-to-11.6.md b/doc/update/11.5-to-11.6.md
index 031abc434ca..2e9ec5d71de 100644
--- a/doc/update/11.5-to-11.6.md
+++ b/doc/update/11.5-to-11.6.md
@@ -51,7 +51,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/6.9-to-7.0.md b/doc/update/6.9-to-7.0.md
index 27063948028..781c90e4198 100644
--- a/doc/update/6.9-to-7.0.md
+++ b/doc/update/6.9-to-7.0.md
@@ -47,7 +47,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 3. Get latest code
diff --git a/doc/update/6.x-or-7.x-to-7.14.md b/doc/update/6.x-or-7.x-to-7.14.md
index 61854b91aa2..6fcec5b7974 100644
--- a/doc/update/6.x-or-7.x-to-7.14.md
+++ b/doc/update/6.x-or-7.x-to-7.14.md
@@ -67,7 +67,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
## 3. Get latest code
diff --git a/doc/update/7.0-to-7.1.md b/doc/update/7.0-to-7.1.md
index 308e8aeb985..fb4710faad5 100644
--- a/doc/update/7.0-to-7.1.md
+++ b/doc/update/7.0-to-7.1.md
@@ -47,7 +47,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 3. Get latest code
diff --git a/doc/update/8.10-to-8.11.md b/doc/update/8.10-to-8.11.md
index df3e34f5cc6..12a465e1602 100644
--- a/doc/update/8.10-to-8.11.md
+++ b/doc/update/8.10-to-8.11.md
@@ -47,7 +47,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Get latest code
diff --git a/doc/update/8.11-to-8.12.md b/doc/update/8.11-to-8.12.md
index 9d6a1f42375..b9a7986d5ba 100644
--- a/doc/update/8.11-to-8.12.md
+++ b/doc/update/8.11-to-8.12.md
@@ -47,7 +47,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Get latest code
diff --git a/doc/update/8.12-to-8.13.md b/doc/update/8.12-to-8.13.md
index 6225dee9802..37e61794e7e 100644
--- a/doc/update/8.12-to-8.13.md
+++ b/doc/update/8.12-to-8.13.md
@@ -47,7 +47,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Get latest code
diff --git a/doc/update/8.13-to-8.14.md b/doc/update/8.13-to-8.14.md
index d2508e3f980..927f453b9bf 100644
--- a/doc/update/8.13-to-8.14.md
+++ b/doc/update/8.13-to-8.14.md
@@ -47,7 +47,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Get latest code
diff --git a/doc/update/8.14-to-8.15.md b/doc/update/8.14-to-8.15.md
index daf8d0f2ca6..d98a60d31c8 100644
--- a/doc/update/8.14-to-8.15.md
+++ b/doc/update/8.14-to-8.15.md
@@ -50,7 +50,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Get latest code
diff --git a/doc/update/8.15-to-8.16.md b/doc/update/8.15-to-8.16.md
index 3668142edd2..94b0102ed48 100644
--- a/doc/update/8.15-to-8.16.md
+++ b/doc/update/8.15-to-8.16.md
@@ -50,7 +50,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Get latest code
diff --git a/doc/update/8.16-to-8.17.md b/doc/update/8.16-to-8.17.md
index ee2e31c2aec..5a4f620a164 100644
--- a/doc/update/8.16-to-8.17.md
+++ b/doc/update/8.16-to-8.17.md
@@ -50,7 +50,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/8.17-to-9.0.md b/doc/update/8.17-to-9.0.md
index 3c73bc573a6..38f7d22437a 100644
--- a/doc/update/8.17-to-9.0.md
+++ b/doc/update/8.17-to-9.0.md
@@ -49,7 +49,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/9.0-to-9.1.md b/doc/update/9.0-to-9.1.md
index 7c9dacc9b90..a4d2e7be23c 100644
--- a/doc/update/9.0-to-9.1.md
+++ b/doc/update/9.0-to-9.1.md
@@ -49,7 +49,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/9.1-to-9.2.md b/doc/update/9.1-to-9.2.md
index b815242ab4e..dd808c51985 100644
--- a/doc/update/9.1-to-9.2.md
+++ b/doc/update/9.1-to-9.2.md
@@ -49,7 +49,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/9.2-to-9.3.md b/doc/update/9.2-to-9.3.md
index a58b12cb81c..d2bcf45a28e 100644
--- a/doc/update/9.2-to-9.3.md
+++ b/doc/update/9.2-to-9.3.md
@@ -49,7 +49,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/9.3-to-9.4.md b/doc/update/9.3-to-9.4.md
index 0c87468334b..dae2162a964 100644
--- a/doc/update/9.3-to-9.4.md
+++ b/doc/update/9.3-to-9.4.md
@@ -49,7 +49,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/9.4-to-9.5.md b/doc/update/9.4-to-9.5.md
index 6a655f77a55..f2811e9471f 100644
--- a/doc/update/9.4-to-9.5.md
+++ b/doc/update/9.4-to-9.5.md
@@ -49,7 +49,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/update/9.5-to-10.0.md b/doc/update/9.5-to-10.0.md
index 7790d192a82..333a6e35714 100644
--- a/doc/update/9.5-to-10.0.md
+++ b/doc/update/9.5-to-10.0.md
@@ -49,7 +49,7 @@ sudo make install
Install Bundler:
```bash
-sudo gem install bundler --no-ri --no-rdoc
+sudo gem install bundler --no-document
```
### 4. Update Node
diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md
index 6bdafc60949..6f334af4fb7 100644
--- a/doc/user/project/clusters/index.md
+++ b/doc/user/project/clusters/index.md
@@ -60,7 +60,7 @@ new Kubernetes cluster to your project:
**Sign in with Google** button.
1. From there on, choose your cluster's settings:
- **Kubernetes cluster name** - The name you wish to give the cluster.
- - **Environment scope** - The [associated environment](#setting-the-environment-scope) to this cluster.
+ - **Environment scope** - The [associated environment](#setting-the-environment-scope-premium) to this cluster.
- **Google Cloud Platform project** - Choose the project you created in your GCP
console that will host the Kubernetes cluster. Learn more about
[Google Cloud Platform projects](https://cloud.google.com/resource-manager/docs/creating-managing-projects).
diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md
index d9a2eeb32ae..5de8e66e7eb 100644
--- a/doc/user/project/integrations/prometheus.md
+++ b/doc/user/project/integrations/prometheus.md
@@ -30,7 +30,7 @@ GitLab can seamlessly deploy and manage Prometheus on a [connected Kubernetes cl
Once you have a connected Kubernetes cluster with Helm installed, deploying a managed Prometheus is as easy as a single click.
-1. Go to the `Operations > Kubernetes` page, to view your connected clusters
+1. Go to the **Operations > Kubernetes** page to view your connected clusters
1. Select the cluster you would like to deploy Prometheus to
1. Click the **Install** button to deploy Prometheus to the cluster
@@ -88,7 +88,7 @@ to integrate with.
Once configured, GitLab will attempt to retrieve performance metrics for any
environment which has had a successful deployment.
-GitLab will automatically scan the Prometheus server for metrics from known serves like Kubernetes and NGINX, and attempt to identify individual environment. The supported metrics and scan process is detailed in our [Prometheus Metric Library documentation](prometheus_library/metrics.html).
+GitLab will automatically scan the Prometheus server for metrics from known serves like Kubernetes and NGINX, and attempt to identify individual environment. The supported metrics and scan process is detailed in our [Prometheus Metric Library documentation](prometheus_library/index.md).
You can view the performance dashboard for an environment by [clicking on the monitoring button](../../../ci/environments.md#monitoring-environments).
diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md
index cb68c9318bc..3bbfa74f4b7 100644
--- a/doc/user/project/settings/import_export.md
+++ b/doc/user/project/settings/import_export.md
@@ -71,6 +71,7 @@ The following items will NOT be exported:
- Build traces and artifacts
- Container registry images
- CI variables
+- Webhooks
- Any encrypted tokens
## Exporting a project and its data
diff --git a/doc/workflow/todos.md b/doc/workflow/todos.md
index f94d592d0db..830f17aa7f2 100644
--- a/doc/workflow/todos.md
+++ b/doc/workflow/todos.md
@@ -35,6 +35,9 @@ A Todo appears in your Todos dashboard when:
- the author, or
- have set it to automatically merge once pipeline succeeds.
+NOTE: **Note:**
+When an user no longer has access to a resource related to a Todo like an issue, merge request, project or group the related Todos, for security reasons, gets deleted within the next hour. The delete is delayed to prevent data loss in case user got their access revoked by mistake.
+
### Directly addressed Todos
> [Introduced][ce-7926] in GitLab 9.0.
diff --git a/lib/api/internal.rb b/lib/api/internal.rb
index ae40b5f7557..9488b3469d9 100644
--- a/lib/api/internal.rb
+++ b/lib/api/internal.rb
@@ -256,8 +256,9 @@ module API
post '/post_receive' do
status 200
+
PostReceive.perform_async(params[:gl_repository], params[:identifier],
- params[:changes])
+ params[:changes], params[:push_options].to_a)
broadcast_message = BroadcastMessage.current&.last&.message
reference_counter_decreased = Gitlab::ReferenceCounter.new(params[:gl_repository]).decrease
diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb
index 80a5cbd6b19..45c694b6448 100644
--- a/lib/api/jobs.rb
+++ b/lib/api/jobs.rb
@@ -38,6 +38,8 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
get ':id/jobs' do
+ authorize_read_builds!
+
builds = user_project.builds.order('id DESC')
builds = filter_builds(builds, params[:scope])
@@ -56,7 +58,10 @@ module API
end
# rubocop: disable CodeReuse/ActiveRecord
get ':id/pipelines/:pipeline_id/jobs' do
+ authorize!(:read_pipeline, user_project)
pipeline = user_project.ci_pipelines.find(params[:pipeline_id])
+ authorize!(:read_build, pipeline)
+
builds = pipeline.builds
builds = filter_builds(builds, params[:scope])
builds = builds.preload(:job_artifacts_archive, :job_artifacts, project: [:namespace])
diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb
index a0434a66ef1..0add2b3f875 100644
--- a/lib/backup/manager.rb
+++ b/lib/backup/manager.rb
@@ -195,7 +195,7 @@ module Backup
if connection.service == ::Fog::Storage::Local
connection.directories.create(key: remote_directory)
else
- connection.directories.get(remote_directory)
+ connection.directories.new(key: remote_directory)
end
end
diff --git a/lib/banzai/filter/external_link_filter.rb b/lib/banzai/filter/external_link_filter.rb
index 2e6d742de27..4f60b6f84c6 100644
--- a/lib/banzai/filter/external_link_filter.rb
+++ b/lib/banzai/filter/external_link_filter.rb
@@ -9,11 +9,10 @@ module Banzai
def call
links.each do |node|
uri = uri(node['href'].to_s)
- next unless uri
- node.set_attribute('href', uri.to_s)
+ node.set_attribute('href', uri.to_s) if uri
- if SCHEMES.include?(uri.scheme) && external_url?(uri)
+ if SCHEMES.include?(uri&.scheme) && !internal_url?(uri)
node.set_attribute('rel', 'nofollow noreferrer noopener')
node.set_attribute('target', '_blank')
end
@@ -35,11 +34,12 @@ module Banzai
doc.xpath(query)
end
- def external_url?(uri)
+ def internal_url?(uri)
+ return false if uri.nil?
# Relative URLs miss a hostname
- return false unless uri.hostname
+ return true unless uri.hostname
- uri.hostname != internal_url.hostname
+ uri.hostname == internal_url.hostname
end
def internal_url
diff --git a/lib/banzai/filter/label_reference_filter.rb b/lib/banzai/filter/label_reference_filter.rb
index 04ec38209c7..f90a35952e5 100644
--- a/lib/banzai/filter/label_reference_filter.rb
+++ b/lib/banzai/filter/label_reference_filter.rb
@@ -29,7 +29,7 @@ module Banzai
if label
yield match, label.id, project, namespace, $~
else
- match
+ escape_html_entities(match)
end
end
end
@@ -102,6 +102,10 @@ module Banzai
CGI.unescapeHTML(text.to_s)
end
+ def escape_html_entities(text)
+ CGI.escapeHTML(text.to_s)
+ end
+
def object_link_title(object, matches)
# use title of wrapped element instead
nil
diff --git a/lib/gitlab/ci/pipeline/chain/command.rb b/lib/gitlab/ci/pipeline/chain/command.rb
index 100b9521412..e62d547d862 100644
--- a/lib/gitlab/ci/pipeline/chain/command.rb
+++ b/lib/gitlab/ci/pipeline/chain/command.rb
@@ -10,7 +10,7 @@ module Gitlab
:origin_ref, :checkout_sha, :after_sha, :before_sha,
:trigger_request, :schedule, :merge_request,
:ignore_skip_ci, :save_incompleted,
- :seeds_block, :variables_attributes
+ :seeds_block, :variables_attributes, :push_options
) do
include Gitlab::Utils::StrongMemoize
@@ -54,7 +54,13 @@ module Gitlab
def protected_ref?
strong_memoize(:protected_ref) do
- project.protected_for?(ref)
+ project.protected_for?(origin_ref)
+ end
+ end
+
+ def ambiguous_ref?
+ strong_memoize(:ambiguous_ref) do
+ project.repository.ambiguous_ref?(origin_ref)
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/skip.rb b/lib/gitlab/ci/pipeline/chain/skip.rb
index b9707d2f8f5..79bbcc1ed1e 100644
--- a/lib/gitlab/ci/pipeline/chain/skip.rb
+++ b/lib/gitlab/ci/pipeline/chain/skip.rb
@@ -8,6 +8,7 @@ module Gitlab
include ::Gitlab::Utils::StrongMemoize
SKIP_PATTERN = /\[(ci[ _-]skip|skip[ _-]ci)\]/i
+ SKIP_PUSH_OPTION = 'ci.skip'
def perform!
if skipped?
@@ -16,7 +17,7 @@ module Gitlab
end
def skipped?
- !@command.ignore_skip_ci && commit_message_skips_ci?
+ !@command.ignore_skip_ci && (commit_message_skips_ci? || push_option_skips_ci?)
end
def break?
@@ -32,6 +33,10 @@ module Gitlab
!!(@pipeline.git_commit_message =~ SKIP_PATTERN)
end
end
+
+ def push_option_skips_ci?
+ !!(@command.push_options&.include?(SKIP_PUSH_OPTION))
+ end
end
end
end
diff --git a/lib/gitlab/ci/pipeline/chain/validate/repository.rb b/lib/gitlab/ci/pipeline/chain/validate/repository.rb
index d88851d8245..9c6c2bc8e25 100644
--- a/lib/gitlab/ci/pipeline/chain/validate/repository.rb
+++ b/lib/gitlab/ci/pipeline/chain/validate/repository.rb
@@ -16,6 +16,10 @@ module Gitlab
unless @command.sha
return error('Commit not found')
end
+
+ if @command.ambiguous_ref?
+ return error('Ref is ambiguous')
+ end
end
def break?
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
index a9e361b0b32..8f6cf8d2d03 100644
--- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -185,7 +185,8 @@ dependency_scanning:
- setup_docker
- dependency_scanning
artifacts:
- paths: [gl-dependency-scanning-report.json]
+ reports:
+ dependency_scanning: gl-dependency-scanning-report.json
only:
refs:
- branches
diff --git a/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml b/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
index 93cb31f48c0..0d12cbc6460 100644
--- a/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Ruby.gitlab-ci.yml
@@ -24,7 +24,6 @@ before_script:
- ruby -v # Print out ruby version for debugging
# Uncomment next line if your rails app needs a JS runtime:
# - apt-get update -q && apt-get install nodejs -yqq
- - gem install bundler --no-ri --no-rdoc # Bundler is not installed with the image
- bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby
# Optional - Delete if not using `rubocop`
diff --git a/lib/gitlab/cleanup/remote_uploads.rb b/lib/gitlab/cleanup/remote_uploads.rb
index eba1faacc3a..03298d960a4 100644
--- a/lib/gitlab/cleanup/remote_uploads.rb
+++ b/lib/gitlab/cleanup/remote_uploads.rb
@@ -67,7 +67,7 @@ module Gitlab
end
def remote_directory
- connection.directories.get(configuration['remote_directory'])
+ connection.directories.new(key: configuration['remote_directory'])
end
def connection
diff --git a/lib/gitlab/data_builder/push.rb b/lib/gitlab/data_builder/push.rb
index 9bf2f9291a8..862127110b9 100644
--- a/lib/gitlab/data_builder/push.rb
+++ b/lib/gitlab/data_builder/push.rb
@@ -31,7 +31,11 @@ module Gitlab
}
}
],
- total_commits_count: 1
+ total_commits_count: 1,
+ push_options: [
+ "ci.skip",
+ "custom option"
+ ]
}.freeze
# Produce a hash of post-receive data
@@ -52,10 +56,12 @@ module Gitlab
# homepage: String,
# },
# commits: Array,
- # total_commits_count: Fixnum
+ # total_commits_count: Fixnum,
+ # push_options: Array
# }
#
- def build(project, user, oldrev, newrev, ref, commits = [], message = nil, commits_count: nil)
+ # rubocop:disable Metrics/ParameterLists
+ def build(project, user, oldrev, newrev, ref, commits = [], message = nil, commits_count: nil, push_options: [])
commits = Array(commits)
# Total commits count
@@ -93,6 +99,7 @@ module Gitlab
project: project.hook_attrs,
commits: commit_attrs,
total_commits_count: commits_count,
+ push_options: push_options,
# DEPRECATED
repository: project.hook_attrs.slice(:name, :url, :description, :homepage,
:git_http_url, :git_ssh_url, :visibility_level)
diff --git a/lib/gitlab/git.rb b/lib/gitlab/git.rb
index c4aac228b2f..44a62586a23 100644
--- a/lib/gitlab/git.rb
+++ b/lib/gitlab/git.rb
@@ -54,11 +54,11 @@ module Gitlab
end
def tag_ref?(ref)
- ref.start_with?(TAG_REF_PREFIX)
+ ref =~ /^#{TAG_REF_PREFIX}.+/
end
def branch_ref?(ref)
- ref.start_with?(BRANCH_REF_PREFIX)
+ ref =~ /^#{BRANCH_REF_PREFIX}.+/
end
def blank_ref?(ref)
diff --git a/lib/gitlab/git_post_receive.rb b/lib/gitlab/git_post_receive.rb
index cf2329e489d..426436c2164 100644
--- a/lib/gitlab/git_post_receive.rb
+++ b/lib/gitlab/git_post_receive.rb
@@ -3,12 +3,13 @@
module Gitlab
class GitPostReceive
include Gitlab::Identifier
- attr_reader :project, :identifier, :changes
+ attr_reader :project, :identifier, :changes, :push_options
- def initialize(project, identifier, changes)
+ def initialize(project, identifier, changes, push_options)
@project = project
@identifier = identifier
@changes = deserialize_changes(changes)
+ @push_options = push_options
end
def identify
diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml
index 3cd8ede830c..25cdd5ab121 100644
--- a/lib/gitlab/import_export/import_export.yml
+++ b/lib/gitlab/import_export/import_export.yml
@@ -63,7 +63,6 @@ project_tree:
- :triggers
- :pipeline_schedules
- :services
- - :hooks
- protected_branches:
- :merge_access_levels
- :push_access_levels
@@ -156,12 +155,6 @@ excluded_attributes:
- :reference
- :reference_html
- :epic_id
- hooks:
- - :token
- - :encrypted_token
- - :encrypted_token_iv
- - :encrypted_url
- - :encrypted_url_iv
runners:
- :token
- :token_encrypted
diff --git a/lib/gitlab/middleware/go.rb b/lib/gitlab/middleware/go.rb
index d1a87c3b3bb..72a788022ef 100644
--- a/lib/gitlab/middleware/go.rb
+++ b/lib/gitlab/middleware/go.rb
@@ -6,6 +6,7 @@ module Gitlab
module Middleware
class Go
include ActionView::Helpers::TagHelper
+ include ActionController::HttpAuthentication::Basic
PROJECT_PATH_REGEX = %r{\A(#{Gitlab::PathRegex.full_namespace_route_regex}/#{Gitlab::PathRegex.project_route_regex})/}.freeze
@@ -14,7 +15,7 @@ module Gitlab
end
def call(env)
- request = Rack::Request.new(env)
+ request = ActionDispatch::Request.new(env)
render_go_doc(request) || @app.call(env)
end
@@ -110,21 +111,23 @@ module Gitlab
def project_for_paths(paths, request)
project = Project.where_full_path_in(paths).first
- return unless Ability.allowed?(current_user(request), :read_project, project)
+ return unless Ability.allowed?(current_user(request, project), :read_project, project)
project
end
- def current_user(request)
- authenticator = Gitlab::Auth::RequestAuthenticator.new(request)
- user = authenticator.find_user_from_access_token || authenticator.find_user_from_warden
+ def current_user(request, project)
+ return unless has_basic_credentials?(request)
- return unless user&.can?(:access_api)
+ login, password = user_name_and_password(request)
+ auth_result = Gitlab::Auth.find_for_git_client(login, password, project: project, ip: request.ip)
+ return unless auth_result.success?
- # Right now, the `api` scope is the only one that should be able to determine private project existence.
- return unless authenticator.valid_access_token?(scopes: [:api])
+ return unless auth_result.actor&.can?(:access_git)
- user
+ return unless auth_result.authentication_abilities.include?(:read_project)
+
+ auth_result.actor
end
end
end
diff --git a/lib/json_web_token/hmac_token.rb b/lib/json_web_token/hmac_token.rb
index ceb1b9c913f..ec0917ab49d 100644
--- a/lib/json_web_token/hmac_token.rb
+++ b/lib/json_web_token/hmac_token.rb
@@ -18,7 +18,7 @@ module JSONWebToken
end
def encoded
- JWT.encode(payload, secret, JWT_ALGORITHM)
+ JWT.encode(payload, secret, JWT_ALGORITHM, { typ: 'JWT' })
end
private
diff --git a/lib/json_web_token/rsa_token.rb b/lib/json_web_token/rsa_token.rb
index 160e1e506f1..bcce811cd28 100644
--- a/lib/json_web_token/rsa_token.rb
+++ b/lib/json_web_token/rsa_token.rb
@@ -11,7 +11,8 @@ module JSONWebToken
def encoded
headers = {
- kid: kid
+ kid: kid,
+ typ: 'JWT'
}
JWT.encode(payload, key, 'RS256', headers)
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 88eff3b6645..ddfd5599883 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -4416,6 +4416,9 @@ msgstr ""
msgid "No"
msgstr ""
+msgid "No activities found"
+msgstr ""
+
msgid "No assignee"
msgstr ""
@@ -6239,7 +6242,7 @@ msgstr ""
msgid "SortOptions|Least popular"
msgstr ""
-msgid "SortOptions|Milestone"
+msgid "SortOptions|Milestone due date"
msgstr ""
msgid "SortOptions|Milestone due later"
diff --git a/qa/Dockerfile b/qa/Dockerfile
index 9956ced0ef6..ca7f9accb70 100644
--- a/qa/Dockerfile
+++ b/qa/Dockerfile
@@ -1,4 +1,4 @@
-FROM ruby:2.4-stretch
+FROM ruby:2.5-stretch
LABEL maintainer "Grzegorz Bizon <grzegorz@gitlab.com>"
ENV DEBIAN_FRONTEND noninteractive
diff --git a/qa/Gemfile b/qa/Gemfile
index d69c71003ae..75ad7bd07af 100644
--- a/qa/Gemfile
+++ b/qa/Gemfile
@@ -5,5 +5,6 @@ gem 'capybara', '~> 2.16.1'
gem 'capybara-screenshot', '~> 1.0.18'
gem 'rake', '~> 12.3.0'
gem 'rspec', '~> 3.7'
-gem 'selenium-webdriver', '~> 3.8.0'
+gem 'selenium-webdriver', '~> 3.12'
gem 'airborne', '~> 0.2.13'
+gem 'nokogiri', '~> 1.8.5'
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index d61ecf8fbb5..55f3211482b 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -25,7 +25,7 @@ GEM
capybara-screenshot (1.0.18)
capybara (>= 1.0, < 3)
launchy
- childprocess (0.8.0)
+ childprocess (0.9.0)
ffi (~> 1.0, >= 1.0.11)
coderay (1.1.2)
concurrent-ruby (1.0.5)
@@ -47,7 +47,7 @@ GEM
mini_portile2 (2.3.0)
minitest (5.11.1)
netrc (0.11.0)
- nokogiri (1.8.2)
+ nokogiri (1.8.5)
mini_portile2 (~> 2.3.0)
pry (0.11.3)
coderay (~> 1.1.0)
@@ -78,9 +78,9 @@ GEM
rspec-support (~> 3.7.0)
rspec-support (3.7.0)
rubyzip (1.2.2)
- selenium-webdriver (3.8.0)
+ selenium-webdriver (3.141.0)
childprocess (~> 0.5)
- rubyzip (~> 1.0)
+ rubyzip (~> 1.2, >= 1.2.2)
thread_safe (0.3.6)
tzinfo (1.2.4)
thread_safe (~> 0.1)
@@ -97,10 +97,11 @@ DEPENDENCIES
airborne (~> 0.2.13)
capybara (~> 2.16.1)
capybara-screenshot (~> 1.0.18)
+ nokogiri (~> 1.8.5)
pry-byebug (~> 3.5.1)
rake (~> 12.3.0)
rspec (~> 3.7)
- selenium-webdriver (~> 3.8.0)
+ selenium-webdriver (~> 3.12)
BUNDLED WITH
- 1.17.1
+ 1.17.3
diff --git a/qa/qa.rb b/qa/qa.rb
index bf05b6b53ca..ef6a92f9768 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -283,6 +283,7 @@ module QA
autoload :Select2, 'qa/page/component/select2'
autoload :DropdownFilter, 'qa/page/component/dropdown_filter'
autoload :UsersSelect, 'qa/page/component/users_select'
+ autoload :Note, 'qa/page/component/note'
module Issuable
autoload :Common, 'qa/page/component/issuable/common'
diff --git a/qa/qa/page/component/note.rb b/qa/qa/page/component/note.rb
new file mode 100644
index 00000000000..67d7f114786
--- /dev/null
+++ b/qa/qa/page/component/note.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Component
+ module Note
+ def self.included(base)
+ base.view 'app/assets/javascripts/notes/components/comment_form.vue' do
+ element :note_dropdown
+ element :discussion_option
+ end
+
+ base.view 'app/assets/javascripts/notes/components/note_form.vue' do
+ element :reply_input
+ element :reply_comment_button
+ end
+
+ base.view 'app/assets/javascripts/notes/components/noteable_discussion.vue' do
+ element :discussion_reply
+ end
+
+ base.view 'app/assets/javascripts/notes/components/toggle_replies_widget.vue' do
+ element :expand_replies
+ element :collapse_replies
+ end
+ end
+
+ def start_discussion(text)
+ fill_element :comment_input, text
+ click_element :note_dropdown
+ click_element :discussion_option
+ click_element :comment_button
+ end
+
+ def reply_to_discussion(reply_text)
+ all_elements(:discussion_reply).last.click
+ fill_element :reply_input, reply_text
+ click_element :reply_comment_button
+ end
+
+ def collapse_replies
+ click_element :collapse_replies
+ end
+
+ def expand_replies
+ click_element :expand_replies
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb
index 869dc0b9d21..4f21ed602d9 100644
--- a/qa/qa/page/merge_request/show.rb
+++ b/qa/qa/page/merge_request/show.rb
@@ -4,6 +4,8 @@ module QA
module Page
module MergeRequest
class Show < Page::Base
+ include Page::Component::Note
+
view 'app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue' do
element :merge_button
element :fast_forward_message, 'Fast-forward merge without a merge commit' # rubocop:disable QA/ElementWithPattern
@@ -34,19 +36,6 @@ module QA
element :diff_comment
end
- view 'app/assets/javascripts/notes/components/comment_form.vue' do
- element :note_dropdown
- element :discussion_option
- end
-
- view 'app/assets/javascripts/notes/components/note_form.vue' do
- element :reply_input
- end
-
- view 'app/assets/javascripts/notes/components/noteable_discussion.vue' do
- element :discussion_reply
- end
-
view 'app/assets/javascripts/diffs/components/inline_diff_table_row.vue' do
element :new_diff_line
end
@@ -163,18 +152,6 @@ module QA
fill_element :reply_input, text
end
- def start_discussion(text)
- fill_element :comment_input, text
- click_element :note_dropdown
- click_element :discussion_option
- click_element :comment_button
- end
-
- def reply_to_discussion(reply_text)
- all_elements(:discussion_reply).last.click
- fill_element :reply_input, reply_text
- end
-
def edit!
click_element :edit_button
end
diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb
index 9ec6d90719e..1028cc045a0 100644
--- a/qa/qa/page/project/issue/show.rb
+++ b/qa/qa/page/project/issue/show.rb
@@ -6,6 +6,7 @@ module QA
module Issue
class Show < Page::Base
include Page::Component::Issuable::Common
+ include Page::Component::Note
view 'app/views/shared/notes/_form.html.haml' do
element :new_note_form, 'new-note' # rubocop:disable QA/ElementWithPattern
diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
new file mode 100644
index 00000000000..fa779bd1f4e
--- /dev/null
+++ b/qa/qa/specs/features/browser_ui/2_plan/issue/collapse_comments_in_discussions_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Plan' do
+ describe 'collapse comments in issue discussions' do
+ let(:issue_title) { 'issue title' }
+
+ it 'user collapses reply for comments in an issue' do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.perform(&:sign_in_using_credentials)
+
+ Resource::Issue.fabricate! do |issue|
+ issue.title = issue_title
+ end
+
+ expect(page).to have_content(issue_title)
+
+ Page::Project::Issue::Show.perform do |show_page|
+ show_page.select_all_activities_filter
+ show_page.start_discussion("My first discussion")
+ expect(show_page).to have_content("My first discussion")
+
+ show_page.reply_to_discussion("My First Reply")
+ expect(show_page).to have_content("My First Reply")
+
+ show_page.collapse_replies
+ expect(show_page).to have_content("1 reply")
+ expect(show_page).not_to have_content("My First Reply")
+
+ show_page.expand_replies
+ expect(show_page).to have_content("My First Reply")
+ expect(show_page).not_to have_content("1 reply")
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/support/page/logging.rb b/qa/qa/support/page/logging.rb
index df3b794b14b..cfccbb910b7 100644
--- a/qa/qa/support/page/logging.rb
+++ b/qa/qa/support/page/logging.rb
@@ -37,8 +37,11 @@ module QA
exists
end
- def find_element(name, wait: Capybara.default_max_wait_time)
- log("finding :#{name} (wait: #{wait})")
+ def find_element(name, text_filter = nil, wait: Capybara.default_max_wait_time)
+ msg = ["finding :#{name}"]
+ msg << %Q(with text_filter "#{text_filter}") if text_filter
+ msg << "(wait: #{wait})"
+ log(msg.compact.join(' '))
element = super
diff --git a/qa/spec/page/logging_spec.rb b/qa/spec/page/logging_spec.rb
index a54ff424f53..f108a5ca318 100644
--- a/qa/spec/page/logging_spec.rb
+++ b/qa/spec/page/logging_spec.rb
@@ -47,6 +47,15 @@ describe QA::Support::Page::Logging do
it 'logs find_element' do
expect { subject.find_element(:element) }
+ .to output(/finding :element/).to_stdout_from_any_process
+ expect { subject.find_element(:element) }
+ .to output(/found :element/).to_stdout_from_any_process
+ end
+
+ it 'logs find_element with text_filter' do
+ expect { subject.find_element(:element, 'foo') }
+ .to output(/finding :element with text_filter "foo"/).to_stdout_from_any_process
+ expect { subject.find_element(:element, 'foo') }
.to output(/found :element/).to_stdout_from_any_process
end
diff --git a/spec/controllers/dashboard/milestones_controller_spec.rb b/spec/controllers/dashboard/milestones_controller_spec.rb
index 8a8cc14fd4c..c9ccd5f7c55 100644
--- a/spec/controllers/dashboard/milestones_controller_spec.rb
+++ b/spec/controllers/dashboard/milestones_controller_spec.rb
@@ -52,7 +52,7 @@ describe Dashboard::MilestonesController do
expect(response).to have_gitlab_http_status(200)
expect(json_response.size).to eq(2)
- expect(json_response.map { |i| i["first_milestone"]["id"] }).to match_array([group_milestone.id, project_milestone.id])
+ expect(json_response.map { |i| i["name"] }).to match_array([group_milestone.name, project_milestone.name])
expect(json_response.map { |i| i["group_name"] }.compact).to match_array(group.name)
end
diff --git a/spec/controllers/groups/milestones_controller_spec.rb b/spec/controllers/groups/milestones_controller_spec.rb
index b8e1e08cff7..40d991a669c 100644
--- a/spec/controllers/groups/milestones_controller_spec.rb
+++ b/spec/controllers/groups/milestones_controller_spec.rb
@@ -64,7 +64,7 @@ describe Groups::MilestonesController do
context 'when there is a title parameter' do
it 'searches for a legacy group milestone' do
- expect(GlobalMilestone).to receive(:build)
+ expect(GroupMilestone).to receive(:build)
expect(Milestone).not_to receive(:find_by_iid)
get :show, params: { group_id: group.to_param, id: title, title: milestone1.safe_title }
diff --git a/spec/controllers/groups/settings/ci_cd_controller_spec.rb b/spec/controllers/groups/settings/ci_cd_controller_spec.rb
index b7f04f732b9..40673d10b91 100644
--- a/spec/controllers/groups/settings/ci_cd_controller_spec.rb
+++ b/spec/controllers/groups/settings/ci_cd_controller_spec.rb
@@ -5,30 +5,65 @@ describe Groups::Settings::CiCdController do
let(:user) { create(:user) }
before do
- group.add_maintainer(user)
sign_in(user)
end
describe 'GET #show' do
- it 'renders show with 200 status code' do
- get :show, params: { group_id: group }
+ context 'when user is owner' do
+ before do
+ group.add_owner(user)
+ end
- expect(response).to have_gitlab_http_status(200)
- expect(response).to render_template(:show)
+ it 'renders show with 200 status code' do
+ get :show, params: { group_id: group }
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(response).to render_template(:show)
+ end
+ end
+
+ context 'when user is not owner' do
+ before do
+ group.add_maintainer(user)
+ end
+
+ it 'renders a 404' do
+ get :show, params: { group_id: group }
+
+ expect(response).to have_gitlab_http_status(404)
+ end
end
end
describe 'PUT #reset_registration_token' do
subject { put :reset_registration_token, params: { group_id: group } }
- it 'resets runner registration token' do
- expect { subject }.to change { group.reload.runners_token }
+ context 'when user is owner' do
+ before do
+ group.add_owner(user)
+ end
+
+ it 'resets runner registration token' do
+ expect { subject }.to change { group.reload.runners_token }
+ end
+
+ it 'redirects the user to admin runners page' do
+ subject
+
+ expect(response).to redirect_to(group_settings_ci_cd_path)
+ end
end
- it 'redirects the user to admin runners page' do
- subject
+ context 'when user is not owner' do
+ before do
+ group.add_maintainer(user)
+ end
+
+ it 'renders a 404' do
+ subject
- expect(response).to redirect_to(group_settings_ci_cd_path)
+ expect(response).to have_gitlab_http_status(404)
+ end
end
end
end
diff --git a/spec/controllers/projects/ci/lints_controller_spec.rb b/spec/controllers/projects/ci/lints_controller_spec.rb
index 82c1374aa4f..cfa010c2d1c 100644
--- a/spec/controllers/projects/ci/lints_controller_spec.rb
+++ b/spec/controllers/projects/ci/lints_controller_spec.rb
@@ -51,7 +51,6 @@ describe Projects::Ci::LintsController do
- apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- ruby -v
- which ruby
- - gem install bundler --no-ri --no-rdoc
- bundle install --jobs $(nproc) "${FLAGS[@]}"
HEREDOC
end
diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb
index d46b9ffb3ce..4f4d3ca226f 100644
--- a/spec/controllers/projects/merge_requests_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests_controller_spec.rb
@@ -950,7 +950,7 @@ describe Projects::MergeRequestsController do
end
it 'returns 200' do
- get :discussions, namespace_id: project.namespace, project_id: project, id: merge_request.iid
+ get :discussions, params: { namespace_id: project.namespace, project_id: project, id: merge_request.iid }
expect(response.status).to eq(200)
end
@@ -969,7 +969,7 @@ describe Projects::MergeRequestsController do
expect(collection).to receive(:find_by_id).with(note_diff_file.id).and_call_original
end
- get :discussions, namespace_id: project.namespace, project_id: project, id: merge_request.iid
+ get :discussions, params: { namespace_id: project.namespace, project_id: project, id: merge_request.iid }
end
end
@@ -986,7 +986,7 @@ describe Projects::MergeRequestsController do
expect(collection).to receive(:find_by_id).with(note_diff_file.id).and_call_original
end
- get :discussions, namespace_id: project.namespace, project_id: project, id: merge_request.iid
+ get :discussions, params: { namespace_id: project.namespace, project_id: project, id: merge_request.iid }
end
it 'does not preload highlights when diff note is resolved' do
@@ -999,7 +999,7 @@ describe Projects::MergeRequestsController do
expect(collection).to receive(:find_by_id).with(note_diff_file.id).and_call_original
end
- get :discussions, namespace_id: project.namespace, project_id: project, id: merge_request.iid
+ get :discussions, params: { namespace_id: project.namespace, project_id: project, id: merge_request.iid }
end
end
end
diff --git a/spec/controllers/projects/snippets_controller_spec.rb b/spec/controllers/projects/snippets_controller_spec.rb
index 1a3fb4da15f..75c9839dd9b 100644
--- a/spec/controllers/projects/snippets_controller_spec.rb
+++ b/spec/controllers/projects/snippets_controller_spec.rb
@@ -379,6 +379,46 @@ describe Projects::SnippetsController do
end
end
+ describe "GET #show for embeddable content" do
+ let(:project_snippet) { create(:project_snippet, snippet_permission, project: project, author: user) }
+
+ before do
+ sign_in(user)
+
+ get :show, params: { namespace_id: project.namespace, project_id: project, id: project_snippet.to_param }, format: :js
+ end
+
+ context 'when snippet is private' do
+ let(:snippet_permission) { :private }
+
+ it 'responds with status 404' do
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context 'when snippet is public' do
+ let(:snippet_permission) { :public }
+
+ it 'responds with status 200' do
+ expect(assigns(:snippet)).to eq(project_snippet)
+ expect(response).to have_gitlab_http_status(200)
+ end
+ end
+
+ context 'when the project is private' do
+ let(:project) { create(:project_empty_repo, :private) }
+
+ context 'when snippet is public' do
+ let(:project_snippet) { create(:project_snippet, :public, project: project, author: user) }
+
+ it 'responds with status 404' do
+ expect(assigns(:snippet)).to eq(project_snippet)
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+ end
+
describe 'GET #raw' do
let(:project_snippet) do
create(
diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb
index ea067a01295..f84f069f4db 100644
--- a/spec/controllers/projects_controller_spec.rb
+++ b/spec/controllers/projects_controller_spec.rb
@@ -621,10 +621,10 @@ describe ProjectsController do
end
describe "GET refs" do
- let(:public_project) { create(:project, :public, :repository) }
+ let(:project) { create(:project, :public, :repository) }
it 'gets a list of branches and tags' do
- get :refs, params: { namespace_id: public_project.namespace, id: public_project, sort: 'updated_desc' }
+ get :refs, params: { namespace_id: project.namespace, id: project, sort: 'updated_desc' }
parsed_body = JSON.parse(response.body)
expect(parsed_body['Branches']).to include('master')
@@ -634,7 +634,7 @@ describe ProjectsController do
end
it "gets a list of branches, tags and commits" do
- get :refs, params: { namespace_id: public_project.namespace, id: public_project, ref: "123456" }
+ get :refs, params: { namespace_id: project.namespace, id: project, ref: "123456" }
parsed_body = JSON.parse(response.body)
expect(parsed_body["Branches"]).to include("master")
@@ -649,7 +649,7 @@ describe ProjectsController do
end
it "gets a list of branches, tags and commits" do
- get :refs, params: { namespace_id: public_project.namespace, id: public_project, ref: "123456" }
+ get :refs, params: { namespace_id: project.namespace, id: project, ref: "123456" }
parsed_body = JSON.parse(response.body)
expect(parsed_body["Branches"]).to include("master")
@@ -657,6 +657,22 @@ describe ProjectsController do
expect(parsed_body["Commits"]).to include("123456")
end
end
+
+ context 'when private project' do
+ let(:project) { create(:project, :repository) }
+
+ context 'as a guest' do
+ it 'renders forbidden' do
+ user = create(:user)
+ project.add_guest(user)
+
+ sign_in(user)
+ get :refs, params: { namespace_id: project.namespace, id: project }
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
end
describe 'POST #preview_markdown' do
diff --git a/spec/controllers/snippets_controller_spec.rb b/spec/controllers/snippets_controller_spec.rb
index d2a56518f65..5c6858dc7b2 100644
--- a/spec/controllers/snippets_controller_spec.rb
+++ b/spec/controllers/snippets_controller_spec.rb
@@ -80,6 +80,12 @@ describe SnippetsController do
expect(assigns(:snippet)).to eq(personal_snippet)
expect(response).to have_gitlab_http_status(200)
end
+
+ it 'responds with status 404 when embeddable content is requested' do
+ get :show, params: { id: personal_snippet.to_param }, format: :js
+
+ expect(response).to have_gitlab_http_status(404)
+ end
end
end
@@ -106,6 +112,12 @@ describe SnippetsController do
expect(assigns(:snippet)).to eq(personal_snippet)
expect(response).to have_gitlab_http_status(200)
end
+
+ it 'responds with status 404 when embeddable content is requested' do
+ get :show, params: { id: personal_snippet.to_param }, format: :js
+
+ expect(response).to have_gitlab_http_status(404)
+ end
end
context 'when not signed in' do
@@ -131,6 +143,13 @@ describe SnippetsController do
expect(assigns(:snippet)).to eq(personal_snippet)
expect(response).to have_gitlab_http_status(200)
end
+
+ it 'responds with status 200 when embeddable content is requested' do
+ get :show, params: { id: personal_snippet.to_param }, format: :js
+
+ expect(assigns(:snippet)).to eq(personal_snippet)
+ expect(response).to have_gitlab_http_status(200)
+ end
end
context 'when not signed in' do
diff --git a/spec/features/group_variables_spec.rb b/spec/features/group_variables_spec.rb
index 89e0cdd8ed7..57e3ddfb39c 100644
--- a/spec/features/group_variables_spec.rb
+++ b/spec/features/group_variables_spec.rb
@@ -7,7 +7,7 @@ describe 'Group variables', :js do
let(:page_path) { group_settings_ci_cd_path(group) }
before do
- group.add_maintainer(user)
+ group.add_owner(user)
gitlab_sign_in(user)
visit page_path
diff --git a/spec/features/groups/milestone_spec.rb b/spec/features/groups/milestone_spec.rb
index 174840794ed..d57eb87ca77 100644
--- a/spec/features/groups/milestone_spec.rb
+++ b/spec/features/groups/milestone_spec.rb
@@ -81,7 +81,7 @@ describe 'Group milestones' do
description: 'Lorem Ipsum is simply dummy text'
)
end
- let!(:active_project_milestone2) { create(:milestone, project: other_project, state: 'active', title: 'v1.0') }
+ let!(:active_project_milestone2) { create(:milestone, project: other_project, state: 'active', title: 'v1.1') }
let!(:closed_project_milestone1) { create(:milestone, project: project, state: 'closed', title: 'v2.0') }
let!(:closed_project_milestone2) { create(:milestone, project: other_project, state: 'closed', title: 'v2.0') }
let!(:active_group_milestone) { create(:milestone, group: group, state: 'active', title: 'GL-113') }
@@ -104,7 +104,7 @@ describe 'Group milestones' do
legacy_milestone = GroupMilestone.build_collection(group, group.projects, { state: 'active' }).first
expect(page).to have_selector("#milestone_#{active_group_milestone.id}", count: 1)
- expect(page).to have_selector("#milestone_#{legacy_milestone.milestones.first.id}", count: 1)
+ expect(page).to have_selector("#milestone_#{legacy_milestone.milestone.id}", count: 1)
end
it 'shows milestone detail and supports its edit' do
@@ -121,6 +121,7 @@ describe 'Group milestones' do
it 'renders milestones' do
expect(page).to have_content('v1.0')
+ expect(page).to have_content('v1.1')
expect(page).to have_content('GL-113')
expect(page).to have_link(
'1 Issue',
diff --git a/spec/features/groups/milestones_sorting_spec.rb b/spec/features/groups/milestones_sorting_spec.rb
index bc226ff41c1..7bc015ea28f 100644
--- a/spec/features/groups/milestones_sorting_spec.rb
+++ b/spec/features/groups/milestones_sorting_spec.rb
@@ -42,6 +42,7 @@ describe 'Milestones sorting', :js do
expect(page).to have_button('Due later')
+ # assert descending sorting
within '.milestones' do
expect(page.all('ul.content-list > li').first.text).to include('v1.0')
expect(page.all('ul.content-list > li')[1].text).to include('v3.0')
diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb
index d7531d5fcd9..3b7a17ef355 100644
--- a/spec/features/issues/gfm_autocomplete_spec.rb
+++ b/spec/features/issues/gfm_autocomplete_spec.rb
@@ -3,6 +3,8 @@ require 'rails_helper'
describe 'GFM autocomplete', :js do
let(:issue_xss_title) { 'This will execute alert<img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;' }
let(:user_xss_title) { 'eve <img src=x onerror=alert(2)&lt;img src=x onerror=alert(1)&gt;' }
+ let(:label_xss_title) { 'alert label &lt;img src=x onerror="alert(\'Hello xss\');" a'}
+ let(:milestone_xss_title) { 'alert milestone &lt;img src=x onerror="alert(\'Hello xss\');" a' }
let(:user_xss) { create(:user, name: user_xss_title, username: 'xss.user') }
let(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') }
@@ -25,10 +27,14 @@ describe 'GFM autocomplete', :js do
simulate_input('#issue-description', "@#{user.name[0...3]}")
+ wait_for_requests
+
find('.atwho-view .cur').click
click_button 'Save changes'
+ wait_for_requests
+
expect(find('.description')).to have_content(user.to_reference)
end
@@ -47,6 +53,8 @@ describe 'GFM autocomplete', :js do
find('#note-body').native.send_keys('#')
end
+ wait_for_requests
+
expect(page).to have_selector('.atwho-container')
page.within '.atwho-container #at-view-issues' do
@@ -59,6 +67,8 @@ describe 'GFM autocomplete', :js do
find('#note-body').native.send_keys('@ev')
end
+ wait_for_requests
+
expect(page).to have_selector('.atwho-container')
page.within '.atwho-container #at-view-users' do
@@ -66,6 +76,22 @@ describe 'GFM autocomplete', :js do
end
end
+ it 'opens autocomplete menu for Milestone when field starts with text with item escaping HTML characters' do
+ create(:milestone, project: project, title: milestone_xss_title)
+
+ page.within '.timeline-content-form' do
+ find('#note-body').native.send_keys('%')
+ end
+
+ wait_for_requests
+
+ expect(page).to have_selector('.atwho-container')
+
+ page.within '.atwho-container #at-view-milestones' do
+ expect(find('li').text).to have_content('alert milestone')
+ end
+ end
+
it 'doesnt open autocomplete menu character is prefixed with text' do
page.within '.timeline-content-form' do
find('#note-body').native.send_keys('testing')
@@ -258,12 +284,28 @@ describe 'GFM autocomplete', :js do
let!(:bug) { create(:label, project: project, title: 'bug') }
let!(:feature_proposal) { create(:label, project: project, title: 'feature proposal') }
+ it 'opens autocomplete menu for Labels when field starts with text with item escaping HTML characters' do
+ create(:label, project: project, title: label_xss_title)
+
+ note = find('#note-body')
+
+ # It should show all the labels on "~".
+ type(note, '~')
+
+ wait_for_requests
+
+ page.within '.atwho-container #at-view-labels' do
+ expect(find('.atwho-view-ul').text).to have_content('alert label')
+ end
+ end
+
context 'when no labels are assigned' do
it 'shows labels' do
note = find('#note-body')
# It should show all the labels on "~".
type(note, '~')
+ wait_for_requests
expect_labels(shown: [backend, bug, feature_proposal])
# It should show all the labels on "/label ~".
@@ -290,6 +332,7 @@ describe 'GFM autocomplete', :js do
# It should show all the labels on "~".
type(note, '~')
+ wait_for_requests
expect_labels(shown: [backend, bug, feature_proposal])
# It should show only unset labels on "/label ~".
@@ -316,6 +359,7 @@ describe 'GFM autocomplete', :js do
# It should show all the labels on "~".
type(note, '~')
+ wait_for_requests
expect_labels(shown: [backend, bug, feature_proposal])
# It should show no labels on "/label ~".
diff --git a/spec/features/merge_request/user_sees_versions_spec.rb b/spec/features/merge_request/user_sees_versions_spec.rb
index f7512294bef..63d8decc2d2 100644
--- a/spec/features/merge_request/user_sees_versions_spec.rb
+++ b/spec/features/merge_request/user_sees_versions_spec.rb
@@ -64,6 +64,17 @@ describe 'Merge request > User sees versions', :js do
end
end
+ it 'shows the commit SHAs for every version in the dropdown' do
+ page.within '.mr-version-dropdown' do
+ find('.btn-default').click
+
+ page.within('.dropdown-content') do
+ shas = merge_request.merge_request_diffs.map { |diff| Commit.truncate_sha(diff.head_commit_sha) }
+ shas.each { |sha| expect(page).to have_content(sha) }
+ end
+ end
+ end
+
it 'shows comments that were last relevant at that version' do
expect(page).to have_content '5 changed files'
diff --git a/spec/features/merge_request/user_tries_to_access_private_repository_through_new_mr_spec.rb b/spec/features/merge_request/user_tries_to_access_private_repository_through_new_mr_spec.rb
new file mode 100644
index 00000000000..9318b5f1ebb
--- /dev/null
+++ b/spec/features/merge_request/user_tries_to_access_private_repository_through_new_mr_spec.rb
@@ -0,0 +1,37 @@
+require 'spec_helper'
+
+describe 'Merge Request > Tries to access private repo of public project' do
+ let(:current_user) { create(:user) }
+ let(:private_project) do
+ create(:project, :public, :repository,
+ path: 'nothing-to-see-here',
+ name: 'nothing to see here',
+ repository_access_level: ProjectFeature::PRIVATE)
+ end
+ let(:owned_project) do
+ create(:project, :public, :repository,
+ namespace: current_user.namespace,
+ creator: current_user)
+ end
+
+ context 'when the user enters the querystring info for the other project' do
+ let(:mr_path) do
+ project_new_merge_request_diffs_path(
+ owned_project,
+ merge_request: {
+ source_project_id: private_project.id,
+ source_branch: 'feature'
+ }
+ )
+ end
+
+ before do
+ sign_in current_user
+ visit mr_path
+ end
+
+ it "does not mention the project the user can't see the repo of" do
+ expect(page).not_to have_content('nothing-to-see-here')
+ end
+ end
+end
diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb
index cb7a912946c..09de983f669 100644
--- a/spec/features/runners_spec.rb
+++ b/spec/features/runners_spec.rb
@@ -259,8 +259,9 @@ describe 'Runners' do
context 'group runners in group settings' do
let(:group) { create(:group) }
+
before do
- group.add_maintainer(user)
+ group.add_owner(user)
end
context 'group with no runners' do
diff --git a/spec/features/users/overview_spec.rb b/spec/features/users/overview_spec.rb
index 873de85708a..8748230fa0c 100644
--- a/spec/features/users/overview_spec.rb
+++ b/spec/features/users/overview_spec.rb
@@ -33,6 +33,8 @@ describe 'Overview tab on a user profile', :js do
it 'does not show any entries in the list of activities' do
page.within('.activities-block') do
+ expect(page).to have_selector('.loading', visible: false)
+ expect(page).to have_content('No activities found')
expect(page).not_to have_selector('.event-item')
end
end
@@ -93,6 +95,7 @@ describe 'Overview tab on a user profile', :js do
it 'it shows an empty project list with an info message' do
page.within('.projects-block') do
+ expect(page).to have_selector('.loading', visible: false)
expect(page).to have_content('No projects found')
expect(page).not_to have_selector('.project-row')
end
diff --git a/spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml b/spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml
index 0bab94a7c2e..1e88cd120aa 100644
--- a/spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml
+++ b/spec/fixtures/gitlab/ci/external_files/.gitlab-ci-template-1.yml
@@ -2,7 +2,6 @@ before_script:
- apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- ruby -v
- which ruby
- - gem install bundler --no-ri --no-rdoc
- bundle install --jobs $(nproc) "${FLAGS[@]}"
rspec:
diff --git a/spec/javascripts/notes/components/discussion_filter_spec.js b/spec/javascripts/notes/components/discussion_filter_spec.js
index 9070d968cfd..5efcab436e4 100644
--- a/spec/javascripts/notes/components/discussion_filter_spec.js
+++ b/spec/javascripts/notes/components/discussion_filter_spec.js
@@ -7,8 +7,9 @@ import { discussionFiltersMock, discussionMock } from '../mock_data';
describe('DiscussionFilter component', () => {
let vm;
let store;
+ let eventHub;
- beforeEach(() => {
+ const mountComponent = () => {
store = createStore();
const discussions = [
@@ -22,7 +23,7 @@ describe('DiscussionFilter component', () => {
const selectedValue = discussionFiltersMock[0].value;
store.state.discussions = discussions;
- vm = mountComponentWithStore(Component, {
+ return mountComponentWithStore(Component, {
el: null,
store,
props: {
@@ -30,6 +31,11 @@ describe('DiscussionFilter component', () => {
selectedValue,
},
});
+ };
+
+ beforeEach(() => {
+ window.mrTabs = undefined;
+ vm = mountComponent();
});
afterEach(() => {
@@ -83,4 +89,30 @@ describe('DiscussionFilter component', () => {
expect(defaultFilter.lastChild.classList).toContain('dropdown-divider');
});
+
+ describe('Merge request tabs', () => {
+ eventHub = new Vue();
+
+ beforeEach(() => {
+ window.mrTabs = {
+ eventHub,
+ currentTab: 'show',
+ };
+
+ vm = mountComponent();
+ });
+
+ afterEach(() => {
+ window.mrTabs = undefined;
+ });
+
+ it('only renders when discussion tab is active', done => {
+ eventHub.$emit('MergeRequestTabChange', 'commit');
+
+ vm.$nextTick(() => {
+ expect(vm.$el.querySelector).toBeUndefined();
+ done();
+ });
+ });
+ });
});
diff --git a/spec/lib/banzai/filter/external_link_filter_spec.rb b/spec/lib/banzai/filter/external_link_filter_spec.rb
index 2a3c0cd78b8..e6dae8d5382 100644
--- a/spec/lib/banzai/filter/external_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/external_link_filter_spec.rb
@@ -49,16 +49,16 @@ describe Banzai::Filter::ExternalLinkFilter do
end
context 'for invalid urls' do
- it 'skips broken hrefs' do
+ it 'adds rel and target attributes to broken hrefs' do
doc = filter %q(<p><a href="don't crash on broken urls">Google</a></p>)
- expected = %q(<p><a href="don't%20crash%20on%20broken%20urls">Google</a></p>)
+ expected = %q(<p><a href="don't%20crash%20on%20broken%20urls" rel="nofollow noreferrer noopener" target="_blank">Google</a></p>)
expect(doc.to_html).to eq(expected)
end
- it 'skips improperly formatted mailtos' do
+ it 'adds rel and target to improperly formatted mailtos' do
doc = filter %q(<p><a href="mailto://jblogs@example.com">Email</a></p>)
- expected = %q(<p><a href="mailto://jblogs@example.com">Email</a></p>)
+ expected = %q(<p><a href="mailto://jblogs@example.com" rel="nofollow noreferrer noopener" target="_blank">Email</a></p>)
expect(doc.to_html).to eq(expected)
end
diff --git a/spec/lib/banzai/filter/label_reference_filter_spec.rb b/spec/lib/banzai/filter/label_reference_filter_spec.rb
index 00257ed7904..9cfdb9e53a2 100644
--- a/spec/lib/banzai/filter/label_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/label_reference_filter_spec.rb
@@ -236,6 +236,24 @@ describe Banzai::Filter::LabelReferenceFilter do
end
end
+ context 'References with html entities' do
+ let!(:label) { create(:label, name: '&lt;html&gt;', project: project) }
+
+ it 'links to a valid reference' do
+ doc = reference_filter('See ~"&lt;html&gt;"')
+
+ expect(doc.css('a').first.attr('href')).to eq urls
+ .project_issues_url(project, label_name: label.name)
+ expect(doc.text).to eq 'See <html>'
+ end
+
+ it 'ignores invalid label names and escapes entities' do
+ act = %(Label #{Label.reference_prefix}"&lt;non valid&gt;")
+
+ expect(reference_filter(act).to_html).to eq act
+ end
+ end
+
describe 'consecutive references' do
let(:bug) { create(:label, name: 'bug', project: project) }
let(:feature_proposal) { create(:label, name: 'feature proposal', project: project) }
diff --git a/spec/lib/gitlab/ci/config/external/file/local_spec.rb b/spec/lib/gitlab/ci/config/external/file/local_spec.rb
index 541deb13b97..645db642e29 100644
--- a/spec/lib/gitlab/ci/config/external/file/local_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/local_spec.rb
@@ -44,7 +44,6 @@ describe Gitlab::Ci::Config::External::File::Local do
- apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- ruby -v
- which ruby
- - gem install bundler --no-ri --no-rdoc
- bundle install --jobs $(nproc) "${FLAGS[@]}"
HEREDOC
end
diff --git a/spec/lib/gitlab/ci/config/external/file/remote_spec.rb b/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
index 7c1a1c38736..eaf621e4140 100644
--- a/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/file/remote_spec.rb
@@ -11,7 +11,6 @@ describe Gitlab::Ci::Config::External::File::Remote do
- apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- ruby -v
- which ruby
- - gem install bundler --no-ri --no-rdoc
- bundle install --jobs $(nproc) "${FLAGS[@]}"
HEREDOC
end
diff --git a/spec/lib/gitlab/ci/config/external/processor_spec.rb b/spec/lib/gitlab/ci/config/external/processor_spec.rb
index 1a05f716247..dbd28e9745c 100644
--- a/spec/lib/gitlab/ci/config/external/processor_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/processor_spec.rb
@@ -51,7 +51,6 @@ describe Gitlab::Ci::Config::External::Processor do
- apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- ruby -v
- which ruby
- - gem install bundler --no-ri --no-rdoc
- bundle install --jobs $(nproc) "${FLAGS[@]}"
rspec:
@@ -86,7 +85,6 @@ describe Gitlab::Ci::Config::External::Processor do
- apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs
- ruby -v
- which ruby
- - gem install bundler --no-ri --no-rdoc
- bundle install --jobs $(nproc) "${FLAGS[@]}"
HEREDOC
end
diff --git a/spec/lib/gitlab/ci/config_spec.rb b/spec/lib/gitlab/ci/config_spec.rb
index 975e11e8cc1..ea6f1e20014 100644
--- a/spec/lib/gitlab/ci/config_spec.rb
+++ b/spec/lib/gitlab/ci/config_spec.rb
@@ -170,7 +170,6 @@ describe Gitlab::Ci::Config do
before_script_values = [
"apt-get update -qq && apt-get install -y -qq sqlite3 libsqlite3-dev nodejs", "ruby -v",
"which ruby",
- "gem install bundler --no-ri --no-rdoc",
"bundle install --jobs $(nproc) \"${FLAGS[@]}\""
]
variables = {
diff --git a/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
index 75a177d2d1f..6aa802ce6fd 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/command_spec.rb
@@ -182,4 +182,24 @@ describe Gitlab::Ci::Pipeline::Chain::Command do
it { is_expected.to eq(false) }
end
end
+
+ describe '#ambiguous_ref' do
+ let(:project) { create(:project, :repository) }
+ let(:command) { described_class.new(project: project, origin_ref: 'ref') }
+
+ subject { command.ambiguous_ref? }
+
+ context 'when ref is not ambiguous' do
+ it { is_expected. to eq(false) }
+ end
+
+ context 'when ref is ambiguous' do
+ before do
+ project.repository.add_tag(project.creator, 'ref', 'master')
+ project.repository.add_branch(project.creator, 'ref', 'master')
+ end
+
+ it { is_expected. to eq(true) }
+ end
+ end
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
index 284aed91e29..1b014ecfaa4 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
@@ -14,6 +14,7 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do
Gitlab::Ci::Pipeline::Chain::Command.new(
project: project,
current_user: user,
+ origin_ref: 'master',
seeds_block: nil)
end
@@ -106,6 +107,7 @@ describe Gitlab::Ci::Pipeline::Chain::Populate do
Gitlab::Ci::Pipeline::Chain::Command.new(
project: project,
current_user: user,
+ origin_ref: 'master',
seeds_block: seeds_block)
end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb
index fb1b53fc55c..a7cad423d09 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/validate/repository_spec.rb
@@ -42,6 +42,27 @@ describe Gitlab::Ci::Pipeline::Chain::Validate::Repository do
end
end
+ context 'when ref is ambiguous' do
+ let(:project) do
+ create(:project, :repository).tap do |proj|
+ proj.repository.add_tag(user, 'master', 'master')
+ end
+ end
+ let(:command) do
+ Gitlab::Ci::Pipeline::Chain::Command.new(
+ project: project, current_user: user, origin_ref: 'master')
+ end
+
+ it 'breaks the chain' do
+ expect(step.break?).to be true
+ end
+
+ it 'adds an error about missing ref' do
+ expect(pipeline.errors.to_a)
+ .to include 'Ref is ambiguous'
+ end
+ end
+
context 'when does not have existing SHA set' do
let(:command) do
Gitlab::Ci::Pipeline::Chain::Command.new(
diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
index fffa727c2ed..2cf812b26dc 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb
@@ -1,7 +1,8 @@
require 'spec_helper'
describe Gitlab::Ci::Pipeline::Seed::Build do
- let(:pipeline) { create(:ci_empty_pipeline) }
+ let(:project) { create(:project, :repository) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: project) }
let(:attributes) do
{ name: 'rspec',
diff --git a/spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb
index 05ce3412fd8..82f741845db 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/stage_spec.rb
@@ -1,7 +1,8 @@
require 'spec_helper'
describe Gitlab::Ci::Pipeline::Seed::Stage do
- let(:pipeline) { create(:ci_empty_pipeline) }
+ let(:project) { create(:project, :repository) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: project) }
let(:attributes) do
{ name: 'test',
diff --git a/spec/lib/gitlab/cleanup/remote_uploads_spec.rb b/spec/lib/gitlab/cleanup/remote_uploads_spec.rb
index 8d03baeb07b..35642cd6e50 100644
--- a/spec/lib/gitlab/cleanup/remote_uploads_spec.rb
+++ b/spec/lib/gitlab/cleanup/remote_uploads_spec.rb
@@ -25,7 +25,7 @@ describe Gitlab::Cleanup::RemoteUploads do
expect(::Fog::Storage).to receive(:new).and_return(connection)
- expect(connection).to receive(:directories).and_return(double(get: directory))
+ expect(connection).to receive(:directories).and_return(double(new: directory))
expect(directory).to receive(:files).and_return(remote_files)
end
diff --git a/spec/lib/gitlab/middleware/go_spec.rb b/spec/lib/gitlab/middleware/go_spec.rb
index 7a3a9ab875b..f52095bf633 100644
--- a/spec/lib/gitlab/middleware/go_spec.rb
+++ b/spec/lib/gitlab/middleware/go_spec.rb
@@ -96,43 +96,36 @@ describe Gitlab::Middleware::Go do
it_behaves_like 'unauthorized'
end
- end
-
- context 'using warden' do
- before do
- env['warden'] = double(authenticate: current_user)
- end
- context 'when active' do
- it_behaves_like 'authenticated'
- end
-
- context 'when blocked' do
+ context 'with user is blocked' do
before do
- current_user.block!
+ current_user.block
end
it_behaves_like 'unauthorized'
end
end
- context 'using a personal access token' do
- let(:personal_access_token) { create(:personal_access_token, user: current_user) }
-
- before do
- env['HTTP_PRIVATE_TOKEN'] = personal_access_token.token
- end
-
- context 'with api scope' do
- it_behaves_like 'authenticated'
- end
+ context 'using basic auth' do
+ context 'using a personal access token' do
+ let(:personal_access_token) { create(:personal_access_token, user: current_user) }
- context 'with read_user scope' do
before do
- personal_access_token.update_attribute(:scopes, [:read_user])
+ env['REMOTE_ADDR'] = "192.168.0.1"
+ env['HTTP_AUTHORIZATION'] = ActionController::HttpAuthentication::Basic.encode_credentials(current_user.username, personal_access_token.token)
end
- it_behaves_like 'unauthorized'
+ context 'with api scope' do
+ it_behaves_like 'authenticated'
+ end
+
+ context 'with read_user scope' do
+ before do
+ personal_access_token.update_attribute(:scopes, [:read_user])
+ end
+
+ it_behaves_like 'unauthorized'
+ end
end
end
end
diff --git a/spec/lib/json_web_token/rsa_token_spec.rb b/spec/lib/json_web_token/rsa_token_spec.rb
index d6edc964844..a3c54651e80 100644
--- a/spec/lib/json_web_token/rsa_token_spec.rb
+++ b/spec/lib/json_web_token/rsa_token_spec.rb
@@ -25,7 +25,7 @@ describe JSONWebToken::RSAToken do
rsa_token['key'] = 'value'
end
- subject { JWT.decode(rsa_encoded, rsa_key) }
+ subject { JWT.decode(rsa_encoded, rsa_key, true, { algorithm: 'RS256' }) }
it { expect {subject}.not_to raise_error }
it { expect(subject.first).to include('key' => 'value') }
@@ -39,7 +39,7 @@ describe JSONWebToken::RSAToken do
context 'for invalid key to raise an exception' do
let(:new_key) { OpenSSL::PKey::RSA.generate(512) }
- subject { JWT.decode(rsa_encoded, new_key) }
+ subject { JWT.decode(rsa_encoded, new_key, true, { algorithm: 'RS256' }) }
it { expect {subject}.to raise_error(JWT::DecodeError) }
end
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index fe7f5f8e1e3..7baf4d93804 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -2386,6 +2386,8 @@ describe Ci::Build do
end
context 'when protected variable is defined' do
+ let(:ref) { Gitlab::Git::BRANCH_REF_PREFIX + build.ref }
+
let(:protected_variable) do
{ key: 'PROTECTED_KEY', value: 'protected_value', public: false }
end
@@ -2398,7 +2400,7 @@ describe Ci::Build do
context 'when the branch is protected' do
before do
- allow(build.project).to receive(:protected_for?).with(build.ref).and_return(true)
+ allow(build.project).to receive(:protected_for?).with(ref).and_return(true)
end
it { is_expected.to include(protected_variable) }
@@ -2406,7 +2408,7 @@ describe Ci::Build do
context 'when the tag is protected' do
before do
- allow(build.project).to receive(:protected_for?).with(build.ref).and_return(true)
+ allow(build.project).to receive(:protected_for?).with(ref).and_return(true)
end
it { is_expected.to include(protected_variable) }
@@ -2431,6 +2433,8 @@ describe Ci::Build do
end
context 'when group protected variable is defined' do
+ let(:ref) { Gitlab::Git::BRANCH_REF_PREFIX + build.ref }
+
let(:protected_variable) do
{ key: 'PROTECTED_KEY', value: 'protected_value', public: false }
end
@@ -2443,7 +2447,7 @@ describe Ci::Build do
context 'when the branch is protected' do
before do
- allow(build.project).to receive(:protected_for?).with(build.ref).and_return(true)
+ allow(build.project).to receive(:protected_for?).with(ref).and_return(true)
end
it { is_expected.to include(protected_variable) }
@@ -2451,7 +2455,7 @@ describe Ci::Build do
context 'when the tag is protected' do
before do
- allow(build.project).to receive(:protected_for?).with(build.ref).and_return(true)
+ allow(build.project).to receive(:protected_for?).with(ref).and_return(true)
end
it { is_expected.to include(protected_variable) }
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index b67c6a4cffa..17f33785fda 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -397,6 +397,10 @@ describe Ci::Pipeline, :mailer do
end
describe '#protected_ref?' do
+ before do
+ pipeline.project = create(:project, :repository)
+ end
+
it 'delegates method to project' do
expect(pipeline).not_to be_protected_ref
end
diff --git a/spec/models/clusters/applications/runner_spec.rb b/spec/models/clusters/applications/runner_spec.rb
index 47daa79873e..cae23daac8c 100644
--- a/spec/models/clusters/applications/runner_spec.rb
+++ b/spec/models/clusters/applications/runner_spec.rb
@@ -18,7 +18,7 @@ describe Clusters::Applications::Runner do
let(:application) { create(:clusters_applications_runner, :scheduled, version: '0.1.30') }
it 'updates the application version' do
- expect(application.reload.version).to eq('0.1.39')
+ expect(application.reload.version).to eq('0.1.43')
end
end
end
@@ -46,7 +46,7 @@ describe Clusters::Applications::Runner do
it 'should be initialized with 4 arguments' do
expect(subject.name).to eq('runner')
expect(subject.chart).to eq('runner/gitlab-runner')
- expect(subject.version).to eq('0.1.39')
+ expect(subject.version).to eq('0.1.43')
expect(subject).not_to be_rbac
expect(subject.repository).to eq('https://charts.gitlab.io')
expect(subject.files).to eq(gitlab_runner.files)
@@ -64,7 +64,7 @@ describe Clusters::Applications::Runner do
let(:gitlab_runner) { create(:clusters_applications_runner, :errored, runner: ci_runner, version: '0.1.13') }
it 'should be initialized with the locked version' do
- expect(subject.version).to eq('0.1.39')
+ expect(subject.version).to eq('0.1.43')
end
end
end
diff --git a/spec/models/concerns/has_ref_spec.rb b/spec/models/concerns/has_ref_spec.rb
new file mode 100644
index 00000000000..8aed72d77a4
--- /dev/null
+++ b/spec/models/concerns/has_ref_spec.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe HasRef do
+ describe '#branch?' do
+ let(:build) { create(:ci_build) }
+
+ subject { build.branch? }
+
+ context 'is not a tag' do
+ before do
+ build.tag = false
+ end
+
+ it 'return true when tag is set to false' do
+ is_expected.to be_truthy
+ end
+ end
+
+ context 'is not a tag' do
+ before do
+ build.tag = true
+ end
+
+ it 'return false when tag is set to true' do
+ is_expected.to be_falsey
+ end
+ end
+ end
+
+ describe '#git_ref' do
+ subject { build.git_ref }
+
+ context 'when tag is true' do
+ let(:build) { create(:ci_build, tag: true) }
+
+ it 'returns a tag ref' do
+ is_expected.to start_with(Gitlab::Git::TAG_REF_PREFIX)
+ end
+ end
+
+ context 'when tag is false' do
+ let(:build) { create(:ci_build, tag: false) }
+
+ it 'returns a branch ref' do
+ is_expected.to start_with(Gitlab::Git::BRANCH_REF_PREFIX)
+ end
+ end
+
+ context 'when tag is nil' do
+ let(:build) { create(:ci_build, tag: nil) }
+
+ it 'returns a branch ref' do
+ is_expected.to start_with(Gitlab::Git::BRANCH_REF_PREFIX)
+ end
+ end
+ end
+end
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index 81748681528..a64720f1876 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -243,6 +243,20 @@ describe Event do
expect(event.visible_to_user?(admin)).to eq true
end
end
+
+ context 'private project' do
+ let(:project) { create(:project, :private) }
+ let(:target) { note_on_issue }
+
+ it do
+ expect(event.visible_to_user?(non_member)).to eq false
+ expect(event.visible_to_user?(author)).to eq false
+ expect(event.visible_to_user?(assignee)).to eq false
+ expect(event.visible_to_user?(member)).to eq true
+ expect(event.visible_to_user?(guest)).to eq true
+ expect(event.visible_to_user?(admin)).to eq true
+ end
+ end
end
context 'merge request diff note event' do
@@ -265,8 +279,8 @@ describe Event do
it do
expect(event.visible_to_user?(non_member)).to eq false
- expect(event.visible_to_user?(author)).to eq true
- expect(event.visible_to_user?(assignee)).to eq true
+ expect(event.visible_to_user?(author)).to eq false
+ expect(event.visible_to_user?(assignee)).to eq false
expect(event.visible_to_user?(member)).to eq true
expect(event.visible_to_user?(guest)).to eq false
expect(event.visible_to_user?(admin)).to eq true
diff --git a/spec/models/global_milestone_spec.rb b/spec/models/global_milestone_spec.rb
index b6355455c1d..62699df5611 100644
--- a/spec/models/global_milestone_spec.rb
+++ b/spec/models/global_milestone_spec.rb
@@ -65,56 +65,103 @@ describe GlobalMilestone do
)
end
- before do
- projects = [
+ let!(:projects) do
+ [
project1,
project2,
project3
]
-
- @global_milestones = described_class.build_collection(projects, {})
end
- it 'has all project milestones' do
- expect(@global_milestones.count).to eq(2)
+ let!(:global_milestones) { described_class.build_collection(projects, {}) }
+
+ context 'when building a collection of milestones' do
+ it 'has all project milestones' do
+ expect(global_milestones.count).to eq(6)
+ end
+
+ it 'has all project milestones titles' do
+ expect(global_milestones.map(&:title)).to match_array(['Milestone v1.2', 'Milestone v1.2', 'Milestone v1.2', 'VD-123', 'VD-123', 'VD-123'])
+ end
+
+ it 'has all project milestones' do
+ expect(global_milestones.size).to eq(6)
+ end
+
+ it 'sorts collection by due date' do
+ expect(global_milestones.map(&:due_date)).to eq [milestone1_due_date, milestone1_due_date, milestone1_due_date, nil, nil, nil]
+ end
end
- it 'has all project milestones titles' do
- expect(@global_milestones.map(&:title)).to match_array(['Milestone v1.2', 'VD-123'])
+ context 'when adding new milestones' do
+ it 'does not add more queries' do
+ control_count = ActiveRecord::QueryRecorder.new do
+ described_class.build_collection(projects, {})
+ end.count
+
+ create_list(:milestone, 3, project: project3)
+
+ expect do
+ described_class.build_collection(projects, {})
+ end.not_to exceed_all_query_limit(control_count)
+ end
end
+ end
+
+ describe '.states_count' do
+ context 'when the projects have milestones' do
+ before do
+ create(:closed_milestone, title: 'Active Group Milestone', project: project3)
+ create(:active_milestone, title: 'Active Group Milestone', project: project1)
+ create(:active_milestone, title: 'Active Group Milestone', project: project2)
+ create(:closed_milestone, title: 'Closed Group Milestone', project: project1)
+ create(:closed_milestone, title: 'Closed Group Milestone', project: project2)
+ create(:closed_milestone, title: 'Closed Group Milestone', project: project3)
+ create(:closed_milestone, title: 'Closed Group Milestone 4', group: group)
+ end
+
+ it 'returns the quantity of global milestones and group milestones in each possible state' do
+ expected_count = { opened: 2, closed: 5, all: 7 }
- it 'has all project milestones' do
- expect(@global_milestones.map { |group_milestone| group_milestone.milestones.count }.sum).to eq(6)
+ count = described_class.states_count(Project.all, group)
+
+ expect(count).to eq(expected_count)
+ end
+
+ it 'returns the quantity of global milestones in each possible state' do
+ expected_count = { opened: 2, closed: 4, all: 6 }
+
+ count = described_class.states_count(Project.all)
+
+ expect(count).to eq(expected_count)
+ end
end
- it 'sorts collection by due date' do
- expect(@global_milestones.map(&:due_date)).to eq [nil, milestone1_due_date]
+ context 'when the projects do not have milestones' do
+ before do
+ project1
+ end
+
+ it 'returns 0 as the quantity of global milestones in each state' do
+ expected_count = { opened: 0, closed: 0, all: 0 }
+
+ count = described_class.states_count(Project.all)
+
+ expect(count).to eq(expected_count)
+ end
end
end
describe '#initialize' do
let(:milestone1_project1) { create(:milestone, title: "Milestone v1.2", project: project1) }
- let(:milestone1_project2) { create(:milestone, title: "Milestone v1.2", project: project2) }
- let(:milestone1_project3) { create(:milestone, title: "Milestone v1.2", project: project3) }
-
- before do
- milestones =
- [
- milestone1_project1,
- milestone1_project2,
- milestone1_project3
- ]
- milestones_relation = Milestone.where(id: milestones.map(&:id))
-
- @global_milestone = described_class.new(milestone1_project1.title, milestones_relation)
- end
+ subject(:global_milestone) { described_class.new(milestone1_project1) }
it 'has exactly one group milestone' do
- expect(@global_milestone.title).to eq('Milestone v1.2')
+ expect(global_milestone.title).to eq('Milestone v1.2')
end
it 'has all project milestones with the same title' do
- expect(@global_milestone.milestones.count).to eq(3)
+ expect(global_milestone.milestone).to eq(milestone1_project1)
end
end
@@ -122,7 +169,7 @@ describe GlobalMilestone do
let(:milestone) { create(:milestone, title: "git / test", project: project1) }
it 'strips out slashes and spaces' do
- global_milestone = described_class.new(milestone.title, Milestone.where(id: milestone.id))
+ global_milestone = described_class.new(milestone)
expect(global_milestone.safe_title).to eq('git-test')
end
@@ -132,11 +179,8 @@ describe GlobalMilestone do
context 'when at least one milestone is active' do
it 'returns active' do
title = 'Active Group Milestone'
- milestones = [
- create(:active_milestone, title: title),
- create(:closed_milestone, title: title)
- ]
- global_milestone = described_class.new(title, milestones)
+
+ global_milestone = described_class.new(create(:active_milestone, title: title))
expect(global_milestone.state).to eq('active')
end
@@ -145,11 +189,8 @@ describe GlobalMilestone do
context 'when all milestones are closed' do
it 'returns closed' do
title = 'Closed Group Milestone'
- milestones = [
- create(:closed_milestone, title: title),
- create(:closed_milestone, title: title)
- ]
- global_milestone = described_class.new(title, milestones)
+
+ global_milestone = described_class.new(create(:closed_milestone, title: title))
expect(global_milestone.state).to eq('closed')
end
diff --git a/spec/models/group_milestone_spec.rb b/spec/models/group_milestone_spec.rb
index b60676afc91..fcc33cd95fe 100644
--- a/spec/models/group_milestone_spec.rb
+++ b/spec/models/group_milestone_spec.rb
@@ -20,13 +20,36 @@ describe GroupMilestone do
end
describe '.build_collection' do
- before do
- project_milestone
+ let(:group) { create(:group) }
+ let(:project1) { create(:project, group: group) }
+ let(:project2) { create(:project, path: 'gitlab-ci', group: group) }
+ let(:project3) { create(:project, path: 'cookbook-gitlab', group: group) }
+
+ let!(:projects) do
+ [
+ project1,
+ project2,
+ project3
+ ]
end
it 'returns array of milestones, each with group assigned' do
milestones = described_class.build_collection(group, [project], {})
expect(milestones).to all(have_attributes(group: group))
end
+
+ context 'when adding new milestones' do
+ it 'does not add more queries' do
+ control_count = ActiveRecord::QueryRecorder.new do
+ described_class.build_collection(group, projects, {})
+ end.count
+
+ create(:milestone, title: 'This title', project: project1)
+
+ expect do
+ described_class.build_collection(group, projects, {})
+ end.not_to exceed_all_query_limit(control_count)
+ end
+ end
end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index a01f76a5bab..4b6592020c1 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -299,6 +299,13 @@ describe Project do
expect(project.errors[:import_url].first).to include('Requests to localhost are not allowed')
end
+ it 'does not allow import_url pointing to the local network' do
+ project = build(:project, import_url: 'https://192.168.1.1')
+
+ expect(project).to be_invalid
+ expect(project.errors[:import_url].first).to include('Requests to the local network are not allowed')
+ end
+
it "does not allow import_url with invalid ports for new projects" do
project = build(:project, import_url: 'http://github.com:25/t.git')
@@ -2543,6 +2550,10 @@ describe Project do
end
context 'when the ref is not protected' do
+ before do
+ allow(project).to receive(:protected_for?).with('ref').and_return(false)
+ end
+
it 'contains only the CI variables' do
is_expected.to contain_exactly(ci_variable)
end
@@ -2582,42 +2593,139 @@ describe Project do
end
describe '#protected_for?' do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
- subject { project.protected_for?('ref') }
+ subject { project.protected_for?(ref) }
- context 'when the ref is not protected' do
+ shared_examples 'ref is not protected' do
before do
stub_application_setting(
default_branch_protection: Gitlab::Access::PROTECTION_NONE)
end
it 'returns false' do
- is_expected.to be_falsey
+ is_expected.to be false
end
end
- context 'when the ref is a protected branch' do
+ shared_examples 'ref is protected branch' do
before do
- allow(project).to receive(:repository).and_call_original
- allow(project).to receive_message_chain(:repository, :branch_exists?).and_return(true)
- create(:protected_branch, name: 'ref', project: project)
+ create(:protected_branch, name: 'master', project: project)
end
it 'returns true' do
- is_expected.to be_truthy
+ is_expected.to be true
end
end
- context 'when the ref is a protected tag' do
+ shared_examples 'ref is protected tag' do
before do
- allow(project).to receive_message_chain(:repository, :branch_exists?).and_return(false)
- allow(project).to receive_message_chain(:repository, :tag_exists?).and_return(true)
- create(:protected_tag, name: 'ref', project: project)
+ create(:protected_tag, name: 'v1.0.0', project: project)
end
it 'returns true' do
- is_expected.to be_truthy
+ is_expected.to be true
+ end
+ end
+
+ context 'when ref is nil' do
+ let(:ref) { nil }
+
+ it 'returns false' do
+ is_expected.to be false
+ end
+ end
+
+ context 'when ref is ref name' do
+ context 'when ref is ambiguous' do
+ let(:ref) { 'ref' }
+
+ before do
+ project.repository.add_branch(project.creator, 'ref', 'master')
+ project.repository.add_tag(project.creator, 'ref', 'master')
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Repository::AmbiguousRefError)
+ end
+ end
+
+ context 'when the ref is not protected' do
+ let(:ref) { 'master' }
+
+ it_behaves_like 'ref is not protected'
+ end
+
+ context 'when the ref is a protected branch' do
+ let(:ref) { 'master' }
+
+ it_behaves_like 'ref is protected branch'
+ end
+
+ context 'when the ref is a protected tag' do
+ let(:ref) { 'v1.0.0' }
+
+ it_behaves_like 'ref is protected tag'
+ end
+
+ context 'when ref does not exist' do
+ let(:ref) { 'something' }
+
+ it 'returns false' do
+ is_expected.to be false
+ end
+ end
+ end
+
+ context 'when ref is full ref' do
+ context 'when the ref is not protected' do
+ let(:ref) { 'refs/heads/master' }
+
+ it_behaves_like 'ref is not protected'
+ end
+
+ context 'when the ref is a protected branch' do
+ let(:ref) { 'refs/heads/master' }
+
+ it_behaves_like 'ref is protected branch'
+ end
+
+ context 'when the ref is a protected tag' do
+ let(:ref) { 'refs/tags/v1.0.0' }
+
+ it_behaves_like 'ref is protected tag'
+ end
+
+ context 'when branch ref name is a full tag ref' do
+ let(:ref) { 'refs/tags/something' }
+
+ before do
+ project.repository.add_branch(project.creator, ref, 'master')
+ end
+
+ context 'when ref is not protected' do
+ it 'returns false' do
+ is_expected.to be false
+ end
+ end
+
+ context 'when ref is a protected branch' do
+ before do
+ create(:protected_branch, name: 'refs/tags/something', project: project)
+ end
+
+ it 'returns true' do
+ is_expected.to be true
+ end
+ end
+ end
+
+ context 'when ref does not exist' do
+ let(:ref) { 'refs/heads/something' }
+
+ it 'returns false' do
+ is_expected.to be false
+ end
end
end
end
@@ -2837,7 +2945,7 @@ describe Project do
it 'shows full error updating an invalid MR' do
error_message = 'Failed to replace merge_requests because one or more of the new records could not be saved.'\
- ' Validate fork Source project is not a fork of the target project'
+ ' Validate fork Source project is not a fork of the target project'
expect { project.append_or_update_attribute(:merge_requests, [create(:merge_request)]) }
.to raise_error(ActiveRecord::RecordNotSaved, error_message)
diff --git a/spec/models/remote_mirror_spec.rb b/spec/models/remote_mirror_spec.rb
index 5d3c25062d5..224bc9ed935 100644
--- a/spec/models/remote_mirror_spec.rb
+++ b/spec/models/remote_mirror_spec.rb
@@ -24,6 +24,20 @@ describe RemoteMirror, :mailer do
expect(remote_mirror).to be_invalid
expect(remote_mirror.errors[:url].first).to include('Username needs to start with an alphanumeric character')
end
+
+ it 'does not allow url pointing to localhost' do
+ remote_mirror = build(:remote_mirror, url: 'http://127.0.0.2/t.git')
+
+ expect(remote_mirror).to be_invalid
+ expect(remote_mirror.errors[:url].first).to include('Requests to loopback addresses are not allowed')
+ end
+
+ it 'does not allow url pointing to the local network' do
+ remote_mirror = build(:remote_mirror, url: 'https://192.168.1.1')
+
+ expect(remote_mirror).to be_invalid
+ expect(remote_mirror.errors[:url].first).to include('Requests to the local network are not allowed')
+ end
end
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index f09b4b67061..2063b4bbe75 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -1005,6 +1005,67 @@ describe Repository do
end
end
+ describe '#ambiguous_ref?' do
+ let(:ref) { 'ref' }
+
+ subject { repository.ambiguous_ref?(ref) }
+
+ context 'when ref is ambiguous' do
+ before do
+ repository.add_tag(project.creator, ref, 'master')
+ repository.add_branch(project.creator, ref, 'master')
+ end
+
+ it 'should be true' do
+ is_expected.to eq(true)
+ end
+ end
+
+ context 'when ref is not ambiguous' do
+ before do
+ repository.add_tag(project.creator, ref, 'master')
+ end
+
+ it 'should be false' do
+ is_expected.to eq(false)
+ end
+ end
+ end
+
+ describe '#expand_ref' do
+ let(:ref) { 'ref' }
+
+ subject { repository.expand_ref(ref) }
+
+ context 'when ref is not tag or branch name' do
+ let(:ref) { 'refs/heads/master' }
+
+ it 'returns nil' do
+ is_expected.to eq(nil)
+ end
+ end
+
+ context 'when ref is tag name' do
+ before do
+ repository.add_tag(project.creator, ref, 'master')
+ end
+
+ it 'returns the tag ref' do
+ is_expected.to eq("refs/tags/#{ref}")
+ end
+ end
+
+ context 'when ref is branch name' do
+ before do
+ repository.add_branch(project.creator, ref, 'master')
+ end
+
+ it 'returns the branch ref' do
+ is_expected.to eq("refs/heads/#{ref}")
+ end
+ end
+ end
+
describe '#add_branch' do
let(:branch_name) { 'new_feature' }
let(:target) { 'master' }
diff --git a/spec/models/snippet_spec.rb b/spec/models/snippet_spec.rb
index 7a7272ccb60..664dc3fa145 100644
--- a/spec/models/snippet_spec.rb
+++ b/spec/models/snippet_spec.rb
@@ -423,4 +423,41 @@ describe Snippet do
expect(blob.data).to eq(snippet.content)
end
end
+
+ describe '#embeddable?' do
+ context 'project snippet' do
+ [
+ { project: :public, snippet: :public, embeddable: true },
+ { project: :internal, snippet: :public, embeddable: false },
+ { project: :private, snippet: :public, embeddable: false },
+ { project: :public, snippet: :internal, embeddable: false },
+ { project: :internal, snippet: :internal, embeddable: false },
+ { project: :private, snippet: :internal, embeddable: false },
+ { project: :public, snippet: :private, embeddable: false },
+ { project: :internal, snippet: :private, embeddable: false },
+ { project: :private, snippet: :private, embeddable: false }
+ ].each do |combination|
+ it 'only returns true when both project and snippet are public' do
+ project = create(:project, combination[:project])
+ snippet = create(:project_snippet, combination[:snippet], project: project)
+
+ expect(snippet.embeddable?).to eq(combination[:embeddable])
+ end
+ end
+ end
+
+ context 'personal snippet' do
+ [
+ { snippet: :public, embeddable: true },
+ { snippet: :internal, embeddable: false },
+ { snippet: :private, embeddable: false }
+ ].each do |combination|
+ it 'only returns true when snippet is public' do
+ snippet = create(:personal_snippet, combination[:snippet])
+
+ expect(snippet.embeddable?).to eq(combination[:embeddable])
+ end
+ end
+ end
+ end
end
diff --git a/spec/policies/issuable_policy_spec.rb b/spec/policies/issuable_policy_spec.rb
index d1bf98995e7..db3df760472 100644
--- a/spec/policies/issuable_policy_spec.rb
+++ b/spec/policies/issuable_policy_spec.rb
@@ -7,6 +7,33 @@ describe IssuablePolicy, models: true do
let(:policies) { described_class.new(user, issue) }
describe '#rules' do
+ context 'when user is author of issuable' do
+ let(:merge_request) { create(:merge_request, source_project: project, author: user) }
+ let(:policies) { described_class.new(user, merge_request) }
+
+ context 'when user is able to read project' do
+ it 'enables user to read and update issuables' do
+ expect(policies).to be_allowed(:read_issue, :update_issue, :reopen_issue, :read_merge_request, :update_merge_request)
+ end
+ end
+
+ context 'when project is private' do
+ let(:project) { create(:project, :private) }
+
+ context 'when user belongs to the projects team' do
+ it 'enables user to read and update issuables' do
+ project.add_maintainer(user)
+
+ expect(policies).to be_allowed(:read_issue, :update_issue, :reopen_issue, :read_merge_request, :update_merge_request)
+ end
+ end
+
+ it 'disallows user from reading and updating issuables from that project' do
+ expect(policies).to be_disallowed(:read_issue, :update_issue, :reopen_issue, :read_merge_request, :update_merge_request)
+ end
+ end
+ end
+
context 'when discussion is locked for the issuable' do
let(:issue) { create(:issue, project: project, discussion_locked: true) }
diff --git a/spec/requests/api/internal_spec.rb b/spec/requests/api/internal_spec.rb
index 589816b5d8f..0fe63e2e517 100644
--- a/spec/requests/api/internal_spec.rb
+++ b/spec/requests/api/internal_spec.rb
@@ -809,7 +809,8 @@ describe API::Internal do
gl_repository: gl_repository,
secret_token: secret_token,
identifier: identifier,
- changes: changes
+ changes: changes,
+ push_options: push_options
}
end
@@ -817,6 +818,11 @@ describe API::Internal do
"#{Gitlab::Git::BLANK_SHA} 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/new_branch"
end
+ let(:push_options) do
+ ['ci.skip',
+ 'another push option']
+ end
+
before do
project.add_developer(user)
allow(described_class).to receive(:identify).and_return(user)
@@ -825,7 +831,7 @@ describe API::Internal do
it 'enqueues a PostReceive worker job' do
expect(PostReceive).to receive(:perform_async)
- .with(gl_repository, identifier, changes)
+ .with(gl_repository, identifier, changes, push_options)
post api("/internal/post_receive"), params: valid_params
end
diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb
index 73131dba542..97aa71bf231 100644
--- a/spec/requests/api/jobs_spec.rb
+++ b/spec/requests/api/jobs_spec.rb
@@ -142,10 +142,20 @@ describe API::Jobs do
end
context 'unauthorized user' do
- let(:api_user) { nil }
+ context 'when user is not logged in' do
+ let(:api_user) { nil }
- it 'does not return project jobs' do
- expect(response).to have_gitlab_http_status(401)
+ it 'does not return project jobs' do
+ expect(response).to have_gitlab_http_status(401)
+ end
+ end
+
+ context 'when user is guest' do
+ let(:api_user) { guest }
+
+ it 'does not return project jobs' do
+ expect(response).to have_gitlab_http_status(403)
+ end
end
end
@@ -241,10 +251,20 @@ describe API::Jobs do
end
context 'unauthorized user' do
- let(:api_user) { nil }
+ context 'when user is not logged in' do
+ let(:api_user) { nil }
- it 'does not return jobs' do
- expect(response).to have_gitlab_http_status(401)
+ it 'does not return jobs' do
+ expect(response).to have_gitlab_http_status(401)
+ end
+ end
+
+ context 'when user is guest' do
+ let(:api_user) { guest }
+
+ it 'does not return jobs' do
+ expect(response).to have_gitlab_http_status(403)
+ end
end
end
end
diff --git a/spec/requests/api/runner_spec.rb b/spec/requests/api/runner_spec.rb
index c63621fe7d1..2f322cc7054 100644
--- a/spec/requests/api/runner_spec.rb
+++ b/spec/requests/api/runner_spec.rb
@@ -1320,7 +1320,7 @@ describe API::Runner, :clean_gitlab_redis_shared_state do
end
before do
- fog_connection.directories.get('artifacts').files.create(
+ fog_connection.directories.new(key: 'artifacts').files.create(
key: 'tmp/uploads/12312300',
body: 'content'
)
diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb
index 3cc29a7076d..f1514e90eb2 100644
--- a/spec/requests/lfs_http_spec.rb
+++ b/spec/requests/lfs_http_spec.rb
@@ -1123,7 +1123,7 @@ describe 'Git LFS API and storage' do
context 'with valid remote_id' do
before do
- fog_connection.directories.get('lfs-objects').files.create(
+ fog_connection.directories.new(key: 'lfs-objects').files.create(
key: 'tmp/uploads/12312300',
body: 'content'
)
diff --git a/spec/services/auth/container_registry_authentication_service_spec.rb b/spec/services/auth/container_registry_authentication_service_spec.rb
index f2e9799452a..8021bd338e0 100644
--- a/spec/services/auth/container_registry_authentication_service_spec.rb
+++ b/spec/services/auth/container_registry_authentication_service_spec.rb
@@ -5,7 +5,7 @@ describe Auth::ContainerRegistryAuthenticationService do
let(:current_user) { nil }
let(:current_params) { {} }
let(:rsa_key) { OpenSSL::PKey::RSA.generate(512) }
- let(:payload) { JWT.decode(subject[:token], rsa_key).first }
+ let(:payload) { JWT.decode(subject[:token], rsa_key, true, { algorithm: 'RS256' }).first }
let(:authentication_abilities) do
[:read_container_image, :create_container_image, :admin_container_image]
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index ffa47d527f7..87b60387c52 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -19,12 +19,14 @@ describe Ci::CreatePipelineService do
ref: ref_name,
trigger_request: nil,
variables_attributes: nil,
- merge_request: nil)
+ merge_request: nil,
+ push_options: nil)
params = { ref: ref,
before: '00000000',
after: after,
commits: [{ message: message }],
- variables_attributes: variables_attributes }
+ variables_attributes: variables_attributes,
+ push_options: push_options }
described_class.new(project, user, params).execute(
source, trigger_request: trigger_request, merge_request: merge_request)
@@ -357,6 +359,22 @@ describe Ci::CreatePipelineService do
end
end
+ context 'when push options contain ci.skip' do
+ let(:push_options) do
+ ['ci.skip',
+ 'another push option']
+ end
+
+ it 'creates a pipline in the skipped state' do
+ pipeline = execute_service(push_options: push_options)
+
+ # TODO: DRY these up with "skips builds creation if the commit message"
+ expect(pipeline).to be_persisted
+ expect(pipeline.builds.any?).to be false
+ expect(pipeline.status).to eq("skipped")
+ end
+ end
+
context 'when there are no jobs for this pipeline' do
before do
config = YAML.dump({ test: { script: 'ls', only: ['feature'] } })
@@ -667,7 +685,7 @@ describe Ci::CreatePipelineService do
stub_ci_pipeline_yaml_file(YAML.dump(config))
end
- let(:ref_name) { 'feature' }
+ let(:ref_name) { 'refs/heads/feature' }
context 'when source is merge request' do
let(:source) { :merge_request }
@@ -696,7 +714,7 @@ describe Ci::CreatePipelineService do
let(:merge_request) do
create(:merge_request,
source_project: project,
- source_branch: ref_name,
+ source_branch: Gitlab::Git.ref_name(ref_name),
target_project: project,
target_branch: 'master')
end
@@ -709,7 +727,7 @@ describe Ci::CreatePipelineService do
end
context 'when ref is tag' do
- let(:ref_name) { 'v1.1.0' }
+ let(:ref_name) { 'refs/tags/v1.1.0' }
it 'does not create a merge request pipeline' do
expect(pipeline).not_to be_persisted
@@ -721,7 +739,7 @@ describe Ci::CreatePipelineService do
let(:merge_request) do
create(:merge_request,
source_project: project,
- source_branch: ref_name,
+ source_branch: Gitlab::Git.ref_name(ref_name),
target_project: target_project,
target_branch: 'master')
end
@@ -786,7 +804,7 @@ describe Ci::CreatePipelineService do
let(:merge_request) do
create(:merge_request,
source_project: project,
- source_branch: ref_name,
+ source_branch: Gitlab::Git.ref_name(ref_name),
target_project: project,
target_branch: 'master')
end
@@ -928,7 +946,7 @@ describe Ci::CreatePipelineService do
let(:merge_request) do
create(:merge_request,
source_project: project,
- source_branch: ref_name,
+ source_branch: Gitlab::Git.ref_name(ref_name),
target_project: project,
target_branch: 'master')
end
diff --git a/spec/services/groups/update_service_spec.rb b/spec/services/groups/update_service_spec.rb
index 84cfa53ea05..d87a7dd234d 100644
--- a/spec/services/groups/update_service_spec.rb
+++ b/spec/services/groups/update_service_spec.rb
@@ -56,7 +56,7 @@ describe Groups::UpdateService do
create(:project, :private, group: internal_group)
expect(TodosDestroyer::GroupPrivateWorker).to receive(:perform_in)
- .with(1.hour, internal_group.id)
+ .with(Todo::WAIT_FOR_DELETE, internal_group.id)
end
it "changes permission level to private" do
diff --git a/spec/services/issuable/bulk_update_service_spec.rb b/spec/services/issuable/bulk_update_service_spec.rb
index f0b0f7956ce..ca366cdf1df 100644
--- a/spec/services/issuable/bulk_update_service_spec.rb
+++ b/spec/services/issuable/bulk_update_service_spec.rb
@@ -28,6 +28,33 @@ describe Issuable::BulkUpdateService do
expect(project.issues.opened).to be_empty
expect(project.issues.closed).not_to be_empty
end
+
+ context 'when issue for a different project is created' do
+ let(:private_project) { create(:project, :private) }
+ let(:issue) { create(:issue, project: private_project, author: user) }
+
+ context 'when user has access to the project' do
+ it 'closes all issues passed' do
+ private_project.add_maintainer(user)
+
+ bulk_update(issues + [issue], state_event: 'close')
+
+ expect(project.issues.opened).to be_empty
+ expect(project.issues.closed).not_to be_empty
+ expect(private_project.issues.closed).not_to be_empty
+ end
+ end
+
+ context 'when user does not have access to project' do
+ it 'only closes all issues that the user has access to' do
+ bulk_update(issues + [issue], state_event: 'close')
+
+ expect(project.issues.opened).to be_empty
+ expect(project.issues.closed).not_to be_empty
+ expect(private_project.issues.closed).to be_empty
+ end
+ end
+ end
end
describe 'reopen issues' do
diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb
index bd519e7f077..ce20bf2bef6 100644
--- a/spec/services/issues/update_service_spec.rb
+++ b/spec/services/issues/update_service_spec.rb
@@ -77,7 +77,7 @@ describe Issues::UpdateService, :mailer do
end
it 'enqueues ConfidentialIssueWorker when an issue is made confidential' do
- expect(TodosDestroyer::ConfidentialIssueWorker).to receive(:perform_in).with(1.hour, issue.id)
+ expect(TodosDestroyer::ConfidentialIssueWorker).to receive(:perform_in).with(Todo::WAIT_FOR_DELETE, issue.id)
update_issue(confidential: true)
end
diff --git a/spec/services/members/destroy_service_spec.rb b/spec/services/members/destroy_service_spec.rb
index 0a5220c7c61..5aa7165e135 100644
--- a/spec/services/members/destroy_service_spec.rb
+++ b/spec/services/members/destroy_service_spec.rb
@@ -22,7 +22,7 @@ describe Members::DestroyService do
shared_examples 'a service destroying a member' do
before do
type = member.is_a?(GroupMember) ? 'Group' : 'Project'
- expect(TodosDestroyer::EntityLeaveWorker).to receive(:perform_in).with(1.hour, member.user_id, member.source_id, type)
+ expect(TodosDestroyer::EntityLeaveWorker).to receive(:perform_in).with(Todo::WAIT_FOR_DELETE, member.user_id, member.source_id, type)
end
it 'destroys the member' do
diff --git a/spec/services/members/update_service_spec.rb b/spec/services/members/update_service_spec.rb
index 6d19a95ffeb..599ed39ca37 100644
--- a/spec/services/members/update_service_spec.rb
+++ b/spec/services/members/update_service_spec.rb
@@ -20,11 +20,28 @@ describe Members::UpdateService do
shared_examples 'a service updating a member' do
it 'updates the member' do
+ expect(TodosDestroyer::EntityLeaveWorker).not_to receive(:perform_in).with(Todo::WAIT_FOR_DELETE, member.user_id, member.source_id, source.class.name)
+
updated_member = described_class.new(current_user, params).execute(member, permission: permission)
expect(updated_member).to be_valid
expect(updated_member.access_level).to eq(Gitlab::Access::MAINTAINER)
end
+
+ context 'when member is downgraded to guest' do
+ let(:params) do
+ { access_level: Gitlab::Access::GUEST }
+ end
+
+ it 'schedules to delete confidential todos' do
+ expect(TodosDestroyer::EntityLeaveWorker).to receive(:perform_in).with(Todo::WAIT_FOR_DELETE, member.user_id, member.source_id, source.class.name).once
+
+ updated_member = described_class.new(current_user, params).execute(member, permission: permission)
+
+ expect(updated_member).to be_valid
+ expect(updated_member.access_level).to eq(Gitlab::Access::GUEST)
+ end
+ end
end
before do
diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb
index 1894d8c8d0e..536d0d345a4 100644
--- a/spec/services/merge_requests/build_service_spec.rb
+++ b/spec/services/merge_requests/build_service_spec.rb
@@ -3,6 +3,7 @@ require 'spec_helper'
describe MergeRequests::BuildService do
using RSpec::Parameterized::TableSyntax
include RepoHelpers
+ include ProjectForksHelper
let(:project) { create(:project, :repository) }
let(:source_project) { nil }
@@ -49,7 +50,7 @@ describe MergeRequests::BuildService do
describe '#execute' do
it 'calls the compare service with the correct arguments' do
- allow_any_instance_of(described_class).to receive(:branches_valid?).and_return(true)
+ allow_any_instance_of(described_class).to receive(:projects_and_branches_valid?).and_return(true)
expect(CompareService).to receive(:new)
.with(project, Gitlab::Git::BRANCH_REF_PREFIX + source_branch)
.and_call_original
@@ -393,11 +394,27 @@ describe MergeRequests::BuildService do
end
end
+ context 'target_project is set but repo is not accessible by current_user' do
+ let(:target_project) do
+ create(:project, :public, :repository, repository_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'sets target project correctly' do
+ expect(merge_request.target_project).to eq(project)
+ end
+ end
+
context 'source_project is set and accessible by current_user' do
let(:source_project) { create(:project, :public, :repository)}
let(:commits) { Commit.decorate([commit_1], project) }
- it 'sets target project correctly' do
+ before do
+ # To create merge requests _from_ a project the user needs at least
+ # developer access
+ source_project.add_developer(user)
+ end
+
+ it 'sets source project correctly' do
expect(merge_request.source_project).to eq(source_project)
end
end
@@ -406,11 +423,43 @@ describe MergeRequests::BuildService do
let(:source_project) { create(:project, :private, :repository)}
let(:commits) { Commit.decorate([commit_1], project) }
- it 'sets target project correctly' do
+ it 'sets source project correctly' do
+ expect(merge_request.source_project).to eq(project)
+ end
+ end
+
+ context 'source_project is set but the user cannot create merge requests from the project' do
+ let(:source_project) do
+ create(:project, :public, :repository, merge_requests_access_level: ProjectFeature::PRIVATE)
+ end
+
+ it 'sets the source_project correctly' do
expect(merge_request.source_project).to eq(project)
end
end
+ context 'target_project is not in the fork network of source_project' do
+ let(:target_project) { create(:project, :public, :repository) }
+
+ it 'adds an error to the merge request' do
+ expect(merge_request.errors[:validate_fork]).to contain_exactly('Source project is not a fork of the target project')
+ end
+ end
+
+ context 'target_project is in the fork network of source project but no longer accessible' do
+ let!(:project) { fork_project(target_project, user, namespace: user.namespace, repository: true) }
+ let(:source_project) { project }
+ let(:target_project) { create(:project, :public, :repository) }
+
+ before do
+ target_project.update(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
+ end
+
+ it 'sets the target_project correctly' do
+ expect(merge_request.target_project).to eq(project)
+ end
+ end
+
context 'when specifying target branch in the description' do
let(:description) { "A merge request targeting another branch\n\n/target_branch with-codeowners" }
diff --git a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
index d7d7f1874eb..95c9b6e63b8 100644
--- a/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
+++ b/spec/services/projects/lfs_pointers/lfs_download_service_spec.rb
@@ -4,17 +4,15 @@ describe Projects::LfsPointers::LfsDownloadService do
let(:project) { create(:project) }
let(:oid) { '9e548e25631dd9ce6b43afd6359ab76da2819d6a5b474e66118c7819e1d8b3e8' }
let(:download_link) { "http://gitlab.com/#{oid}" }
- let(:lfs_content) do
- <<~HEREDOC
- whatever
- HEREDOC
- end
+ let(:lfs_content) { SecureRandom.random_bytes(10) }
subject { described_class.new(project) }
before do
allow(project).to receive(:lfs_enabled?).and_return(true)
WebMock.stub_request(:get, download_link).to_return(body: lfs_content)
+
+ allow(Gitlab::CurrentSettings).to receive(:allow_local_requests_from_hooks_and_services?).and_return(false)
end
describe '#execute' do
@@ -32,7 +30,7 @@ describe Projects::LfsPointers::LfsDownloadService do
it 'stores the content' do
subject.execute(oid, download_link)
- expect(File.read(LfsObject.first.file.file.file)).to eq lfs_content
+ expect(File.binread(LfsObject.first.file.file.file)).to eq lfs_content
end
end
@@ -54,18 +52,61 @@ describe Projects::LfsPointers::LfsDownloadService do
end
end
+ context 'when localhost requests are allowed' do
+ let(:download_link) { 'http://192.168.2.120' }
+
+ before do
+ allow(Gitlab::CurrentSettings).to receive(:allow_local_requests_from_hooks_and_services?).and_return(true)
+ end
+
+ it 'downloads the file' do
+ expect(subject).to receive(:download_and_save_file).and_call_original
+
+ expect { subject.execute(oid, download_link) }.to change { LfsObject.count }.by(1)
+ end
+ end
+
context 'when a bad URL is used' do
- where(download_link: ['/etc/passwd', 'ftp://example.com', 'http://127.0.0.2'])
+ where(download_link: ['/etc/passwd', 'ftp://example.com', 'http://127.0.0.2', 'http://192.168.2.120'])
with_them do
it 'does not download the file' do
- expect(subject).not_to receive(:download_and_save_file)
-
expect { subject.execute(oid, download_link) }.not_to change { LfsObject.count }
end
end
end
+ context 'when the URL points to a redirected URL' do
+ context 'that is blocked' do
+ where(redirect_link: ['ftp://example.com', 'http://127.0.0.2', 'http://192.168.2.120'])
+
+ with_them do
+ before do
+ WebMock.stub_request(:get, download_link).to_return(status: 301, headers: { 'Location' => redirect_link })
+ end
+
+ it 'does not follow the redirection' do
+ expect(Rails.logger).to receive(:error).with(/LFS file with oid #{oid} couldn't be downloaded/)
+
+ expect { subject.execute(oid, download_link) }.not_to change { LfsObject.count }
+ end
+ end
+ end
+
+ context 'that is valid' do
+ let(:redirect_link) { "http://example.com/"}
+
+ before do
+ WebMock.stub_request(:get, download_link).to_return(status: 301, headers: { 'Location' => redirect_link })
+ WebMock.stub_request(:get, redirect_link).to_return(body: lfs_content)
+ end
+
+ it 'follows the redirection' do
+ expect { subject.execute(oid, download_link) }.to change { LfsObject.count }.from(0).to(1)
+ end
+ end
+ end
+
context 'when an lfs object with the same oid already exists' do
before do
create(:lfs_object, oid: 'oid')
diff --git a/spec/services/projects/update_service_spec.rb b/spec/services/projects/update_service_spec.rb
index d58ff2cedc0..8adfc63222e 100644
--- a/spec/services/projects/update_service_spec.rb
+++ b/spec/services/projects/update_service_spec.rb
@@ -41,7 +41,7 @@ describe Projects::UpdateService do
end
it 'updates the project to private' do
- expect(TodosDestroyer::ProjectPrivateWorker).to receive(:perform_in).with(1.hour, project.id)
+ expect(TodosDestroyer::ProjectPrivateWorker).to receive(:perform_in).with(Todo::WAIT_FOR_DELETE, project.id)
result = update_project(project, user, visibility_level: Gitlab::VisibilityLevel::PRIVATE)
@@ -191,7 +191,7 @@ describe Projects::UpdateService do
context 'when changing feature visibility to private' do
it 'updates the visibility correctly' do
expect(TodosDestroyer::PrivateFeaturesWorker)
- .to receive(:perform_in).with(1.hour, project.id)
+ .to receive(:perform_in).with(Todo::WAIT_FOR_DELETE, project.id)
result = update_project(project, user, project_feature_attributes:
{ issues_access_level: ProjectFeature::PRIVATE }
diff --git a/spec/services/todo_service_spec.rb b/spec/services/todo_service_spec.rb
index c52515aefd8..253f2e44d10 100644
--- a/spec/services/todo_service_spec.rb
+++ b/spec/services/todo_service_spec.rb
@@ -19,6 +19,7 @@ describe TodoService do
before do
project.add_guest(guest)
project.add_developer(author)
+ project.add_developer(assignee)
project.add_developer(member)
project.add_developer(john_doe)
project.add_developer(skipped)
diff --git a/spec/support/gitlab_stubs/gitlab_ci.yml b/spec/support/gitlab_stubs/gitlab_ci.yml
index e55a61b2b94..f3755e52b2c 100644
--- a/spec/support/gitlab_stubs/gitlab_ci.yml
+++ b/spec/support/gitlab_stubs/gitlab_ci.yml
@@ -1,9 +1,8 @@
-image: ruby:2.1
+image: ruby:2.6
services:
- postgres
before_script:
- - gem install bundler
- bundle install
- bundle exec rake db:create
diff --git a/spec/uploaders/file_uploader_spec.rb b/spec/uploaders/file_uploader_spec.rb
index c74e0bf1955..db9e5eb2ad6 100644
--- a/spec/uploaders/file_uploader_spec.rb
+++ b/spec/uploaders/file_uploader_spec.rb
@@ -201,7 +201,7 @@ describe FileUploader do
end
let!(:fog_file) do
- fog_connection.directories.get('uploads').files.create(
+ fog_connection.directories.new(key: 'uploads').files.create(
key: 'tmp/uploads/test/123123',
body: 'content'
)
diff --git a/spec/uploaders/object_storage_spec.rb b/spec/uploaders/object_storage_spec.rb
index 7e673681c31..533e9d87ea6 100644
--- a/spec/uploaders/object_storage_spec.rb
+++ b/spec/uploaders/object_storage_spec.rb
@@ -716,7 +716,7 @@ describe ObjectStorage do
end
let!(:fog_file) do
- fog_connection.directories.get('uploads').files.create(
+ fog_connection.directories.new(key: 'uploads').files.create(
key: 'tmp/uploads/test/123123',
body: 'content'
)
diff --git a/spec/workers/mail_scheduler/notification_service_worker_spec.rb b/spec/workers/mail_scheduler/notification_service_worker_spec.rb
index f725c8763a0..1033557ee88 100644
--- a/spec/workers/mail_scheduler/notification_service_worker_spec.rb
+++ b/spec/workers/mail_scheduler/notification_service_worker_spec.rb
@@ -17,10 +17,21 @@ describe MailScheduler::NotificationServiceWorker do
end
context 'when the arguments cannot be deserialized' do
- it 'does nothing' do
- expect(worker.notification_service).not_to receive(method)
+ context 'when the arguments are not deserializeable' do
+ it 'raises exception' do
+ expect(worker.notification_service).not_to receive(method)
+ expect { worker.perform(method, key.to_global_id.to_s.succ) }.to raise_exception(ArgumentError)
+ end
+ end
+
+ context 'when the arguments are deserializeable' do
+ it 'does nothing' do
+ serialized_arguments = *serialize(key)
+ key.destroy!
- worker.perform(method, key.to_global_id.to_s.succ)
+ expect(worker.notification_service).not_to receive(method)
+ expect { worker.perform(method, serialized_arguments) }.not_to raise_exception
+ end
end
end