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:
authorMayra Cabrera <mcabrera@gitlab.com>2018-04-23 22:38:32 +0300
committerMayra Cabrera <mcabrera@gitlab.com>2018-04-23 22:38:32 +0300
commit3569294e642dfa136f7d0c28333d1017d4091f52 (patch)
treee3373673f5d1d13c8f4aa74a52cd58cde30fde97
parent342f33beb2ce090cfabfd0a5e7327b78d04588bb (diff)
parente9b8fb43ca917cf79f4016d8fcd3d2f1732afc63 (diff)
Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce
-rw-r--r--.gitlab-ci.yml2
-rw-r--r--.rubocop_todo.yml8
-rw-r--r--CONTRIBUTING.md8
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--Gemfile.lock2
-rw-r--r--app/assets/javascripts/create_merge_request_dropdown.js33
-rw-r--r--app/assets/javascripts/pipelines/components/graph/action_component.vue25
-rw-r--r--app/assets/javascripts/pipelines/components/graph/dropdown_action_component.vue53
-rw-r--r--app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue128
-rw-r--r--app/assets/javascripts/pipelines/components/graph/graph_component.vue7
-rw-r--r--app/assets/javascripts/pipelines/components/graph/job_component.vue28
-rw-r--r--app/assets/javascripts/pipelines/components/graph/stage_column_component.vue7
-rw-r--r--app/assets/javascripts/pipelines/pipeline_details_bundle.js17
-rw-r--r--app/assets/javascripts/vue_shared/components/ci_badge_link.vue88
-rw-r--r--app/assets/javascripts/vue_shared/components/ci_icon.vue75
-rw-r--r--app/assets/javascripts/vue_shared/components/clipboard_button.vue76
-rw-r--r--app/assets/javascripts/vue_shared/components/commit.vue215
-rw-r--r--app/assets/javascripts/vue_shared/components/expand_button.vue54
-rw-r--r--app/assets/javascripts/vue_shared/components/header_ci_component.vue132
-rw-r--r--app/assets/javascripts/vue_shared/components/icon.vue118
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue14
-rw-r--r--app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue6
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss8
-rw-r--r--app/controllers/projects/issues_controller.rb6
-rw-r--r--app/controllers/projects/jobs_controller.rb2
-rw-r--r--app/finders/users_finder.rb12
-rw-r--r--app/models/concerns/atomic_internal_id.rb5
-rw-r--r--app/models/concerns/avatarable.rb5
-rw-r--r--app/models/concerns/nonatomic_internal_id.rb22
-rw-r--r--app/models/concerns/routable.rb7
-rw-r--r--app/models/concerns/uniquify.rb22
-rw-r--r--app/models/deployment.rb4
-rw-r--r--app/models/group.rb4
-rw-r--r--app/models/internal_id.rb3
-rw-r--r--app/models/issue.rb16
-rw-r--r--app/models/merge_request.rb4
-rw-r--r--app/models/milestone.rb5
-rw-r--r--app/models/project_services/flowdock_service.rb48
-rw-r--r--app/presenters/project_presenter.rb2
-rw-r--r--app/uploaders/gitlab_uploader.rb4
-rw-r--r--app/views/admin/application_settings/_repository_storage.html.haml2
-rw-r--r--app/views/projects/empty.html.haml2
-rw-r--r--app/views/projects/jobs/index.html.haml2
-rw-r--r--app/views/projects/pipelines/_with_tabs.html.haml2
-rw-r--r--app/views/projects/settings/ci_cd/_autodevops_form.html.haml40
-rw-r--r--app/views/projects/settings/ci_cd/_form.html.haml38
-rw-r--r--app/views/projects/settings/ci_cd/show.html.haml14
-rw-r--r--app/views/shared/_auto_devops_callout.html.haml2
-rw-r--r--changelogs/unreleased/33697-remove-ujs-action-big-graph.yml5
-rw-r--r--changelogs/unreleased/39345-get-raw-archive.yml5
-rw-r--r--changelogs/unreleased/42803-show-new-branch-mr-button.yml5
-rw-r--r--changelogs/unreleased/42936-improve-ns-factory-avoid-duplicates.yml6
-rw-r--r--changelogs/unreleased/43466-make-auto-devops-settings-first-class.yml5
-rw-r--r--changelogs/unreleased/44775-avatar-on-os-fails-with-cdn.yml5
-rw-r--r--changelogs/unreleased/45576-fix-create-project-for-user-endpoint.yml5
-rw-r--r--changelogs/unreleased/45625-job-log-shows-no-job-log.yml5
-rw-r--r--changelogs/unreleased/45666-project-ci-lint-links.yml5
-rw-r--r--changelogs/unreleased/ab-44259-atomic-internal-ids-for-all-models.yml5
-rw-r--r--changelogs/unreleased/blackst0ne-add-missing-changelog-type-to-docs.yml5
-rw-r--r--changelogs/unreleased/dz-add-2fa-filter-admin-api.yml5
-rw-r--r--changelogs/unreleased/rd-44635-error-500-when-clicking-ghost-user-or-gitlab-support-bot-in-ui.yml5
-rw-r--r--changelogs/unreleased/rd-45502-uploading-project-export-with-lfs-file-locks-fails.yml5
-rw-r--r--changelogs/unreleased/update-doorkeeper-changelog.yml5
-rw-r--r--config/initializers/1_settings.rb129
-rw-r--r--config/initializers/2_app.rb8
-rw-r--r--db/fixtures/development/17_cycle_analytics.rb2
-rw-r--r--db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb66
-rw-r--r--db/migrate/20180416155103_add_further_scope_columns_to_internal_id_table.rb15
-rw-r--r--db/migrate/20180417090132_add_index_constraints_to_internal_id_table.rb40
-rw-r--r--db/schema.rb7
-rw-r--r--doc/administration/high_availability/redis.md41
-rw-r--r--doc/administration/pages/index.md36
-rw-r--r--doc/api/project_import_export.md8
-rw-r--r--doc/api/projects.md25
-rw-r--r--doc/api/users.md1
-rw-r--r--doc/development/changelog.md2
-rw-r--r--doc/development/testing_guide/best_practices.md36
-rw-r--r--doc/development/testing_guide/testing_rake_tasks.md2
-rw-r--r--doc/user/project/deploy_tokens/index.md2
-rw-r--r--features/support/env.rb6
-rw-r--r--lib/api/api.rb1
-rw-r--r--lib/api/helpers/notes_helpers.rb4
-rw-r--r--lib/api/helpers/project_snapshots_helpers.rb25
-rw-r--r--lib/api/project_snapshots.rb19
-rw-r--r--lib/api/projects.rb10
-rw-r--r--lib/api/users.rb2
-rw-r--r--lib/gitlab.rb13
-rw-r--r--lib/gitlab/git.rb2
-rw-r--r--lib/gitlab/git/committer_with_hooks.rb (renamed from lib/gitlab/wiki/committer_with_hooks.rb)10
-rw-r--r--lib/gitlab/git/repository.rb4
-rw-r--r--lib/gitlab/git/wiki.rb2
-rw-r--r--lib/gitlab/gitaly_client/repository_service.rb16
-rw-r--r--lib/gitlab/import_export/import_export.yml2
-rw-r--r--lib/gitlab/workhorse.rb14
-rw-r--r--lib/settings.rb126
-rw-r--r--locale/gitlab.pot3
-rw-r--r--rubocop/spec_helpers.rb2
-rw-r--r--spec/controllers/import/bitbucket_controller_spec.rb5
-rw-r--r--spec/controllers/import/gitlab_controller_spec.rb5
-rw-r--r--spec/controllers/projects/forks_controller_spec.rb6
-rw-r--r--spec/controllers/projects/jobs_controller_spec.rb5
-rw-r--r--spec/factories/commits.rb2
-rw-r--r--spec/factories/gpg_key_subkeys.rb2
-rw-r--r--spec/factories/gpg_keys.rb2
-rw-r--r--spec/factories/gpg_signature.rb2
-rw-r--r--spec/factories/groups.rb8
-rw-r--r--spec/factories/namespaces.rb18
-rw-r--r--spec/factories/notes.rb2
-rw-r--r--spec/factories/projects.rb2
-rw-r--r--spec/fast_spec_helper.rb15
-rw-r--r--spec/features/projects/jobs/user_browses_jobs_spec.rb2
-rw-r--r--spec/features/projects/new_project_spec.rb4
-rw-r--r--spec/features/projects/settings/pipelines_settings_spec.rb30
-rw-r--r--spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb8
-rw-r--r--spec/javascripts/issue_spec.js1
-rw-r--r--spec/javascripts/pipelines/graph/action_component_spec.js47
-rw-r--r--spec/javascripts/pipelines/graph/dropdown_action_component_spec.js32
-rw-r--r--spec/javascripts/pipelines/graph/job_component_spec.js11
-rw-r--r--spec/javascripts/settings_panels_spec.js4
-rw-r--r--spec/javascripts/vue_shared/components/ci_icon_spec.js149
-rw-r--r--spec/javascripts/vue_shared/components/clipboard_button_spec.js2
-rw-r--r--spec/javascripts/vue_shared/components/commit_spec.js7
-rw-r--r--spec/javascripts/vue_shared/components/expand_button_spec.js4
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/base_spec.js16
-rw-r--r--spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js10
-rw-r--r--spec/lib/gitlab/bitbucket_import/project_creator_spec.rb2
-rw-r--r--spec/lib/gitlab/git/committer_with_hooks_spec.rb (renamed from spec/lib/gitlab/wiki/committer_with_hooks_spec.rb)2
-rw-r--r--spec/lib/gitlab/gitaly_client/repository_service_spec.rb11
-rw-r--r--spec/lib/gitlab/gitlab_import/project_creator_spec.rb2
-rw-r--r--spec/lib/gitlab/google_code_import/project_creator_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml6
-rw-r--r--spec/lib/gitlab/legacy_github_import/project_creator_spec.rb2
-rw-r--r--spec/lib/gitlab/workhorse_spec.rb22
-rw-r--r--spec/lib/gitlab_spec.rb10
-rw-r--r--spec/migrations/create_missing_namespace_for_internal_users_spec.rb42
-rw-r--r--spec/models/concerns/avatarable_spec.rb16
-rw-r--r--spec/models/concerns/uniquify_spec.rb9
-rw-r--r--spec/models/deployment_spec.rb9
-rw-r--r--spec/models/issue_spec.rb63
-rw-r--r--spec/models/merge_request_spec.rb8
-rw-r--r--spec/models/milestone_spec.rb20
-rw-r--r--spec/models/project_spec.rb2
-rw-r--r--spec/models/user_spec.rb8
-rw-r--r--spec/presenters/project_presenter_spec.rb2
-rw-r--r--spec/requests/api/project_snapshots_spec.rb51
-rw-r--r--spec/requests/api/projects_spec.rb3
-rw-r--r--spec/requests/api/users_spec.rb12
-rw-r--r--spec/services/groups/nested_create_service_spec.rb7
-rw-r--r--spec/spec_helper.rb59
-rw-r--r--spec/support/capybara.rb2
-rw-r--r--spec/support/controllers/githubish_import_controller_shared_examples.rb9
-rw-r--r--spec/support/factory_bot.rb3
-rwxr-xr-xspec/support/generate-seed-repo-rb2
-rw-r--r--spec/support/gitlab-git-test.git/README.md2
-rw-r--r--spec/support/helpers/api_helpers.rb (renamed from spec/support/api_helpers.rb)0
-rw-r--r--spec/support/helpers/bare_repo_operations.rb (renamed from spec/support/bare_repo_operations.rb)0
-rw-r--r--spec/support/helpers/board_helpers.rb (renamed from spec/support/board_helpers.rb)0
-rw-r--r--spec/support/helpers/capybara_helpers.rb (renamed from spec/support/capybara_helpers.rb)4
-rw-r--r--spec/support/helpers/cookie_helper.rb (renamed from spec/support/cookie_helper.rb)0
-rw-r--r--spec/support/helpers/cycle_analytics_helpers.rb (renamed from spec/support/cycle_analytics_helpers.rb)4
-rw-r--r--spec/support/helpers/database_connection_helpers.rb (renamed from spec/support/database_connection_helpers.rb)0
-rw-r--r--spec/support/helpers/devise_helpers.rb (renamed from spec/support/devise_helpers.rb)0
-rw-r--r--spec/support/helpers/drag_to_helper.rb (renamed from spec/support/drag_to_helper.rb)0
-rw-r--r--spec/support/helpers/dropzone_helper.rb (renamed from spec/support/dropzone_helper.rb)0
-rw-r--r--spec/support/helpers/email_helpers.rb (renamed from spec/support/email_helpers.rb)0
-rw-r--r--spec/support/helpers/fake_migration_classes.rb (renamed from spec/support/fake_migration_classes.rb)0
-rw-r--r--spec/support/helpers/fake_u2f_device.rb (renamed from spec/support/fake_u2f_device.rb)0
-rw-r--r--spec/support/helpers/filter_item_select_helper.rb (renamed from spec/support/filter_item_select_helper.rb)0
-rw-r--r--spec/support/helpers/filter_spec_helper.rb (renamed from spec/support/filter_spec_helper.rb)0
-rw-r--r--spec/support/helpers/filtered_search_helpers.rb (renamed from spec/support/filtered_search_helpers.rb)0
-rw-r--r--spec/support/helpers/fixture_helpers.rb (renamed from spec/support/fixture_helpers.rb)4
-rw-r--r--spec/support/helpers/git_http_helpers.rb (renamed from spec/support/git_http_helpers.rb)0
-rw-r--r--spec/support/helpers/gitlab_verify_helpers.rb25
-rw-r--r--spec/support/helpers/gpg_helpers.rb (renamed from spec/support/gpg_helpers.rb)0
-rw-r--r--spec/support/helpers/import_spec_helper.rb (renamed from spec/support/import_spec_helper.rb)0
-rw-r--r--spec/support/helpers/input_helper.rb (renamed from spec/support/input_helper.rb)0
-rw-r--r--spec/support/helpers/inspect_requests.rb (renamed from spec/support/inspect_requests.rb)0
-rw-r--r--spec/support/helpers/issue_helpers.rb (renamed from spec/support/issue_helpers.rb)0
-rw-r--r--spec/support/helpers/javascript_fixtures_helpers.rb (renamed from spec/support/javascript_fixtures_helpers.rb)0
-rw-r--r--spec/support/helpers/jira_service_helper.rb (renamed from spec/support/jira_service_helper.rb)0
-rw-r--r--spec/support/helpers/kubernetes_helpers.rb (renamed from spec/support/kubernetes_helpers.rb)0
-rw-r--r--spec/support/helpers/ldap_helpers.rb (renamed from spec/support/ldap_helpers.rb)0
-rw-r--r--spec/support/helpers/live_debugger.rb (renamed from spec/support/live_debugger.rb)0
-rw-r--r--spec/support/helpers/login_helpers.rb (renamed from spec/support/login_helpers.rb)0
-rw-r--r--spec/support/helpers/markdown_feature.rb (renamed from spec/support/markdown_feature.rb)0
-rw-r--r--spec/support/helpers/merge_request_helpers.rb (renamed from spec/support/merge_request_helpers.rb)0
-rw-r--r--spec/support/helpers/migrations_helpers.rb (renamed from spec/support/migrations_helpers.rb)0
-rw-r--r--spec/support/helpers/mobile_helpers.rb (renamed from spec/support/mobile_helpers.rb)0
-rw-r--r--spec/support/helpers/project_forks_helper.rb (renamed from spec/support/project_forks_helper.rb)0
-rw-r--r--spec/support/helpers/prometheus_helpers.rb (renamed from spec/support/prometheus_helpers.rb)0
-rw-r--r--spec/support/helpers/query_recorder.rb38
-rw-r--r--spec/support/helpers/quick_actions_helpers.rb10
-rw-r--r--spec/support/helpers/rake_helpers.rb (renamed from spec/support/rake_helpers.rb)0
-rw-r--r--spec/support/helpers/reactive_caching_helpers.rb (renamed from spec/support/reactive_caching_helpers.rb)0
-rw-r--r--spec/support/helpers/redis_without_keys.rb (renamed from spec/support/redis_without_keys.rb)0
-rw-r--r--spec/support/helpers/reference_parser_helpers.rb (renamed from spec/support/reference_parser_helpers.rb)0
-rw-r--r--spec/support/helpers/repo_helpers.rb (renamed from spec/support/repo_helpers.rb)0
-rw-r--r--spec/support/helpers/search_helpers.rb (renamed from spec/support/search_helpers.rb)0
-rw-r--r--spec/support/helpers/seed_helper.rb (renamed from spec/support/seed_helper.rb)10
-rw-r--r--spec/support/helpers/seed_repo.rb (renamed from spec/support/seed_repo.rb)0
-rw-r--r--spec/support/helpers/select2_helper.rb (renamed from spec/support/select2_helper.rb)0
-rw-r--r--spec/support/helpers/selection_helper.rb (renamed from spec/support/selection_helper.rb)0
-rw-r--r--spec/support/helpers/sorting_helper.rb18
-rw-r--r--spec/support/helpers/stub_configuration.rb (renamed from spec/support/stub_configuration.rb)3
-rw-r--r--spec/support/helpers/stub_env.rb (renamed from spec/support/stub_env.rb)0
-rw-r--r--spec/support/helpers/stub_feature_flags.rb (renamed from spec/support/stub_feature_flags.rb)0
-rw-r--r--spec/support/helpers/stub_gitlab_calls.rb (renamed from spec/support/stub_gitlab_calls.rb)0
-rw-r--r--spec/support/helpers/stub_gitlab_data.rb (renamed from spec/support/stub_gitlab_data.rb)0
-rw-r--r--spec/support/helpers/stub_object_storage.rb (renamed from spec/support/stub_object_storage.rb)2
-rw-r--r--spec/support/helpers/test_env.rb (renamed from spec/support/test_env.rb)0
-rw-r--r--spec/support/helpers/upload_helpers.rb (renamed from spec/support/upload_helpers.rb)0
-rw-r--r--spec/support/helpers/user_activities_helpers.rb (renamed from spec/support/user_activities_helpers.rb)0
-rw-r--r--spec/support/helpers/wait_for_requests.rb (renamed from spec/support/wait_for_requests.rb)0
-rw-r--r--spec/support/helpers/workhorse_helpers.rb (renamed from spec/support/workhorse_helpers.rb)0
-rw-r--r--spec/support/json_response.rb (renamed from spec/support/json_response_helpers.rb)4
-rw-r--r--spec/support/matchers/background_migrations_matchers.rb (renamed from spec/support/background_migrations_matchers.rb)0
-rw-r--r--spec/support/matchers/exceed_query_limit.rb (renamed from spec/support/query_recorder.rb)39
-rwxr-xr-xspec/support/prepare-gitlab-git-test-for-commit2
-rw-r--r--spec/support/routing_helpers.rb3
-rw-r--r--spec/support/rspec.rb12
-rw-r--r--spec/support/seed.rb7
-rw-r--r--spec/support/shared_contexts/json_response_shared_context.rb3
-rw-r--r--spec/support/shared_contexts/services_shared_context.rb (renamed from spec/support/services_shared_context.rb)0
-rw-r--r--spec/support/shared_examples/chat_slash_commands_shared_examples.rb (renamed from spec/support/chat_slash_commands_shared_examples.rb)0
-rw-r--r--spec/support/shared_examples/email_format_shared_examples.rb (renamed from spec/support/email_format_shared_examples.rb)0
-rw-r--r--spec/support/shared_examples/gitlab_verify.rb (renamed from spec/support/gitlab_verify.rb)26
-rw-r--r--spec/support/shared_examples/group_members_shared_example.rb (renamed from spec/support/group_members_shared_example.rb)0
-rw-r--r--spec/support/shared_examples/issuable_shared_examples.rb (renamed from spec/support/issuable_shared_examples.rb)0
-rw-r--r--spec/support/shared_examples/issuables_list_metadata_shared_examples.rb (renamed from spec/support/issuables_list_metadata_shared_examples.rb)0
-rw-r--r--spec/support/shared_examples/issue_tracker_service_shared_example.rb (renamed from spec/support/issue_tracker_service_shared_example.rb)0
-rw-r--r--spec/support/shared_examples/ldap_shared_examples.rb (renamed from spec/support/ldap_shared_examples.rb)0
-rw-r--r--spec/support/shared_examples/legacy_path_redirect_shared_examples.rb (renamed from spec/support/legacy_path_redirect_shared_examples.rb)0
-rw-r--r--spec/support/shared_examples/malicious_regexp_shared_examples.rb (renamed from spec/support/malicious_regexp_shared_examples.rb)0
-rw-r--r--spec/support/shared_examples/mentionable_shared_examples.rb (renamed from spec/support/mentionable_shared_examples.rb)0
-rw-r--r--spec/support/shared_examples/milestone_tabs_examples.rb (renamed from spec/support/milestone_tabs_examples.rb)0
-rw-r--r--spec/support/shared_examples/models/atomic_internal_id_spec.rb8
-rw-r--r--spec/support/shared_examples/notify_shared_examples.rb (renamed from spec/support/notify_shared_examples.rb)0
-rw-r--r--spec/support/shared_examples/reference_parser_shared_examples.rb (renamed from spec/support/reference_parser_shared_examples.rb)0
-rw-r--r--spec/support/shared_examples/slack_mattermost_notifications_shared_examples.rb (renamed from spec/support/slack_mattermost_notifications_shared_examples.rb)0
-rw-r--r--spec/support/shared_examples/snippet_visibility.rb (renamed from spec/support/snippet_visibility.rb)0
-rw-r--r--spec/support/shared_examples/snippets_shared_examples.rb (renamed from spec/support/snippets_shared_examples.rb)0
-rw-r--r--spec/support/shared_examples/taskable_shared_examples.rb (renamed from spec/support/taskable_shared_examples.rb)0
-rw-r--r--spec/support/shared_examples/time_tracking_shared_examples.rb (renamed from spec/support/time_tracking_shared_examples.rb)0
-rw-r--r--spec/support/shared_examples/unique_ip_check_shared_examples.rb (renamed from spec/support/unique_ip_check_shared_examples.rb)0
-rw-r--r--spec/support/shared_examples/update_invalid_issuable.rb (renamed from spec/support/update_invalid_issuable.rb)0
-rw-r--r--spec/support/shared_examples/updating_mentions_shared_examples.rb (renamed from spec/support/updating_mentions_shared_examples.rb)0
-rw-r--r--spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb (renamed from spec/views/projects/settings/ci_cd/_form.html.haml_spec.rb)2
-rw-r--r--spec/workers/issue_due_scheduler_worker_spec.rb4
-rw-r--r--yarn.lock289
249 files changed, 2043 insertions, 1399 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f97feca9f7b..87c3944dcce 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -75,7 +75,7 @@ stages:
.use-mysql: &use-mysql
services:
- - mysql:latest
+ - mysql:5.7
- redis:alpine
.rails5-variables: &rails5-variables
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index d443238b9e1..16b0b5c95e2 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -143,7 +143,7 @@ Lint/MissingCopEnableDirective:
Lint/NestedPercentLiteral:
Exclude:
- 'lib/gitlab/git/repository.rb'
- - 'spec/support/email_format_shared_examples.rb'
+ - 'spec/support/shared_examples/email_format_shared_examples.rb'
# Offense count: 1
Lint/ReturnInVoidContext:
@@ -195,8 +195,8 @@ Naming/HeredocDelimiterCase:
- 'spec/lib/gitlab/diff/parser_spec.rb'
- 'spec/lib/json_web_token/rsa_token_spec.rb'
- 'spec/models/commit_spec.rb'
- - 'spec/support/repo_helpers.rb'
- - 'spec/support/seed_repo.rb'
+ - 'spec/support/helpers/repo_helpers.rb'
+ - 'spec/support/helpers/seed_repo.rb'
# Offense count: 112
# Configuration parameters: Blacklist.
@@ -496,7 +496,7 @@ Style/EmptyLiteral:
- 'spec/lib/gitlab/request_context_spec.rb'
- 'spec/lib/gitlab/workhorse_spec.rb'
- 'spec/requests/api/jobs_spec.rb'
- - 'spec/support/chat_slash_commands_shared_examples.rb'
+ - 'spec/support/shared_examples/chat_slash_commands_shared_examples.rb'
# Offense count: 102
# Cop supports --auto-correct.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 02599907af7..29009010f0e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -26,7 +26,9 @@ _This notice should stay as the first item in the CONTRIBUTING.md file._
- [Type labels (~"feature proposal", ~bug, ~customer, etc.)](#type-labels-feature-proposal-bug-customer-etc)
- [Subject labels (~wiki, ~"container registry", ~ldap, ~api, etc.)](#subject-labels-wiki-container-registry-ldap-api-etc)
- [Team labels (~"CI/CD", ~Discussion, ~Edge, ~Platform, etc.)](#team-labels-cicd-discussion-edge-platform-etc)
- - [Priority labels (~Deliverable, ~Stretch, ~"Next Patch Release")](#priority-labels-deliverable-stretch-next-patch-release)
+ - [Milestone labels (~Deliverable, ~Stretch, ~"Next Patch Release")](#milestone-labels-deliverable-stretch-next-patch-release)
+ - [Priority labels (~Deliverable, ~Stretch, ~"Next Patch Release")](#bug-priority-labels-p1-p2-p3-etc)
+ - [Severity labels (~Deliverable, ~Stretch, ~"Next Patch Release")](#bug-severity-labels-s1-s2-s3-etc)
- [Label for community contributors (~"Accepting Merge Requests")](#label-for-community-contributors-accepting-merge-requests)
- [Implement design & UI elements](#implement-design-ui-elements)
- [Issue tracker](#issue-tracker)
@@ -127,6 +129,8 @@ Most issues will have labels for at least one of the following:
- Subject: ~wiki, ~"container registry", ~ldap, ~api, ~frontend, etc.
- Team: ~"CI/CD", ~Discussion, ~Edge, ~Platform, etc.
- Milestone: ~Deliverable, ~Stretch, ~"Next Patch Release"
+- Priority: ~P1, ~P2, ~P3, ~P4
+- Severity: ~S1, ~S2, ~S3, ~S4
All labels, their meaning and priority are defined on the
[labels page][labels-page].
@@ -210,7 +214,7 @@ This label documents the planned timeline & urgency which is used to measure aga
| Label | Meaning | Estimate time to fix | Guidance |
|-------|-----------------|------------------------------------------------------------------|----------|
-| ~P1 | Urgent Priority | The current release | |
+| ~P1 | Urgent Priority | The current release + potentially immediate hotfix to GitLab.com | |
| ~P2 | High Priority | The next release | |
| ~P3 | Medium Priority | Within the next 3 releases (approx one quarter) | |
| ~P4 | Low Priority | Anything outside the next 3 releases (approx beyond one quarter) | The issue is prominent but does not impact user workflow and a workaround is documented |
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 5f8cbfdb7d7..483b7719418 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-0.95.0
+0.96.1
diff --git a/Gemfile.lock b/Gemfile.lock
index 745732f3537..1ba99df5e44 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -178,7 +178,7 @@ GEM
docile (1.1.5)
domain_name (0.5.20170404)
unf (>= 0.0.5, < 1.0.0)
- doorkeeper (4.3.1)
+ doorkeeper (4.3.2)
railties (>= 4.2)
doorkeeper-openid_connect (1.3.0)
doorkeeper (~> 4.3)
diff --git a/app/assets/javascripts/create_merge_request_dropdown.js b/app/assets/javascripts/create_merge_request_dropdown.js
index fb1fc9cd32e..a88b6971f90 100644
--- a/app/assets/javascripts/create_merge_request_dropdown.js
+++ b/app/assets/javascripts/create_merge_request_dropdown.js
@@ -84,20 +84,21 @@ export default class CreateMergeRequestDropdown {
if (data.can_create_branch) {
this.available();
this.enable();
+ this.updateBranchName(data.suggested_branch_name);
if (!this.droplabInitialized) {
this.droplabInitialized = true;
this.initDroplab();
this.bindEvents();
}
- } else if (data.has_related_branch) {
+ } else {
this.hide();
}
})
.catch(() => {
this.unavailable();
this.disable();
- Flash('Failed to check if a new branch can be created.');
+ Flash(__('Failed to check related branches.'));
});
}
@@ -409,13 +410,16 @@ export default class CreateMergeRequestDropdown {
this.unavailableButton.classList.remove('hide');
}
+ updateBranchName(suggestedBranchName) {
+ this.branchInput.value = suggestedBranchName;
+ this.updateCreatePaths('branch', suggestedBranchName);
+ }
+
updateInputState(target, ref, result) {
// target - 'branch' or 'ref' - which the input field we are searching a ref for.
// ref - string - what a user typed.
// result - string - what has been found on backend.
- const pathReplacement = `$1${ref}`;
-
// If a found branch equals exact the same text a user typed,
// that means a new branch cannot be created as it already exists.
if (ref === result) {
@@ -426,18 +430,12 @@ export default class CreateMergeRequestDropdown {
this.refIsValid = true;
this.refInput.dataset.value = ref;
this.showAvailableMessage('ref');
- this.createBranchPath = this.createBranchPath.replace(this.regexps.ref.createBranchPath,
- pathReplacement);
- this.createMrPath = this.createMrPath.replace(this.regexps.ref.createMrPath,
- pathReplacement);
+ this.updateCreatePaths(target, ref);
}
} else if (target === 'branch') {
this.branchIsValid = true;
this.showAvailableMessage('branch');
- this.createBranchPath = this.createBranchPath.replace(this.regexps.branch.createBranchPath,
- pathReplacement);
- this.createMrPath = this.createMrPath.replace(this.regexps.branch.createMrPath,
- pathReplacement);
+ this.updateCreatePaths(target, ref);
} else {
this.refIsValid = false;
this.refInput.dataset.value = ref;
@@ -457,4 +455,15 @@ export default class CreateMergeRequestDropdown {
this.disableCreateAction();
}
}
+
+ // target - 'branch' or 'ref'
+ // ref - string - the new value to use as branch or ref
+ updateCreatePaths(target, ref) {
+ const pathReplacement = `$1${ref}`;
+
+ this.createBranchPath = this.createBranchPath.replace(this.regexps[target].createBranchPath,
+ pathReplacement);
+ this.createMrPath = this.createMrPath.replace(this.regexps[target].createMrPath,
+ pathReplacement);
+ }
}
diff --git a/app/assets/javascripts/pipelines/components/graph/action_component.vue b/app/assets/javascripts/pipelines/components/graph/action_component.vue
index e99d949801f..29ee73a2a6f 100644
--- a/app/assets/javascripts/pipelines/components/graph/action_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/action_component.vue
@@ -32,26 +32,38 @@ export default {
required: true,
},
- buttonDisabled: {
+ requestFinishedFor: {
type: String,
required: false,
- default: null,
+ default: '',
},
},
+ data() {
+ return {
+ isDisabled: false,
+ linkRequested: '',
+ };
+ },
+
computed: {
cssClass() {
const actionIconDash = dasherize(this.actionIcon);
return `${actionIconDash} js-icon-${actionIconDash}`;
},
- isDisabled() {
- return this.buttonDisabled === this.link;
+ },
+ watch: {
+ requestFinishedFor() {
+ if (this.requestFinishedFor === this.linkRequested) {
+ this.isDisabled = false;
+ }
},
},
-
methods: {
onClickAction() {
$(this.$el).tooltip('hide');
eventHub.$emit('graphAction', this.link);
+ this.linkRequested = this.link;
+ this.isDisabled = true;
},
},
};
@@ -62,7 +74,8 @@ export default {
@click="onClickAction"
v-tooltip
:title="tooltipText"
- class="btn btn-blank btn-transparent ci-action-icon-container ci-action-icon-wrapper"
+ class="js-ci-action btn btn-blank
+btn-transparent ci-action-icon-container ci-action-icon-wrapper"
:class="cssClass"
data-container="body"
:disabled="isDisabled"
diff --git a/app/assets/javascripts/pipelines/components/graph/dropdown_action_component.vue b/app/assets/javascripts/pipelines/components/graph/dropdown_action_component.vue
deleted file mode 100644
index 7c4fd65e36f..00000000000
--- a/app/assets/javascripts/pipelines/components/graph/dropdown_action_component.vue
+++ /dev/null
@@ -1,53 +0,0 @@
-<script>
- import icon from '../../../vue_shared/components/icon.vue';
- import tooltip from '../../../vue_shared/directives/tooltip';
-
- /**
- * Renders either a cancel, retry or play icon pointing to the given path.
- * TODO: Remove UJS from here and use an async request instead.
- */
- export default {
- components: {
- icon,
- },
-
- directives: {
- tooltip,
- },
- props: {
- tooltipText: {
- type: String,
- required: true,
- },
-
- link: {
- type: String,
- required: true,
- },
-
- actionMethod: {
- type: String,
- required: true,
- },
-
- actionIcon: {
- type: String,
- required: true,
- },
- },
- };
-</script>
-<template>
- <a
- v-tooltip
- :data-method="actionMethod"
- :title="tooltipText"
- :href="link"
- rel="nofollow"
- class="ci-action-icon-wrapper js-ci-status-icon"
- data-container="body"
- aria-label="Job's action"
- >
- <icon :name="actionIcon" />
- </a>
-</template>
diff --git a/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue b/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue
index be213c2ee78..43121dd38f3 100644
--- a/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/dropdown_job_component.vue
@@ -1,77 +1,83 @@
<script>
- import $ from 'jquery';
- import jobNameComponent from './job_name_component.vue';
- import jobComponent from './job_component.vue';
- import tooltip from '../../../vue_shared/directives/tooltip';
+import $ from 'jquery';
+import JobNameComponent from './job_name_component.vue';
+import JobComponent from './job_component.vue';
+import tooltip from '../../../vue_shared/directives/tooltip';
- /**
- * Renders the dropdown for the pipeline graph.
- *
- * The following object should be provided as `job`:
- *
- * {
- * "id": 4256,
- * "name": "test",
- * "status": {
- * "icon": "icon_status_success",
- * "text": "passed",
- * "label": "passed",
- * "group": "success",
- * "details_path": "/root/ci-mock/builds/4256",
- * "action": {
- * "icon": "retry",
- * "title": "Retry",
- * "path": "/root/ci-mock/builds/4256/retry",
- * "method": "post"
- * }
- * }
- * }
- */
- export default {
- directives: {
- tooltip,
- },
+/**
+ * Renders the dropdown for the pipeline graph.
+ *
+ * The following object should be provided as `job`:
+ *
+ * {
+ * "id": 4256,
+ * "name": "test",
+ * "status": {
+ * "icon": "icon_status_success",
+ * "text": "passed",
+ * "label": "passed",
+ * "group": "success",
+ * "details_path": "/root/ci-mock/builds/4256",
+ * "action": {
+ * "icon": "retry",
+ * "title": "Retry",
+ * "path": "/root/ci-mock/builds/4256/retry",
+ * "method": "post"
+ * }
+ * }
+ * }
+ */
+export default {
+ directives: {
+ tooltip,
+ },
- components: {
- jobComponent,
- jobNameComponent,
- },
+ components: {
+ JobComponent,
+ JobNameComponent,
+ },
- props: {
- job: {
- type: Object,
- required: true,
- },
+ props: {
+ job: {
+ type: Object,
+ required: true,
},
-
- computed: {
- tooltipText() {
- return `${this.job.name} - ${this.job.status.label}`;
- },
+ requestFinishedFor: {
+ type: String,
+ required: false,
+ default: '',
},
+ },
- mounted() {
- this.stopDropdownClickPropagation();
+ computed: {
+ tooltipText() {
+ return `${this.job.name} - ${this.job.status.label}`;
},
+ },
+
+ mounted() {
+ this.stopDropdownClickPropagation();
+ },
- methods: {
- /**
- * When the user right clicks or cmd/ctrl + click in the job name
- * the dropdown should not be closed and the link should open in another tab,
- * so we stop propagation of the click event inside the dropdown.
+ methods: {
+ /**
+ * When the user right clicks or cmd/ctrl + click in the job name or the action icon
+ * the dropdown should not be closed so we stop propagation
+ * of the click event inside the dropdown.
*
* Since this component is rendered multiple times per page we need to guarantee we only
* target the click event of this component.
*/
- stopDropdownClickPropagation() {
- $(this.$el
- .querySelectorAll('.js-grouped-pipeline-dropdown a.mini-pipeline-graph-dropdown-item'))
- .on('click', (e) => {
- e.stopPropagation();
- });
- },
+ stopDropdownClickPropagation() {
+ $(
+ '.js-grouped-pipeline-dropdown button, .js-grouped-pipeline-dropdown a.mini-pipeline-graph-dropdown-item',
+ this.$el,
+ ).on('click', e => {
+ e.stopPropagation();
+ });
},
- };
+ },
+};
</script>
<template>
<div class="ci-job-dropdown-container">
@@ -101,8 +107,8 @@
:key="i">
<job-component
:job="item"
- :is-dropdown="true"
css-class-job-name="mini-pipeline-graph-dropdown-item"
+ :request-finished-for="requestFinishedFor"
/>
</li>
</ul>
diff --git a/app/assets/javascripts/pipelines/components/graph/graph_component.vue b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
index ac9ce7e47d6..7b8a5edcbff 100644
--- a/app/assets/javascripts/pipelines/components/graph/graph_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/graph_component.vue
@@ -7,7 +7,6 @@ export default {
StageColumnComponent,
LoadingIcon,
},
-
props: {
isLoading: {
type: Boolean,
@@ -17,10 +16,10 @@ export default {
type: Object,
required: true,
},
- actionDisabled: {
+ requestFinishedFor: {
type: String,
required: false,
- default: null,
+ default: '',
},
},
@@ -75,7 +74,7 @@ export default {
:key="stage.name"
:stage-connector-class="stageConnectorClass(index, stage)"
:is-first-column="isFirstColumn(index)"
- :action-disabled="actionDisabled"
+ :request-finished-for="requestFinishedFor"
/>
</ul>
</div>
diff --git a/app/assets/javascripts/pipelines/components/graph/job_component.vue b/app/assets/javascripts/pipelines/components/graph/job_component.vue
index c6e5ae6df41..4fcd4b79f4a 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_component.vue
@@ -1,6 +1,5 @@
<script>
import ActionComponent from './action_component.vue';
-import DropdownActionComponent from './dropdown_action_component.vue';
import JobNameComponent from './job_name_component.vue';
import tooltip from '../../../vue_shared/directives/tooltip';
@@ -32,10 +31,8 @@ import tooltip from '../../../vue_shared/directives/tooltip';
export default {
components: {
ActionComponent,
- DropdownActionComponent,
JobNameComponent,
},
-
directives: {
tooltip,
},
@@ -44,26 +41,17 @@ export default {
type: Object,
required: true,
},
-
cssClassJobName: {
type: String,
required: false,
default: '',
},
-
- isDropdown: {
- type: Boolean,
- required: false,
- default: false,
- },
-
- actionDisabled: {
+ requestFinishedFor: {
type: String,
required: false,
- default: null,
+ default: '',
},
},
-
computed: {
status() {
return this.job && this.job.status ? this.job.status : {};
@@ -134,19 +122,11 @@ export default {
</div>
<action-component
- v-if="hasAction && !isDropdown"
- :tooltip-text="status.action.title"
- :link="status.action.path"
- :action-icon="status.action.icon"
- :button-disabled="actionDisabled"
- />
-
- <dropdown-action-component
- v-if="hasAction && isDropdown"
+ v-if="hasAction"
:tooltip-text="status.action.title"
:link="status.action.path"
:action-icon="status.action.icon"
- :action-method="status.action.method"
+ :request-finished-for="requestFinishedFor"
/>
</div>
</template>
diff --git a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
index f6e6569e15b..5461fdbbadd 100644
--- a/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/stage_column_component.vue
@@ -29,10 +29,11 @@ export default {
required: false,
default: '',
},
- actionDisabled: {
+
+ requestFinishedFor: {
type: String,
required: false,
- default: null,
+ default: '',
},
},
@@ -74,12 +75,12 @@ export default {
v-if="job.size === 1"
:job="job"
css-class-job-name="build-content"
- :action-disabled="actionDisabled"
/>
<dropdown-job-component
v-if="job.size > 1"
:job="job"
+ :request-finished-for="requestFinishedFor"
/>
</li>
diff --git a/app/assets/javascripts/pipelines/pipeline_details_bundle.js b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
index 900eb7855f4..6584f96130b 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_bundle.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_bundle.js
@@ -25,7 +25,7 @@ export default () => {
data() {
return {
mediator,
- actionDisabled: null,
+ requestFinishedFor: null,
};
},
created() {
@@ -36,15 +36,17 @@ export default () => {
},
methods: {
postAction(action) {
- this.actionDisabled = action;
+ // Click was made, reset this variable
+ this.requestFinishedFor = null;
- this.mediator.service.postAction(action)
+ this.mediator.service
+ .postAction(action)
.then(() => {
this.mediator.refreshPipeline();
- this.actionDisabled = null;
+ this.requestFinishedFor = action;
})
.catch(() => {
- this.actionDisabled = null;
+ this.requestFinishedFor = action;
Flash(__('An error occurred while making the request.'));
});
},
@@ -54,7 +56,7 @@ export default () => {
props: {
isLoading: this.mediator.state.isLoading,
pipeline: this.mediator.store.state.pipeline,
- actionDisabled: this.actionDisabled,
+ requestFinishedFor: this.requestFinishedFor,
},
});
},
@@ -79,7 +81,8 @@ export default () => {
},
methods: {
postAction(action) {
- this.mediator.service.postAction(action.path)
+ this.mediator.service
+ .postAction(action.path)
.then(() => this.mediator.refreshPipeline())
.catch(() => Flash(__('An error occurred while making the request.')));
},
diff --git a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
index 5324d5dc797..0d64efcbf68 100644
--- a/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
+++ b/app/assets/javascripts/vue_shared/components/ci_badge_link.vue
@@ -1,52 +1,52 @@
<script>
- import ciIcon from './ci_icon.vue';
- import tooltip from '../directives/tooltip';
- /**
- * Renders CI Badge link with CI icon and status text based on
- * API response shared between all places where it is used.
- *
- * Receives status object containing:
- * status: {
- * details_path: "/gitlab-org/gitlab-ce/pipelines/8150156" // url
- * group:"running" // used for CSS class
- * icon: "icon_status_running" // used to render the icon
- * label:"running" // used for potential tooltip
- * text:"running" // text rendered
- * }
- *
- * Used in:
- * - Pipelines table - first column
- * - Jobs table - first column
- * - Pipeline show view - header
- * - Job show view - header
- * - MR widget
- */
+import CiIcon from './ci_icon.vue';
+import tooltip from '../directives/tooltip';
+/**
+ * Renders CI Badge link with CI icon and status text based on
+ * API response shared between all places where it is used.
+ *
+ * Receives status object containing:
+ * status: {
+ * details_path: "/gitlab-org/gitlab-ce/pipelines/8150156" // url
+ * group:"running" // used for CSS class
+ * icon: "icon_status_running" // used to render the icon
+ * label:"running" // used for potential tooltip
+ * text:"running" // text rendered
+ * }
+ *
+ * Used in:
+ * - Pipelines table - first column
+ * - Jobs table - first column
+ * - Pipeline show view - header
+ * - Job show view - header
+ * - MR widget
+ */
- export default {
- components: {
- ciIcon,
+export default {
+ components: {
+ CiIcon,
+ },
+ directives: {
+ tooltip,
+ },
+ props: {
+ status: {
+ type: Object,
+ required: true,
},
- directives: {
- tooltip,
+ showText: {
+ type: Boolean,
+ required: false,
+ default: true,
},
- props: {
- status: {
- type: Object,
- required: true,
- },
- showText: {
- type: Boolean,
- required: false,
- default: true,
- },
+ },
+ computed: {
+ cssClass() {
+ const className = this.status.group;
+ return className ? `ci-status ci-${className}` : 'ci-status';
},
- computed: {
- cssClass() {
- const className = this.status.group;
- return className ? `ci-status ci-${className}` : 'ci-status';
- },
- },
- };
+ },
+};
</script>
<template>
<a
diff --git a/app/assets/javascripts/vue_shared/components/ci_icon.vue b/app/assets/javascripts/vue_shared/components/ci_icon.vue
index 8fea746f4de..fcab8f571dd 100644
--- a/app/assets/javascripts/vue_shared/components/ci_icon.vue
+++ b/app/assets/javascripts/vue_shared/components/ci_icon.vue
@@ -1,45 +1,44 @@
<script>
- import icon from '../../vue_shared/components/icon.vue';
+import Icon from '../../vue_shared/components/icon.vue';
- /**
- * Renders CI icon based on API response shared between all places where it is used.
- *
- * Receives status object containing:
- * status: {
- * details_path: "/gitlab-org/gitlab-ce/pipelines/8150156" // url
- * group:"running" // used for CSS class
- * icon: "icon_status_running" // used to render the icon
- * label:"running" // used for potential tooltip
- * text:"running" // text rendered
- * }
- *
- * Used in:
- * - Pipelines table Badge
- * - Pipelines table mini graph
- * - Pipeline graph
- * - Pipeline show view badge
- * - Jobs table
- * - Jobs show view header
- * - Jobs show view sidebar
- */
- export default {
- components: {
- icon,
+/**
+ * Renders CI icon based on API response shared between all places where it is used.
+ *
+ * Receives status object containing:
+ * status: {
+ * details_path: "/gitlab-org/gitlab-ce/pipelines/8150156" // url
+ * group:"running" // used for CSS class
+ * icon: "icon_status_running" // used to render the icon
+ * label:"running" // used for potential tooltip
+ * text:"running" // text rendered
+ * }
+ *
+ * Used in:
+ * - Pipelines table Badge
+ * - Pipelines table mini graph
+ * - Pipeline graph
+ * - Pipeline show view badge
+ * - Jobs table
+ * - Jobs show view header
+ * - Jobs show view sidebar
+ */
+export default {
+ components: {
+ Icon,
+ },
+ props: {
+ status: {
+ type: Object,
+ required: true,
},
- props: {
- status: {
- type: Object,
- required: true,
- },
+ },
+ computed: {
+ cssClass() {
+ const status = this.status.group;
+ return `ci-status-icon ci-status-icon-${status} js-ci-status-icon-${status}`;
},
-
- computed: {
- cssClass() {
- const status = this.status.group;
- return `ci-status-icon ci-status-icon-${status} js-ci-status-icon-${status}`;
- },
- },
- };
+ },
+};
</script>
<template>
<span :class="cssClass">
diff --git a/app/assets/javascripts/vue_shared/components/clipboard_button.vue b/app/assets/javascripts/vue_shared/components/clipboard_button.vue
index cab126a7eca..cb2cc3901ad 100644
--- a/app/assets/javascripts/vue_shared/components/clipboard_button.vue
+++ b/app/assets/javascripts/vue_shared/components/clipboard_button.vue
@@ -1,40 +1,50 @@
<script>
- /**
- * Falls back to the code used in `copy_to_clipboard.js`
- */
- import tooltip from '../directives/tooltip';
+/**
+ * Falls back to the code used in `copy_to_clipboard.js`
+ *
+ * Renders a button with a clipboard icon that copies the content of `data-clipboard-text`
+ * when clicked.
+ *
+ * @example
+ * <clipboard-button
+ * title="Copy to clipbard"
+ * text="Content to be copied"
+ * css-class="btn-transparent"
+ * />
+ */
+import tooltip from '../directives/tooltip';
- export default {
- name: 'ClipboardButton',
- directives: {
- tooltip,
+export default {
+ name: 'ClipboardButton',
+ directives: {
+ tooltip,
+ },
+ props: {
+ text: {
+ type: String,
+ required: true,
},
- props: {
- text: {
- type: String,
- required: true,
- },
- title: {
- type: String,
- required: true,
- },
- tooltipPlacement: {
- type: String,
- required: false,
- default: 'top',
- },
- tooltipContainer: {
- type: [String, Boolean],
- required: false,
- default: false,
- },
- cssClass: {
- type: String,
- required: false,
- default: 'btn-default',
- },
+ title: {
+ type: String,
+ required: true,
},
- };
+ tooltipPlacement: {
+ type: String,
+ required: false,
+ default: 'top',
+ },
+ tooltipContainer: {
+ type: [String, Boolean],
+ required: false,
+ default: false,
+ },
+ cssClass: {
+ type: String,
+ required: false,
+ default: 'btn-default',
+ },
+ },
+};
</script>
<template>
diff --git a/app/assets/javascripts/vue_shared/components/commit.vue b/app/assets/javascripts/vue_shared/components/commit.vue
index b8875d04488..8f250a6c989 100644
--- a/app/assets/javascripts/vue_shared/components/commit.vue
+++ b/app/assets/javascripts/vue_shared/components/commit.vue
@@ -1,119 +1,111 @@
<script>
- import commitIconSvg from 'icons/_icon_commit.svg';
- import userAvatarLink from './user_avatar/user_avatar_link.vue';
- import tooltip from '../directives/tooltip';
- import icon from '../../vue_shared/components/icon.vue';
+import UserAvatarLink from './user_avatar/user_avatar_link.vue';
+import tooltip from '../directives/tooltip';
+import Icon from '../../vue_shared/components/icon.vue';
- export default {
- directives: {
- tooltip,
+export default {
+ directives: {
+ tooltip,
+ },
+ components: {
+ UserAvatarLink,
+ Icon,
+ },
+ props: {
+ /**
+ * Indicates the existance of a tag.
+ * Used to render the correct icon, if true will render `fa-tag` icon,
+ * if false will render a svg sprite fork icon
+ */
+ tag: {
+ type: Boolean,
+ required: false,
+ default: false,
},
- components: {
- userAvatarLink,
- icon,
+ /**
+ * If provided is used to render the branch name and url.
+ * Should contain the following properties:
+ * name
+ * ref_url
+ */
+ commitRef: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ /**
+ * Used to link to the commit sha.
+ */
+ commitUrl: {
+ type: String,
+ required: false,
+ default: '',
},
- props: {
- /**
- * Indicates the existance of a tag.
- * Used to render the correct icon, if true will render `fa-tag` icon,
- * if false will render a svg sprite fork icon
- */
- tag: {
- type: Boolean,
- required: false,
- default: false,
- },
- /**
- * If provided is used to render the branch name and url.
- * Should contain the following properties:
- * name
- * ref_url
- */
- commitRef: {
- type: Object,
- required: false,
- default: () => ({}),
- },
- /**
- * Used to link to the commit sha.
- */
- commitUrl: {
- type: String,
- required: false,
- default: '',
- },
- /**
- * Used to show the commit short sha that links to the commit url.
- */
- shortSha: {
- type: String,
- required: false,
- default: '',
- },
- /**
- * If provided shows the commit tile.
- */
- title: {
- type: String,
- required: false,
- default: '',
- },
- /**
- * If provided renders information about the author of the commit.
- * When provided should include:
- * `avatar_url` to render the avatar icon
- * `web_url` to link to user profile
- * `username` to render alt and title tags
- */
- author: {
- type: Object,
- required: false,
- default: () => ({}),
- },
- showBranch: {
- type: Boolean,
- required: false,
- default: true,
- },
+ /**
+ * Used to show the commit short sha that links to the commit url.
+ */
+ shortSha: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ /**
+ * If provided shows the commit tile.
+ */
+ title: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ /**
+ * If provided renders information about the author of the commit.
+ * When provided should include:
+ * `avatar_url` to render the avatar icon
+ * `web_url` to link to user profile
+ * `username` to render alt and title tags
+ */
+ author: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ showBranch: {
+ type: Boolean,
+ required: false,
+ default: true,
},
- computed: {
- /**
- * Used to verify if all the properties needed to render the commit
- * ref section were provided.
- *
- * @returns {Boolean}
- */
- hasCommitRef() {
- return this.commitRef && this.commitRef.name && this.commitRef.ref_url;
- },
- /**
- * Used to verify if all the properties needed to render the commit
- * author section were provided.
- *
- * @returns {Boolean}
- */
- hasAuthor() {
- return this.author &&
- this.author.avatar_url &&
- this.author.path &&
- this.author.username;
- },
- /**
- * If information about the author is provided will return a string
- * to be rendered as the alt attribute of the img tag.
- *
- * @returns {String}
- */
- userImageAltDescription() {
- return this.author &&
- this.author.username ? `${this.author.username}'s avatar` : null;
- },
+ },
+ computed: {
+ /**
+ * Used to verify if all the properties needed to render the commit
+ * ref section were provided.
+ *
+ * @returns {Boolean}
+ */
+ hasCommitRef() {
+ return this.commitRef && this.commitRef.name && this.commitRef.ref_url;
},
- created() {
- this.commitIconSvg = commitIconSvg;
+ /**
+ * Used to verify if all the properties needed to render the commit
+ * author section were provided.
+ *
+ * @returns {Boolean}
+ */
+ hasAuthor() {
+ return this.author && this.author.avatar_url && this.author.path && this.author.username;
},
- };
+ /**
+ * If information about the author is provided will return a string
+ * to be rendered as the alt attribute of the img tag.
+ *
+ * @returns {String}
+ */
+ userImageAltDescription() {
+ return this.author && this.author.username ? `${this.author.username}'s avatar` : null;
+ },
+ },
+};
</script>
<template>
<div class="branch-commit">
@@ -141,11 +133,10 @@
{{ commitRef.name }}
</a>
</template>
- <div
- v-html="commitIconSvg"
+ <icon
+ name="commit"
class="commit-icon js-commit-icon"
- >
- </div>
+ />
<a
class="commit-sha"
diff --git a/app/assets/javascripts/vue_shared/components/expand_button.vue b/app/assets/javascripts/vue_shared/components/expand_button.vue
index c943c8d98a4..9295be3e2b2 100644
--- a/app/assets/javascripts/vue_shared/components/expand_button.vue
+++ b/app/assets/javascripts/vue_shared/components/expand_button.vue
@@ -1,33 +1,33 @@
<script>
- import { __ } from '~/locale';
- /**
- * Port of detail_behavior expand button.
- *
- * @example
- * <expand-button>
- * <template slot="expanded">
- * Text goes here.
- * </template>
- * </expand-button>
- */
- export default {
- name: 'ExpandButton',
- data() {
- return {
- isCollapsed: true,
- };
+import { __ } from '~/locale';
+/**
+ * Port of detail_behavior expand button.
+ *
+ * @example
+ * <expand-button>
+ * <template slot="expanded">
+ * Text goes here.
+ * </template>
+ * </expand-button>
+ */
+export default {
+ name: 'ExpandButton',
+ data() {
+ return {
+ isCollapsed: true,
+ };
+ },
+ computed: {
+ ariaLabel() {
+ return __('Click to expand text');
},
- computed: {
- ariaLabel() {
- return __('Click to expand text');
- },
+ },
+ methods: {
+ onClick() {
+ this.isCollapsed = !this.isCollapsed;
},
- methods: {
- onClick() {
- this.isCollapsed = !this.isCollapsed;
- },
- },
- };
+ },
+};
</script>
<template>
<span>
diff --git a/app/assets/javascripts/vue_shared/components/header_ci_component.vue b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
index a0cd0cbd200..088187ed348 100644
--- a/app/assets/javascripts/vue_shared/components/header_ci_component.vue
+++ b/app/assets/javascripts/vue_shared/components/header_ci_component.vue
@@ -1,78 +1,78 @@
<script>
- import ciIconBadge from './ci_badge_link.vue';
- import loadingIcon from './loading_icon.vue';
- import timeagoTooltip from './time_ago_tooltip.vue';
- import tooltip from '../directives/tooltip';
- import userAvatarImage from './user_avatar/user_avatar_image.vue';
+import CiIconBadge from './ci_badge_link.vue';
+import LoadingIcon from './loading_icon.vue';
+import TimeagoTooltip from './time_ago_tooltip.vue';
+import tooltip from '../directives/tooltip';
+import UserAvatarImage from './user_avatar/user_avatar_image.vue';
- /**
- * Renders header component for job and pipeline page based on UI mockups
- *
- * Used in:
- * - job show page
- * - pipeline show page
- */
- export default {
- components: {
- ciIconBadge,
- loadingIcon,
- timeagoTooltip,
- userAvatarImage,
+/**
+ * Renders header component for job and pipeline page based on UI mockups
+ *
+ * Used in:
+ * - job show page
+ * - pipeline show page
+ */
+export default {
+ components: {
+ CiIconBadge,
+ LoadingIcon,
+ TimeagoTooltip,
+ UserAvatarImage,
+ },
+ directives: {
+ tooltip,
+ },
+ props: {
+ status: {
+ type: Object,
+ required: true,
},
- directives: {
- tooltip,
+ itemName: {
+ type: String,
+ required: true,
},
- props: {
- status: {
- type: Object,
- required: true,
- },
- itemName: {
- type: String,
- required: true,
- },
- itemId: {
- type: Number,
- required: true,
- },
- time: {
- type: String,
- required: true,
- },
- user: {
- type: Object,
- required: false,
- default: () => ({}),
- },
- actions: {
- type: Array,
- required: false,
- default: () => [],
- },
- hasSidebarButton: {
- type: Boolean,
- required: false,
- default: false,
- },
- shouldRenderTriggeredLabel: {
- type: Boolean,
- required: false,
- default: true,
- },
+ itemId: {
+ type: Number,
+ required: true,
},
+ time: {
+ type: String,
+ required: true,
+ },
+ user: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ actions: {
+ type: Array,
+ required: false,
+ default: () => [],
+ },
+ hasSidebarButton: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ shouldRenderTriggeredLabel: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
- computed: {
- userAvatarAltText() {
- return `${this.user.name}'s avatar`;
- },
+ computed: {
+ userAvatarAltText() {
+ return `${this.user.name}'s avatar`;
},
+ },
- methods: {
- onClickAction(action) {
- this.$emit('actionClicked', action);
- },
+ methods: {
+ onClickAction(action) {
+ this.$emit('actionClicked', action);
},
- };
+ },
+};
</script>
<template>
diff --git a/app/assets/javascripts/vue_shared/components/icon.vue b/app/assets/javascripts/vue_shared/components/icon.vue
index 6a2e05000e1..1a0df49bc29 100644
--- a/app/assets/javascripts/vue_shared/components/icon.vue
+++ b/app/assets/javascripts/vue_shared/components/icon.vue
@@ -1,76 +1,75 @@
<script>
+/* This is a re-usable vue component for rendering a svg sprite
+ icon
- /* This is a re-usable vue component for rendering a svg sprite
- icon
+ Sample configuration:
- Sample configuration:
+ <icon
+ name="retry"
+ :size="32"
+ css-classes="top"
+ />
- <icon
- name="retry"
- :size="32"
- css-classes="top"
- />
+*/
+// only allow classes in images.scss e.g. s12
+const validSizes = [8, 12, 16, 18, 24, 32, 48, 72];
- */
- // only allow classes in images.scss e.g. s12
- const validSizes = [8, 12, 16, 18, 24, 32, 48, 72];
-
- export default {
- props: {
- name: {
- type: String,
- required: true,
- },
+export default {
+ props: {
+ name: {
+ type: String,
+ required: true,
+ },
- size: {
- type: Number,
- required: false,
- default: 16,
- validator(value) {
- return validSizes.includes(value);
- },
+ size: {
+ type: Number,
+ required: false,
+ default: 16,
+ validator(value) {
+ return validSizes.includes(value);
},
+ },
- cssClasses: {
- type: String,
- required: false,
- default: '',
- },
+ cssClasses: {
+ type: String,
+ required: false,
+ default: '',
+ },
- width: {
- type: Number,
- required: false,
- default: null,
- },
+ width: {
+ type: Number,
+ required: false,
+ default: null,
+ },
- height: {
- type: Number,
- required: false,
- default: null,
- },
+ height: {
+ type: Number,
+ required: false,
+ default: null,
+ },
- y: {
- type: Number,
- required: false,
- default: null,
- },
+ y: {
+ type: Number,
+ required: false,
+ default: null,
+ },
- x: {
- type: Number,
- required: false,
- default: null,
- },
+ x: {
+ type: Number,
+ required: false,
+ default: null,
},
+ },
- computed: {
- spriteHref() {
- return `${gon.sprite_icons}#${this.name}`;
- },
- iconSizeClass() {
- return this.size ? `s${this.size}` : '';
- },
+ computed: {
+ spriteHref() {
+ return `${gon.sprite_icons}#${this.name}`;
+ },
+ iconSizeClass() {
+ return this.size ? `s${this.size}` : '';
},
- };
+ },
+};
</script>
<template>
@@ -79,7 +78,8 @@
:width="width"
:height="height"
:x="x"
- :y="y">
+ :y="y"
+ >
<use v-bind="{ 'xlink:href':spriteHref }" />
</svg>
</template>
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
index 5ede53d8d01..70b46a9c2bb 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/base.vue
@@ -1,4 +1,5 @@
<script>
+import $ from 'jquery';
import { __ } from '~/locale';
import LabelsSelect from '~/labels_select';
import LoadingIcon from '../../loading_icon.vue';
@@ -98,11 +99,18 @@ export default {
this.labelsDropdown = new LabelsSelect(this.$refs.dropdownButton, {
handleClick: this.handleClick,
});
+ $(this.$refs.dropdown).on('hidden.gl.dropdown', this.handleDropdownHidden);
},
methods: {
handleClick(label) {
this.$emit('onLabelClick', label);
},
+ handleCollapsedValueClick() {
+ this.$emit('toggleCollapse');
+ },
+ handleDropdownHidden() {
+ this.$emit('onDropdownClose');
+ },
},
};
</script>
@@ -112,6 +120,7 @@ export default {
<dropdown-value-collapsed
v-if="showCreate"
:labels="context.labels"
+ @onValueClick="handleCollapsedValueClick"
/>
<dropdown-title
:can-edit="canEdit"
@@ -133,7 +142,10 @@ export default {
:name="hiddenInputName"
:label="label"
/>
- <div class="dropdown">
+ <div
+ class="dropdown"
+ ref="dropdown"
+ >
<dropdown-button
:ability-name="abilityName"
:field-name="hiddenInputName"
diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
index 5cf728fe050..68fa2ab8d01 100644
--- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
+++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
@@ -26,6 +26,11 @@ export default {
return labelsString;
},
},
+ methods: {
+ handleClick() {
+ this.$emit('onValueClick');
+ },
+ },
};
</script>
@@ -36,6 +41,7 @@ export default {
data-placement="left"
data-container="body"
:title="labelsList"
+ @click="handleClick"
>
<i
aria-hidden="true"
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index 855ebf7d86d..3a8ec779c14 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -468,6 +468,14 @@
margin-bottom: 10px;
white-space: normal;
+ .ci-job-dropdown-container {
+ // override dropdown.scss
+ .dropdown-menu li button {
+ padding: 0;
+ text-align: center;
+ }
+ }
+
// ensure .build-content has hover style when action-icon is hovered
.ci-job-dropdown-container:hover .build-content {
@extend .build-content:hover;
diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb
index 767e492f566..d69015c8665 100644
--- a/app/controllers/projects/issues_controller.rb
+++ b/app/controllers/projects/issues_controller.rb
@@ -134,11 +134,11 @@ class Projects::IssuesController < Projects::ApplicationController
def can_create_branch
can_create = current_user &&
can?(current_user, :push_code, @project) &&
- @issue.can_be_worked_on?(current_user)
+ @issue.can_be_worked_on?
respond_to do |format|
format.json do
- render json: { can_create_branch: can_create, has_related_branch: @issue.has_related_branch? }
+ render json: { can_create_branch: can_create, suggested_branch_name: @issue.suggested_branch_name }
end
end
end
@@ -177,7 +177,7 @@ class Projects::IssuesController < Projects::ApplicationController
end
def authorize_create_merge_request!
- render_404 unless can?(current_user, :push_code, @project) && @issue.can_be_worked_on?(current_user)
+ render_404 unless can?(current_user, :push_code, @project) && @issue.can_be_worked_on?
end
def render_issue_json
diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb
index 7497b5012ec..dd12d30a085 100644
--- a/app/controllers/projects/jobs_controller.rb
+++ b/app/controllers/projects/jobs_controller.rb
@@ -78,8 +78,6 @@ class Projects::JobsController < Projects::ApplicationController
result.merge!(trace.to_h)
end
- result[:html] = result[:html].presence || 'No job log'
-
render json: result
end
end
diff --git a/app/finders/users_finder.rb b/app/finders/users_finder.rb
index edde8022ec9..65824a51919 100644
--- a/app/finders/users_finder.rb
+++ b/app/finders/users_finder.rb
@@ -32,6 +32,7 @@ class UsersFinder
users = by_active(users)
users = by_external_identity(users)
users = by_external(users)
+ users = by_2fa(users)
users = by_created_at(users)
users = by_custom_attributes(users)
@@ -76,4 +77,15 @@ class UsersFinder
users.external
end
+
+ def by_2fa(users)
+ case params[:two_factor]
+ when 'enabled'
+ users.with_two_factor
+ when 'disabled'
+ users.without_two_factor
+ else
+ users
+ end
+ end
end
diff --git a/app/models/concerns/atomic_internal_id.rb b/app/models/concerns/atomic_internal_id.rb
index 4b66725a3e6..22f516a172f 100644
--- a/app/models/concerns/atomic_internal_id.rb
+++ b/app/models/concerns/atomic_internal_id.rb
@@ -27,8 +27,9 @@ module AtomicInternalId
module ClassMethods
def has_internal_id(column, scope:, init:) # rubocop:disable Naming/PredicateName
before_validation(on: :create) do
- if read_attribute(column).blank?
- scope_attrs = { scope => association(scope).reader }
+ scope_value = association(scope).reader
+ if read_attribute(column).blank? && scope_value
+ scope_attrs = { scope_value.class.table_name.singularize.to_sym => scope_value }
usage = self.class.table_name.to_sym
new_iid = InternalId.generate_next(self, scope_attrs, usage, init)
diff --git a/app/models/concerns/avatarable.rb b/app/models/concerns/avatarable.rb
index 7677891b9ce..13246a774e3 100644
--- a/app/models/concerns/avatarable.rb
+++ b/app/models/concerns/avatarable.rb
@@ -31,12 +31,13 @@ module Avatarable
asset_host = ActionController::Base.asset_host
use_asset_host = asset_host.present?
+ use_authentication = respond_to?(:public?) && !public?
# Avatars for private and internal groups and projects require authentication to be viewed,
# which means they can only be served by Rails, on the regular GitLab host.
# If an asset host is configured, we need to return the fully qualified URL
# instead of only the avatar path, so that Rails doesn't prefix it with the asset host.
- if use_asset_host && respond_to?(:public?) && !public?
+ if use_asset_host && use_authentication
use_asset_host = false
only_path = false
end
@@ -49,6 +50,6 @@ module Avatarable
url_base << gitlab_config.relative_url_root
end
- url_base + avatar.url
+ url_base + avatar.local_url
end
end
diff --git a/app/models/concerns/nonatomic_internal_id.rb b/app/models/concerns/nonatomic_internal_id.rb
deleted file mode 100644
index 9d0c9b8512f..00000000000
--- a/app/models/concerns/nonatomic_internal_id.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-module NonatomicInternalId
- extend ActiveSupport::Concern
-
- included do
- validate :set_iid, on: :create
- validates :iid, presence: true, numericality: true
- end
-
- def set_iid
- if iid.blank?
- parent = project || group
- records = parent.public_send(self.class.name.tableize) # rubocop:disable GitlabSecurity/PublicSend
- max_iid = records.maximum(:iid)
-
- self.iid = max_iid.to_i + 1
- end
- end
-
- def to_param
- iid.to_s
- end
-end
diff --git a/app/models/concerns/routable.rb b/app/models/concerns/routable.rb
index dfd7d94450b..915ad6959be 100644
--- a/app/models/concerns/routable.rb
+++ b/app/models/concerns/routable.rb
@@ -102,7 +102,7 @@ module Routable
# the route. Caching this per request ensures that even if we have multiple instances,
# we will not have to duplicate work, avoiding N+1 queries in some cases.
def full_path
- return uncached_full_path unless RequestStore.active?
+ return uncached_full_path unless RequestStore.active? && persisted?
RequestStore[full_path_key] ||= uncached_full_path
end
@@ -124,6 +124,11 @@ module Routable
end
end
+ # Group would override this to check from association
+ def owned_by?(user)
+ owner == user
+ end
+
private
def set_path_errors
diff --git a/app/models/concerns/uniquify.rb b/app/models/concerns/uniquify.rb
index a7fe5951b6e..549a76da20e 100644
--- a/app/models/concerns/uniquify.rb
+++ b/app/models/concerns/uniquify.rb
@@ -1,13 +1,21 @@
+# Uniquify
+#
+# Return a version of the given 'base' string that is unique
+# by appending a counter to it. Uniqueness is determined by
+# repeated calls to the passed block.
+#
+# You can pass an initial value for the counter, if not given
+# counting starts from 1.
+#
+# If `base` is a function/proc, we expect that calling it with a
+# candidate counter returns a string to test/return.
class Uniquify
- # Return a version of the given 'base' string that is unique
- # by appending a counter to it. Uniqueness is determined by
- # repeated calls to the passed block.
- #
- # If `base` is a function/proc, we expect that calling it with a
- # candidate counter returns a string to test/return.
+ def initialize(counter = nil)
+ @counter = counter
+ end
+
def string(base)
@base = base
- @counter = nil
increment_counter! while yield(base_string)
base_string
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index e18ea8bfea4..254764eefde 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -1,11 +1,13 @@
class Deployment < ActiveRecord::Base
- include NonatomicInternalId
+ include AtomicInternalId
belongs_to :project, required: true
belongs_to :environment, required: true
belongs_to :user
belongs_to :deployable, polymorphic: true # rubocop:disable Cop/PolymorphicAssociations
+ has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.deployments&.maximum(:iid) }
+
validates :sha, presence: true
validates :ref, presence: true
diff --git a/app/models/group.rb b/app/models/group.rb
index 8ff781059cc..9b42bbf99be 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -125,6 +125,10 @@ class Group < Namespace
self[:lfs_enabled]
end
+ def owned_by?(user)
+ owners.include?(user)
+ end
+
def add_users(users, access_level, current_user: nil, expires_at: nil)
GroupMember.add_users(
self,
diff --git a/app/models/internal_id.rb b/app/models/internal_id.rb
index 96a43006642..189942c5ad8 100644
--- a/app/models/internal_id.rb
+++ b/app/models/internal_id.rb
@@ -12,8 +12,9 @@
# * (Optionally) add columns to `internal_ids` if needed for scope.
class InternalId < ActiveRecord::Base
belongs_to :project
+ belongs_to :namespace
- enum usage: { issues: 0 }
+ enum usage: { issues: 0, merge_requests: 1, deployments: 2, milestones: 3, epics: 4 }
validates :usage, presence: true
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 7611e83647c..0332bfa9371 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -194,6 +194,15 @@ class Issue < ActiveRecord::Base
branches_with_iid - branches_with_merge_request
end
+ def suggested_branch_name
+ return to_branch_name unless project.repository.branch_exists?(to_branch_name)
+
+ start_counting_from = 2
+ Uniquify.new(start_counting_from).string(-> (counter) { "#{to_branch_name}-#{counter}" }) do |suggested_branch_name|
+ project.repository.branch_exists?(suggested_branch_name)
+ end
+ end
+
# Returns boolean if a related branch exists for the current issue
# ignores merge requests branchs
def has_related_branch?
@@ -248,11 +257,8 @@ class Issue < ActiveRecord::Base
end
end
- def can_be_worked_on?(current_user)
- !self.closed? &&
- !self.project.forked? &&
- self.related_branches(current_user).empty? &&
- self.closed_by_merge_requests(current_user).empty?
+ def can_be_worked_on?
+ !self.closed? && !self.project.forked?
end
# Returns `true` if the current issue can be viewed by either a logged in User
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 91d8be5559b..8f964a488aa 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -1,5 +1,5 @@
class MergeRequest < ActiveRecord::Base
- include NonatomicInternalId
+ include AtomicInternalId
include Issuable
include Noteable
include Referable
@@ -18,6 +18,8 @@ class MergeRequest < ActiveRecord::Base
belongs_to :source_project, class_name: "Project"
belongs_to :merge_user, class_name: "User"
+ has_internal_id :iid, scope: :target_project, init: ->(s) { s&.target_project&.merge_requests&.maximum(:iid) }
+
has_many :merge_request_diffs
has_one :merge_request_diff,
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index a66a0015827..d14e3a4ded5 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -8,7 +8,7 @@ class Milestone < ActiveRecord::Base
Started = MilestoneStruct.new('Started', '#started', -3)
include CacheMarkdownField
- include NonatomicInternalId
+ include AtomicInternalId
include Sortable
include Referable
include StripAttribute
@@ -21,6 +21,9 @@ class Milestone < ActiveRecord::Base
belongs_to :project
belongs_to :group
+ has_internal_id :iid, scope: :project, init: ->(s) { s&.project&.milestones&.maximum(:iid) }
+ has_internal_id :iid, scope: :group, init: ->(s) { s&.group&.milestones&.maximum(:iid) }
+
has_many :issues
has_many :labels, -> { distinct.reorder('labels.title') }, through: :issues
has_many :merge_requests
diff --git a/app/models/project_services/flowdock_service.rb b/app/models/project_services/flowdock_service.rb
index 4d23a17a545..da01ac1b7cf 100644
--- a/app/models/project_services/flowdock_service.rb
+++ b/app/models/project_services/flowdock_service.rb
@@ -1,5 +1,51 @@
require "flowdock-git-hook"
+# Flow dock depends on Grit to compute the number of commits between two given
+# commits. To make this depend on Gitaly, a monkey patch is applied
+module Flowdock
+ class Git
+ # pass down a Repository all the way down
+ def repo
+ @options[:repo]
+ end
+
+ def config
+ {}
+ end
+
+ def messages
+ Git::Builder.new(repo: repo,
+ ref: @ref,
+ before: @from,
+ after: @to,
+ commit_url: @commit_url,
+ branch_url: @branch_url,
+ diff_url: @diff_url,
+ repo_url: @repo_url,
+ repo_name: @repo_name,
+ permanent_refs: @permanent_refs,
+ tags: tags
+ ).to_hashes
+ end
+
+ class Builder
+ def commits
+ @repo.commits_between(@before, @after).map do |commit|
+ {
+ url: @opts[:commit_url] ? @opts[:commit_url] % [commit.sha] : nil,
+ id: commit.sha,
+ message: commit.message,
+ author: {
+ name: commit.author_name,
+ email: commit.author_email
+ }
+ }
+ end
+ end
+ end
+ end
+end
+
class FlowdockService < Service
prop_accessor :token
validates :token, presence: true, if: :activated?
@@ -34,7 +80,7 @@ class FlowdockService < Service
data[:before],
data[:after],
token: token,
- repo: project.repository.path_to_repo,
+ repo: project.repository,
repo_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}",
commit_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/commit/%s",
diff_url: "#{Gitlab.config.gitlab.url}/#{project.full_path}/compare/%s...%s"
diff --git a/app/presenters/project_presenter.rb b/app/presenters/project_presenter.rb
index 484ac64580d..63ead5538cb 100644
--- a/app/presenters/project_presenter.rb
+++ b/app/presenters/project_presenter.rb
@@ -260,7 +260,7 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
if current_user && can?(current_user, :admin_pipeline, project) && repository.gitlab_ci_yml.blank? && !show_auto_devops_callout
OpenStruct.new(enabled: auto_devops_enabled?,
label: auto_devops_enabled? ? _('Auto DevOps enabled') : _('Enable Auto DevOps'),
- link: project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings'))
+ link: project_settings_ci_cd_path(project, anchor: 'autodevops-settings'))
elsif auto_devops_enabled?
OpenStruct.new(enabled: true,
label: _('Auto DevOps enabled'),
diff --git a/app/uploaders/gitlab_uploader.rb b/app/uploaders/gitlab_uploader.rb
index f12f0466a1d..f8a237178d9 100644
--- a/app/uploaders/gitlab_uploader.rb
+++ b/app/uploaders/gitlab_uploader.rb
@@ -65,6 +65,10 @@ class GitlabUploader < CarrierWave::Uploader::Base
!!model
end
+ def local_url
+ File.join('/', self.class.base_dir, dynamic_segment, filename)
+ end
+
private
# Designed to be overridden by child uploaders that have a dynamic path
diff --git a/app/views/admin/application_settings/_repository_storage.html.haml b/app/views/admin/application_settings/_repository_storage.html.haml
index ac31977e1a9..4eebb59110a 100644
--- a/app/views/admin/application_settings/_repository_storage.html.haml
+++ b/app/views/admin/application_settings/_repository_storage.html.haml
@@ -21,7 +21,7 @@
.help-block
Manage repository storage paths. Learn more in the
= succeed "." do
- = link_to "repository storages documentation", help_page_path("administration/repository_storages")
+ = link_to "repository storages documentation", help_page_path("administration/repository_storage_paths")
.sub-section
%h4 Circuit breaker
.form-group
diff --git a/app/views/projects/empty.html.haml b/app/views/projects/empty.html.haml
index b15fe514a08..2f69da593cd 100644
--- a/app/views/projects/empty.html.haml
+++ b/app/views/projects/empty.html.haml
@@ -22,7 +22,7 @@
%hr
%p
- - link_to_auto_devops_settings = link_to(s_('AutoDevOps|enable Auto DevOps (Beta)'), project_settings_ci_cd_path(@project, anchor: 'js-general-pipeline-settings'))
+ - link_to_auto_devops_settings = link_to(s_('AutoDevOps|enable Auto DevOps (Beta)'), project_settings_ci_cd_path(@project, anchor: 'autodevops-settings'))
- link_to_add_kubernetes_cluster = link_to(s_('AutoDevOps|add a Kubernetes cluster'), new_project_cluster_path(@project))
= s_('AutoDevOps|You can automatically build and test your application if you %{link_to_auto_devops_settings} for this project. You can automatically deploy it as well, if you %{link_to_add_kubernetes_cluster}.').html_safe % { link_to_auto_devops_settings: link_to_auto_devops_settings, link_to_add_kubernetes_cluster: link_to_add_kubernetes_cluster }
diff --git a/app/views/projects/jobs/index.html.haml b/app/views/projects/jobs/index.html.haml
index 9963cc93633..fe1c338b634 100644
--- a/app/views/projects/jobs/index.html.haml
+++ b/app/views/projects/jobs/index.html.haml
@@ -15,7 +15,7 @@
- unless @repository.gitlab_ci_yml
= link_to 'Get started with Pipelines', help_page_path('ci/quick_start/README'), class: 'btn btn-info'
- = link_to ci_lint_path, class: 'btn btn-default' do
+ = link_to project_ci_lint_path(@project), class: 'btn btn-default' do
%span CI lint
.content-list.builds-content-list
diff --git a/app/views/projects/pipelines/_with_tabs.html.haml b/app/views/projects/pipelines/_with_tabs.html.haml
index 852143ecb2a..218e7338c83 100644
--- a/app/views/projects/pipelines/_with_tabs.html.haml
+++ b/app/views/projects/pipelines/_with_tabs.html.haml
@@ -26,7 +26,7 @@
%ul
- pipeline.yaml_errors.split(",").each do |error|
%li= error
- You can also test your .gitlab-ci.yml in the #{link_to "Lint", ci_lint_path}
+ You can also test your .gitlab-ci.yml in the #{link_to "Lint", project_ci_lint_path(@project)}
- if pipeline.project.builds_enabled? && !pipeline.ci_yaml_file
.bs-callout.bs-callout-warning
diff --git a/app/views/projects/settings/ci_cd/_autodevops_form.html.haml b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
new file mode 100644
index 00000000000..7b410101c05
--- /dev/null
+++ b/app/views/projects/settings/ci_cd/_autodevops_form.html.haml
@@ -0,0 +1,40 @@
+.row.prepend-top-default
+ .col-lg-12
+ = form_for @project, url: project_settings_ci_cd_path(@project) do |f|
+ = form_errors(@project)
+ %fieldset.builds-feature
+ .form-group
+ - message = auto_devops_warning_message(@project)
+ - ci_file_formatted = '<code>.gitlab-ci.yml</code>'.html_safe
+ - if message
+ %p.settings-message.text-center
+ = message.html_safe
+ = f.fields_for :auto_devops_attributes, @auto_devops do |form|
+ .radio
+ = form.label :enabled_true do
+ = form.radio_button :enabled, 'true'
+ %strong= s_('CICD|Enable Auto DevOps')
+ %br
+ = s_('CICD|The Auto DevOps pipeline configuration will be used when there is no %{ci_file} in the project.').html_safe % { ci_file: ci_file_formatted }
+
+ .radio
+ = form.label :enabled_false do
+ = form.radio_button :enabled, 'false'
+ %strong= s_('CICD|Disable Auto DevOps')
+ %br
+ = s_('CICD|An explicit %{ci_file} needs to be specified before you can begin using Continuous Integration and Delivery.').html_safe % { ci_file: ci_file_formatted }
+
+ .radio
+ = form.label :enabled_ do
+ = form.radio_button :enabled, ''
+ %strong= s_('CICD|Instance default (%{state})') % { state: "#{Gitlab::CurrentSettings.auto_devops_enabled? ? _('enabled') : _('disabled')}" }
+ %br
+ = s_('CICD|Follow the instance default to either have Auto DevOps enabled or disabled when there is no project specific %{ci_file}.').html_safe % { ci_file: ci_file_formatted }
+
+ = form.label :domain, class:"prepend-top-10" do
+ = _('Domain')
+ = form.text_field :domain, class: 'form-control', placeholder: 'domain.com'
+ .help-block
+ = s_('CICD|You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages.')
+
+ = f.submit 'Save changes', class: "btn btn-success prepend-top-15"
diff --git a/app/views/projects/settings/ci_cd/_form.html.haml b/app/views/projects/settings/ci_cd/_form.html.haml
index 20868f9ba5d..80c226ad273 100644
--- a/app/views/projects/settings/ci_cd/_form.html.haml
+++ b/app/views/projects/settings/ci_cd/_form.html.haml
@@ -3,44 +3,6 @@
= form_for @project, url: project_settings_ci_cd_path(@project) do |f|
= form_errors(@project)
%fieldset.builds-feature
- .form-group
- %h5 Auto DevOps (Beta)
- %p
- Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration.
- = link_to 'Learn more about Auto DevOps', help_page_path('topics/autodevops/index.md')
- - message = auto_devops_warning_message(@project)
- - if message
- %p.settings-message.text-center
- = message.html_safe
- = f.fields_for :auto_devops_attributes, @auto_devops do |form|
- .radio
- = form.label :enabled_true do
- = form.radio_button :enabled, 'true'
- %strong Enable Auto DevOps
- %br
- %span.descr
- The Auto DevOps pipeline configuration will be used when there is no <code>.gitlab-ci.yml</code> in the project.
-
- .radio
- = form.label :enabled_false do
- = form.radio_button :enabled, 'false'
- %strong Disable Auto DevOps
- %br
- %span.descr
- An explicit <code>.gitlab-ci.yml</code> needs to be specified before you can begin using Continuous Integration and Delivery.
-
- .radio
- = form.label :enabled_ do
- = form.radio_button :enabled, ''
- %strong Instance default (#{Gitlab::CurrentSettings.auto_devops_enabled? ? 'enabled' : 'disabled'})
- %br
- %span.descr
- Follow the instance default to either have Auto DevOps enabled or disabled when there is no project specific <code>.gitlab-ci.yml</code>.
- %p
- You need to specify a domain if you want to use Auto Review Apps and Auto Deploy stages.
- = form.text_field :domain, class: 'form-control', placeholder: 'domain.com'
-
- %hr
.form-group.append-bottom-default.js-secret-runner-token
= f.label :runners_token, "Runner token", class: 'label-light'
.form-control.js-secret-value-placeholder
diff --git a/app/views/projects/settings/ci_cd/show.html.haml b/app/views/projects/settings/ci_cd/show.html.haml
index 09268c9943b..5f596a019f7 100644
--- a/app/views/projects/settings/ci_cd/show.html.haml
+++ b/app/views/projects/settings/ci_cd/show.html.haml
@@ -12,10 +12,22 @@
%button.btn.js-settings-toggle{ type: 'button' }
= expanded ? 'Collapse' : 'Expand'
%p
- Update your CI/CD configuration, like job timeout or Auto DevOps.
+ Access your runner token, customize your pipeline configuration, and view your pipeline status and coverage report.
.settings-content
= render 'form'
+%section.settings#autodevops-settings.no-animate{ class: ('expanded' if expanded) }
+ .settings-header
+ %h4
+ = s_('CICD|Auto DevOps (Beta)')
+ %button.btn.btn-default.js-settings-toggle{ type: 'button' }
+ = expanded ? _('Collapse') : _('Expand')
+ %p
+ = s_('CICD|Auto DevOps will automatically build, test, and deploy your application based on a predefined Continuous Integration and Delivery configuration.')
+ = link_to s_('CICD|Learn more about Auto DevOps'), help_page_path('topics/autodevops/index.md')
+ .settings-content
+ = render 'autodevops_form'
+
%section.settings.no-animate{ class: ('expanded' if expanded) }
.settings-header
%h4
diff --git a/app/views/shared/_auto_devops_callout.html.haml b/app/views/shared/_auto_devops_callout.html.haml
index e9ac192f5f7..d3fa324e460 100644
--- a/app/views/shared/_auto_devops_callout.html.haml
+++ b/app/views/shared/_auto_devops_callout.html.haml
@@ -9,7 +9,7 @@
- link = link_to(s_('AutoDevOps|Auto DevOps documentation'), help_page_path('topics/autodevops/index.md'), target: '_blank', rel: 'noopener noreferrer')
= s_('AutoDevOps|Learn more in the %{link_to_documentation}').html_safe % { link_to_documentation: link }
.banner-buttons
- = link_to s_('AutoDevOps|Enable in settings'), project_settings_ci_cd_path(@project, anchor: 'js-general-pipeline-settings'), class: 'btn js-close-callout'
+ = link_to s_('AutoDevOps|Enable in settings'), project_settings_ci_cd_path(@project, anchor: 'autodevops-settings'), class: 'btn js-close-callout'
%button.btn-transparent.banner-close.close.js-close-callout{ type: 'button',
'aria-label' => 'Dismiss Auto DevOps box' }
diff --git a/changelogs/unreleased/33697-remove-ujs-action-big-graph.yml b/changelogs/unreleased/33697-remove-ujs-action-big-graph.yml
new file mode 100644
index 00000000000..43ce52c1209
--- /dev/null
+++ b/changelogs/unreleased/33697-remove-ujs-action-big-graph.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent pipeline actions in dropdown to redirct to a new page
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/39345-get-raw-archive.yml b/changelogs/unreleased/39345-get-raw-archive.yml
new file mode 100644
index 00000000000..fa894432d4c
--- /dev/null
+++ b/changelogs/unreleased/39345-get-raw-archive.yml
@@ -0,0 +1,5 @@
+---
+title: Add an API endpoint to download git repository snapshots
+merge_request: 18173
+author:
+type: added
diff --git a/changelogs/unreleased/42803-show-new-branch-mr-button.yml b/changelogs/unreleased/42803-show-new-branch-mr-button.yml
new file mode 100644
index 00000000000..d689ff7f001
--- /dev/null
+++ b/changelogs/unreleased/42803-show-new-branch-mr-button.yml
@@ -0,0 +1,5 @@
+---
+title: Show new branch/mr button even when branch exists
+merge_request: 17712
+author: Jacopo Beschi @jacopo-beschi
+type: added
diff --git a/changelogs/unreleased/42936-improve-ns-factory-avoid-duplicates.yml b/changelogs/unreleased/42936-improve-ns-factory-avoid-duplicates.yml
new file mode 100644
index 00000000000..54b523b65a1
--- /dev/null
+++ b/changelogs/unreleased/42936-improve-ns-factory-avoid-duplicates.yml
@@ -0,0 +1,6 @@
+---
+title: Fix discussions API setting created_at for notable in a group or notable in
+ a project in a group with owners
+merge_request: 18464
+author:
+type: fixed
diff --git a/changelogs/unreleased/43466-make-auto-devops-settings-first-class.yml b/changelogs/unreleased/43466-make-auto-devops-settings-first-class.yml
new file mode 100644
index 00000000000..f5c5415159c
--- /dev/null
+++ b/changelogs/unreleased/43466-make-auto-devops-settings-first-class.yml
@@ -0,0 +1,5 @@
+---
+title: Create settings section for autodevops
+merge_request: 18321
+author:
+type: changed
diff --git a/changelogs/unreleased/44775-avatar-on-os-fails-with-cdn.yml b/changelogs/unreleased/44775-avatar-on-os-fails-with-cdn.yml
new file mode 100644
index 00000000000..80b5b4a8abe
--- /dev/null
+++ b/changelogs/unreleased/44775-avatar-on-os-fails-with-cdn.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed wrong avatar URL when the avatar is on object storage.
+merge_request: 18092
+author:
+type: fixed
diff --git a/changelogs/unreleased/45576-fix-create-project-for-user-endpoint.yml b/changelogs/unreleased/45576-fix-create-project-for-user-endpoint.yml
new file mode 100644
index 00000000000..12631c75b44
--- /dev/null
+++ b/changelogs/unreleased/45576-fix-create-project-for-user-endpoint.yml
@@ -0,0 +1,5 @@
+---
+title: Fix project creation for user endpoint when jobs_enabled parameter supplied
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/45625-job-log-shows-no-job-log.yml b/changelogs/unreleased/45625-job-log-shows-no-job-log.yml
new file mode 100644
index 00000000000..5f60e818cc1
--- /dev/null
+++ b/changelogs/unreleased/45625-job-log-shows-no-job-log.yml
@@ -0,0 +1,5 @@
+---
+title: Removes 'No Job log' message from build trace
+merge_request: 18523
+author:
+type: fixed
diff --git a/changelogs/unreleased/45666-project-ci-lint-links.yml b/changelogs/unreleased/45666-project-ci-lint-links.yml
new file mode 100644
index 00000000000..dbf803c0921
--- /dev/null
+++ b/changelogs/unreleased/45666-project-ci-lint-links.yml
@@ -0,0 +1,5 @@
+---
+title: Update links to /ci/lint with ones to project ci/lint
+merge_request: 18539
+author: Takuya Noguchi
+type: fixed
diff --git a/changelogs/unreleased/ab-44259-atomic-internal-ids-for-all-models.yml b/changelogs/unreleased/ab-44259-atomic-internal-ids-for-all-models.yml
new file mode 100644
index 00000000000..e154f7dbc85
--- /dev/null
+++ b/changelogs/unreleased/ab-44259-atomic-internal-ids-for-all-models.yml
@@ -0,0 +1,5 @@
+---
+title: Transition to atomic internal ids for all models.
+merge_request: 44259
+author:
+type: other
diff --git a/changelogs/unreleased/blackst0ne-add-missing-changelog-type-to-docs.yml b/changelogs/unreleased/blackst0ne-add-missing-changelog-type-to-docs.yml
new file mode 100644
index 00000000000..f8790fa45aa
--- /dev/null
+++ b/changelogs/unreleased/blackst0ne-add-missing-changelog-type-to-docs.yml
@@ -0,0 +1,5 @@
+---
+title: Add missing changelog type to docs
+merge_request: 18526
+author: "@blackst0ne"
+type: other
diff --git a/changelogs/unreleased/dz-add-2fa-filter-admin-api.yml b/changelogs/unreleased/dz-add-2fa-filter-admin-api.yml
new file mode 100644
index 00000000000..df479e69380
--- /dev/null
+++ b/changelogs/unreleased/dz-add-2fa-filter-admin-api.yml
@@ -0,0 +1,5 @@
+---
+title: Add 2FA filter to users API for admins only
+merge_request: 18503
+author:
+type: changed
diff --git a/changelogs/unreleased/rd-44635-error-500-when-clicking-ghost-user-or-gitlab-support-bot-in-ui.yml b/changelogs/unreleased/rd-44635-error-500-when-clicking-ghost-user-or-gitlab-support-bot-in-ui.yml
new file mode 100644
index 00000000000..a08a75ceda6
--- /dev/null
+++ b/changelogs/unreleased/rd-44635-error-500-when-clicking-ghost-user-or-gitlab-support-bot-in-ui.yml
@@ -0,0 +1,5 @@
+---
+title: Fix missing namespace for some internal users
+merge_request: 18357
+author:
+type: fixed
diff --git a/changelogs/unreleased/rd-45502-uploading-project-export-with-lfs-file-locks-fails.yml b/changelogs/unreleased/rd-45502-uploading-project-export-with-lfs-file-locks-fails.yml
new file mode 100644
index 00000000000..e3266dda629
--- /dev/null
+++ b/changelogs/unreleased/rd-45502-uploading-project-export-with-lfs-file-locks-fails.yml
@@ -0,0 +1,5 @@
+---
+title: Don't include lfs_file_locks data in export bundle
+merge_request: 18495
+author:
+type: fixed
diff --git a/changelogs/unreleased/update-doorkeeper-changelog.yml b/changelogs/unreleased/update-doorkeeper-changelog.yml
new file mode 100644
index 00000000000..b47bdf4a28d
--- /dev/null
+++ b/changelogs/unreleased/update-doorkeeper-changelog.yml
@@ -0,0 +1,5 @@
+---
+title: Update doorkeeper to 4.3.2 to fix GitLab OAuth authentication
+merge_request: 18543
+author:
+type: fixed
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index dc7999ac556..9b00ae459a3 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -1,131 +1,4 @@
-# rubocop:disable GitlabSecurity/PublicSend
-
-require_dependency Rails.root.join('lib/gitlab') # Load Gitlab as soon as possible
-
-class Settings < Settingslogic
- source ENV.fetch('GITLAB_CONFIG') { "#{Rails.root}/config/gitlab.yml" }
- namespace Rails.env
-
- class << self
- def gitlab_on_standard_port?
- on_standard_port?(gitlab)
- end
-
- def host_without_www(url)
- host(url).sub('www.', '')
- end
-
- def build_gitlab_ci_url
- custom_port =
- if on_standard_port?(gitlab)
- nil
- else
- ":#{gitlab.port}"
- end
-
- [
- gitlab.protocol,
- "://",
- gitlab.host,
- custom_port,
- gitlab.relative_url_root
- ].join('')
- end
-
- def build_pages_url
- base_url(pages).join('')
- end
-
- def build_gitlab_shell_ssh_path_prefix
- user_host = "#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}"
-
- if gitlab_shell.ssh_port != 22
- "ssh://#{user_host}:#{gitlab_shell.ssh_port}/"
- else
- if gitlab_shell.ssh_host.include? ':'
- "[#{user_host}]:"
- else
- "#{user_host}:"
- end
- end
- end
-
- def build_base_gitlab_url
- base_url(gitlab).join('')
- end
-
- def build_gitlab_url
- (base_url(gitlab) + [gitlab.relative_url_root]).join('')
- end
-
- # check that values in `current` (string or integer) is a contant in `modul`.
- def verify_constant_array(modul, current, default)
- values = default || []
- unless current.nil?
- values = []
- current.each do |constant|
- values.push(verify_constant(modul, constant, nil))
- end
- values.delete_if { |value| value.nil? }
- end
-
- values
- end
-
- # check that `current` (string or integer) is a contant in `modul`.
- def verify_constant(modul, current, default)
- constant = modul.constants.find { |name| modul.const_get(name) == current }
- value = constant.nil? ? default : modul.const_get(constant)
- if current.is_a? String
- value = modul.const_get(current.upcase) rescue default
- end
-
- value
- end
-
- def absolute(path)
- File.expand_path(path, Rails.root)
- end
-
- private
-
- def base_url(config)
- custom_port = on_standard_port?(config) ? nil : ":#{config.port}"
-
- [
- config.protocol,
- "://",
- config.host,
- custom_port
- ]
- end
-
- def on_standard_port?(config)
- config.port.to_i == (config.https ? 443 : 80)
- end
-
- # Extract the host part of the given +url+.
- def host(url)
- url = url.downcase
- url = "http://#{url}" unless url.start_with?('http')
-
- # Get rid of the path so that we don't even have to encode it
- url_without_path = url.sub(%r{(https?://[^/]+)/?.*}, '\1')
-
- URI.parse(url_without_path).host
- end
-
- # Runs every minute in a random ten-minute period on Sundays, to balance the
- # load on the server receiving these pings. The usage ping is safe to run
- # multiple times because of a 24 hour exclusive lock.
- def cron_for_usage_ping
- hour = rand(24)
- minute = rand(6)
-
- "#{minute}0-#{minute}9 #{hour} * * 0"
- end
- end
-end
+require_dependency File.expand_path('../../lib/gitlab', __dir__) # Load Gitlab as soon as possible
# Default settings
Settings['ldap'] ||= Settingslogic.new({})
diff --git a/config/initializers/2_app.rb b/config/initializers/2_app.rb
deleted file mode 100644
index bd74f90e7d2..00000000000
--- a/config/initializers/2_app.rb
+++ /dev/null
@@ -1,8 +0,0 @@
-module Gitlab
- def self.config
- Settings
- end
-
- VERSION = File.read(Rails.root.join("VERSION")).strip.freeze
- REVISION = Gitlab::Popen.popen(%W(#{config.git.bin_path} log --pretty=format:%h -n 1)).first.chomp.freeze
-end
diff --git a/db/fixtures/development/17_cycle_analytics.rb b/db/fixtures/development/17_cycle_analytics.rb
index d7be6f5950f..7b9a4bad449 100644
--- a/db/fixtures/development/17_cycle_analytics.rb
+++ b/db/fixtures/development/17_cycle_analytics.rb
@@ -1,5 +1,5 @@
require './spec/support/sidekiq'
-require './spec/support/test_env'
+require './spec/support/helpers/test_env'
class Gitlab::Seeder::CycleAnalytics
def initialize(project, perf: false)
diff --git a/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb b/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb
new file mode 100644
index 00000000000..8fc558be733
--- /dev/null
+++ b/db/migrate/20180413022611_create_missing_namespace_for_internal_users.rb
@@ -0,0 +1,66 @@
+class CreateMissingNamespaceForInternalUsers < ActiveRecord::Migration
+ DOWNTIME = false
+
+ def up
+ connection.exec_query(users_query.to_sql).rows.each do |id, username|
+ create_namespace(id, username)
+ # When testing locally I've noticed that these internal users are missing
+ # the notification email, for more details visit the below link:
+ # https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18357#note_68327560
+ set_notification_email(id)
+ end
+ end
+
+ def down
+ # no-op
+ end
+
+ private
+
+ def users
+ @users ||= Arel::Table.new(:users)
+ end
+
+ def namespaces
+ @namespaces ||= Arel::Table.new(:namespaces)
+ end
+
+ def users_query
+ condition = users[:ghost].eq(true)
+
+ if column_exists?(:users, :support_bot)
+ condition = condition.or(users[:support_bot].eq(true))
+ end
+
+ users.join(namespaces, Arel::Nodes::OuterJoin)
+ .on(namespaces[:type].eq(nil).and(namespaces[:owner_id].eq(users[:id])))
+ .where(namespaces[:owner_id].eq(nil))
+ .where(condition)
+ .project(users[:id], users[:username])
+ end
+
+ def create_namespace(user_id, username)
+ path = Uniquify.new.string(username) do |str|
+ query = "SELECT id FROM namespaces WHERE parent_id IS NULL AND path='#{str}' LIMIT 1"
+ connection.exec_query(query).present?
+ end
+
+ insert_query = "INSERT INTO namespaces(owner_id, path, name) VALUES(#{user_id}, '#{path}', '#{path}')"
+ namespace_id = connection.insert_sql(insert_query)
+
+ create_route(namespace_id)
+ end
+
+ def create_route(namespace_id)
+ return unless namespace_id
+
+ row = connection.exec_query("SELECT id, path FROM namespaces WHERE id=#{namespace_id}").first
+ id, path = row.values_at('id', 'path')
+
+ execute("INSERT INTO routes(source_id, source_type, path, name) VALUES(#{id}, 'Namespace', '#{path}', '#{path}')")
+ end
+
+ def set_notification_email(user_id)
+ execute "UPDATE users SET notification_email = email WHERE notification_email IS NULL AND id = #{user_id}"
+ end
+end
diff --git a/db/migrate/20180416155103_add_further_scope_columns_to_internal_id_table.rb b/db/migrate/20180416155103_add_further_scope_columns_to_internal_id_table.rb
new file mode 100644
index 00000000000..37e2d19e022
--- /dev/null
+++ b/db/migrate/20180416155103_add_further_scope_columns_to_internal_id_table.rb
@@ -0,0 +1,15 @@
+class AddFurtherScopeColumnsToInternalIdTable < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ change_column_null :internal_ids, :project_id, true
+ add_column :internal_ids, :namespace_id, :integer, null: true
+ end
+
+ def down
+ change_column_null :internal_ids, :project_id, false
+ remove_column :internal_ids, :namespace_id
+ end
+end
diff --git a/db/migrate/20180417090132_add_index_constraints_to_internal_id_table.rb b/db/migrate/20180417090132_add_index_constraints_to_internal_id_table.rb
new file mode 100644
index 00000000000..582b89a3948
--- /dev/null
+++ b/db/migrate/20180417090132_add_index_constraints_to_internal_id_table.rb
@@ -0,0 +1,40 @@
+class AddIndexConstraintsToInternalIdTable < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :internal_ids, [:usage, :namespace_id], unique: true, where: 'namespace_id IS NOT NULL'
+
+ replace_index(:internal_ids, [:usage, :project_id], name: 'index_internal_ids_on_usage_and_project_id') do
+ add_concurrent_index :internal_ids, [:usage, :project_id], unique: true, where: 'project_id IS NOT NULL'
+ end
+
+ add_concurrent_foreign_key :internal_ids, :namespaces, column: :namespace_id, on_delete: :cascade
+ end
+
+ def down
+ remove_concurrent_index :internal_ids, [:usage, :namespace_id]
+
+ replace_index(:internal_ids, [:usage, :project_id], name: 'index_internal_ids_on_usage_and_project_id') do
+ add_concurrent_index :internal_ids, [:usage, :project_id], unique: true
+ end
+
+ remove_foreign_key :internal_ids, column: :namespace_id
+ end
+
+ private
+ def replace_index(table, columns, name:)
+ temporary_name = "#{name}_old"
+
+ if index_exists?(table, columns, name: name)
+ rename_index table, name, temporary_name
+ end
+
+ yield
+
+ remove_concurrent_index_by_name table, temporary_name
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 1d272bdb779..df621956c80 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -896,12 +896,14 @@ ActiveRecord::Schema.define(version: 20180418053107) do
add_index "identities", ["user_id"], name: "index_identities_on_user_id", using: :btree
create_table "internal_ids", id: :bigserial, force: :cascade do |t|
- t.integer "project_id", null: false
+ t.integer "project_id"
t.integer "usage", null: false
t.integer "last_value", null: false
+ t.integer "namespace_id"
end
- add_index "internal_ids", ["usage", "project_id"], name: "index_internal_ids_on_usage_and_project_id", unique: true, using: :btree
+ add_index "internal_ids", ["usage", "namespace_id"], name: "index_internal_ids_on_usage_and_namespace_id", unique: true, where: "(namespace_id IS NOT NULL)", using: :btree
+ add_index "internal_ids", ["usage", "project_id"], name: "index_internal_ids_on_usage_and_project_id", unique: true, where: "(project_id IS NOT NULL)", using: :btree
create_table "issue_assignees", id: false, force: :cascade do |t|
t.integer "user_id", null: false
@@ -2113,6 +2115,7 @@ ActiveRecord::Schema.define(version: 20180418053107) do
add_foreign_key "gpg_signatures", "gpg_keys", on_delete: :nullify
add_foreign_key "gpg_signatures", "projects", on_delete: :cascade
add_foreign_key "group_custom_attributes", "namespaces", column: "group_id", on_delete: :cascade
+ add_foreign_key "internal_ids", "namespaces", name: "fk_162941d509", on_delete: :cascade
add_foreign_key "internal_ids", "projects", on_delete: :cascade
add_foreign_key "issue_assignees", "issues", name: "fk_b7d881734a", on_delete: :cascade
add_foreign_key "issue_assignees", "users", name: "fk_5e0c8d9154", on_delete: :cascade
diff --git a/doc/administration/high_availability/redis.md b/doc/administration/high_availability/redis.md
index fd2677996b1..430f865f1e7 100644
--- a/doc/administration/high_availability/redis.md
+++ b/doc/administration/high_availability/redis.md
@@ -650,6 +650,47 @@ gitlab_rails['redis_sentinels'] = [
Omnibus GitLab configures some things behind the curtains to make the sysadmins'
lives easier. If you want to know what happens underneath keep reading.
+### Running multiple Redis clusters
+
+GitLab supports running [separate Redis clusters for different persistent
+classes](https://docs.gitlab.com/omnibus/settings/redis.html#running-with-multiple-redis-instances):
+cache, queues, and shared_state. To make this work with Sentinel:
+
+1. Set the appropriate variable in `/etc/gitlab/gitlab.rb` for each instance you are using:
+
+ ```ruby
+ gitlab_rails['redis_cache_instance'] = REDIS_CACHE_URL
+ gitlab_rails['redis_queues_instance'] = REDIS_QUEUES_URL
+ gitlab_rails['redis_shared_state_instance'] = REDIS_SHARED_STATE_URL
+ ```
+ **Note**: Redis URLs should be in the format: `redis://:PASSWORD@SENTINEL_MASTER_NAME`
+
+ 1. PASSWORD is the plaintext password for the Redis instance
+ 2. SENTINEL_MASTER_NAME is the Sentinel master name (e.g. `gitlab-redis-cache`)
+1. Include an array of hashes with host/port combinations, such as the following:
+
+ ```ruby
+ gitlab_rails['redis_cache_sentinels'] = [
+ { host: REDIS_CACHE_SENTINEL_HOST, port: PORT1 },
+ { host: REDIS_CACHE_SENTINEL_HOST2, port: PORT2 }
+ ]
+ gitlab_rails['redis_queues_sentinels'] = [
+ { host: REDIS_QUEUES_SENTINEL_HOST, port: PORT1 },
+ { host: REDIS_QUEUES_SENTINEL_HOST2, port: PORT2 }
+ ]
+ gitlab_rails['redis_shared_state_sentinels'] = [
+ { host: SHARED_STATE_SENTINEL_HOST, port: PORT1 },
+ { host: SHARED_STATE_SENTINEL_HOST2, port: PORT2 }
+ ]
+ ```
+1. Note that for each persistence class, GitLab will default to using the
+ configuration specified in `gitlab_rails['redis_sentinels']` unless
+ overriden by the settings above.
+1. Be sure to include BOTH configuration options for each persistent classes. For example,
+ if you choose to configure a cache instance, you must specify both `gitlab_rails['redis_cache_instance']`
+ and `gitlab_rails['redis_cache_sentinels']` for GitLab to generate the proper configuration files.
+1. Run `gitlab-ctl reconfigure`
+
### Control running services
In the previous example, we've used `redis_sentinel_role` and
diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md
index 00c631fdaae..9b3b1e48efd 100644
--- a/doc/administration/pages/index.md
+++ b/doc/administration/pages/index.md
@@ -119,11 +119,17 @@ The Pages daemon doesn't listen to the outside world.
1. Set the external URL for GitLab Pages in `/etc/gitlab/gitlab.rb`:
- ```ruby
+ ```shell
pages_external_url 'http://example.io'
```
1. [Reconfigure GitLab][reconfigure]
+1. Restart gitlab-pages by running the following command:
+
+ ```shell
+ sudo gitlab-ctl restart gitlab-pages
+ ```
+
Watch the [video tutorial][video-admin] for this configuration.
@@ -143,7 +149,7 @@ outside world.
1. Place the certificate and key inside `/etc/gitlab/ssl`
1. In `/etc/gitlab/gitlab.rb` specify the following configuration:
- ```ruby
+ ```shell
pages_external_url 'https://example.io'
pages_nginx['redirect_http_to_https'] = true
@@ -155,6 +161,11 @@ outside world.
respectively.
1. [Reconfigure GitLab][reconfigure]
+1. Restart gitlab-pages by running the following command:
+
+ ```shell
+ sudo gitlab-ctl restart gitlab-pages
+ ```
## Advanced configuration
@@ -180,7 +191,7 @@ world. Custom domains are supported, but no TLS.
1. Edit `/etc/gitlab/gitlab.rb`:
- ```ruby
+ ```shell
pages_external_url "http://example.io"
nginx['listen_addresses'] = ['1.1.1.1']
pages_nginx['enable'] = false
@@ -192,6 +203,11 @@ world. Custom domains are supported, but no TLS.
listens on. If you don't have IPv6, you can omit the IPv6 address.
1. [Reconfigure GitLab][reconfigure]
+1. Restart gitlab-pages by running the following command:
+
+ ```shell
+ sudo gitlab-ctl restart gitlab-pages
+ ```
### Custom domains with TLS support
@@ -210,7 +226,7 @@ world. Custom domains and TLS are supported.
1. Edit `/etc/gitlab/gitlab.rb`:
- ```ruby
+ ```shell
pages_external_url "https://example.io"
nginx['listen_addresses'] = ['1.1.1.1']
pages_nginx['enable'] = false
@@ -225,6 +241,11 @@ world. Custom domains and TLS are supported.
listens on. If you don't have IPv6, you can omit the IPv6 address.
1. [Reconfigure GitLab][reconfigure]
+1. Restart gitlab-pages by running the following command:
+
+ ```shell
+ sudo gitlab-ctl restart gitlab-pages
+ ```
### Custom domain verification
@@ -247,11 +268,16 @@ are stored.
If you wish to store them in another location you must set it up in
`/etc/gitlab/gitlab.rb`:
- ```ruby
+ ```shell
gitlab_rails['pages_path'] = "/mnt/storage/pages"
```
1. [Reconfigure GitLab][reconfigure]
+1. Restart gitlab-pages by running the following command:
+
+ ```shell
+ sudo gitlab-ctl restart gitlab-pages
+ ```
## Set maximum pages size
diff --git a/doc/api/project_import_export.md b/doc/api/project_import_export.md
index d8f61852b11..085437c801a 100644
--- a/doc/api/project_import_export.md
+++ b/doc/api/project_import_export.md
@@ -112,13 +112,13 @@ POST /projects/import
| `file` | string | yes | The file to be uploaded |
| `path` | string | yes | Name and path for new project |
| `overwrite` | boolean | no | If there is a project with the same path the import will overwrite it. Default to false |
-| `override_params` | Hash | no | Supports all fields defined in the [Project API](projects.md)] |
+| `override_params` | Hash | no | Supports all fields defined in the [Project API](projects.md) |
-The override params passed will take precendence over all values defined inside the export file.
+The override params passed will take precedence over all values defined inside the export file.
-To upload a file from your filesystem, use the `--form` argument. This causes
+To upload a file from your file system, use the `--form` argument. This causes
cURL to post data using the header `Content-Type: multipart/form-data`.
-The `file=` parameter must point to a file on your filesystem and be preceded
+The `file=` parameter must point to a file on your file system and be preceded
by `@`. For example:
```console
diff --git a/doc/api/projects.md b/doc/api/projects.md
index 7ffe380e275..fe21dfe23f9 100644
--- a/doc/api/projects.md
+++ b/doc/api/projects.md
@@ -1398,4 +1398,27 @@ Read more in the [Project Badges](project_badges.md) documentation.
## Issue and merge request description templates
-The non-default [issue and merge request description templates](../user/project/description_templates.md) are managed inside the project's repository. So you can manage them via the API through the [Repositories API](repositories.md) and the [Repository Files API](repository_files.md). \ No newline at end of file
+The non-default [issue and merge request description templates](../user/project/description_templates.md) are managed inside the project's repository. So you can manage them via the API through the [Repositories API](repositories.md) and the [Repository Files API](repository_files.md).
+
+## Download snapshot of a git repository
+
+> Introduced in GitLab 10.7
+
+This endpoint may only be accessed by an administrative user.
+
+Download a snapshot of the project (or wiki, if requested) git repository. This
+snapshot is always in uncompressed [tar](https://en.wikipedia.org/wiki/Tar_(computing))
+format.
+
+If a repository is corrupted to the point where `git clone` does not work, the
+snapshot may allow some of the data to be retrieved.
+
+```
+GET /projects/:id/snapshot
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
+| `wiki` | boolean | no | Whether to download the wiki, rather than project, repository |
+
diff --git a/doc/api/users.md b/doc/api/users.md
index a4447e32908..ca5afa04687 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -55,6 +55,7 @@ GET /users
| --------- | ---- | -------- | ----------- |
| `order_by` | string | no | Return projects ordered by `id`, `name`, `username`, `created_at`, or `updated_at` fields. Default is `id` |
| `sort` | string | no | Return projects sorted in `asc` or `desc` order. Default is `desc` |
+| `two_factor` | string | no | Filter users by Two-factor authentication. Filter values are `enabled` or `disabled`. By default it returns all users |
```json
[
diff --git a/doc/development/changelog.md b/doc/development/changelog.md
index d5a4acff481..a9fa5ae834f 100644
--- a/doc/development/changelog.md
+++ b/doc/development/changelog.md
@@ -22,7 +22,7 @@ The `merge_request` value is a reference to a merge request that adds this
entry, and the `author` key is used to give attribution to community
contributors. **Both are optional**.
The `type` field maps the category of the change,
-valid options are: added, fixed, changed, deprecated, removed, security, other. **Type field is mandatory**.
+valid options are: added, fixed, changed, deprecated, removed, security, performance, other. **Type field is mandatory**.
Community contributors and core team members are encouraged to add their name to
the `author` field. GitLab team members **should not**.
diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md
index df80cd9f584..b77e9b7ff63 100644
--- a/doc/development/testing_guide/best_practices.md
+++ b/doc/development/testing_guide/best_practices.md
@@ -90,6 +90,25 @@ Finished in 34.51 seconds (files took 0.76702 seconds to load)
Note: `live_debug` only works on javascript enabled specs.
+### Fast unit tests
+
+Some classes are well-isolated from Rails and you should be able to test them
+without the overhead added by the Rails environment and Bundler's `:default`
+group's gem loading. In these cases, you can `require 'fast_spec_helper'`
+instead of `require 'spec_helper'` in your test file, and your test should run
+really fast since:
+
+- Gems loading is skipped
+- Rails app boot is skipped
+- gitlab-shell and Gitaly setup are skipped
+- Test repositories setup are skipped
+
+Note that in some cases, you might have to add some `require_dependency 'foo'`
+in your file under test since Rails autoloading is not available in these cases.
+
+This shouldn't be a problem since explicitely listing dependencies should be
+considered a good practice anyway.
+
### `let` variables
GitLab's RSpec suite has made extensive use of `let` variables to reduce
@@ -281,14 +300,13 @@ All fixtures should be be placed under `spec/fixtures/`.
RSpec config files are files that change the RSpec config (i.e.
`RSpec.configure do |config|` blocks). They should be placed under
-`spec/support/config/`.
+`spec/support/`.
Each file should be related to a specific domain, e.g.
-`spec/support/config/capybara.rb`, `spec/support/config/carrierwave.rb`, etc.
+`spec/support/capybara.rb`, `spec/support/carrierwave.rb`, etc.
-Helpers can be included in the `spec/support/config/rspec.rb` file. If a
-helpers module applies only to a certain kind of specs, it should add modifiers
-to the `config.include` call. For instance if
+If a helpers module applies only to a certain kind of specs, it should add
+modifiers to the `config.include` call. For instance if
`spec/support/helpers/cycle_analytics_helpers.rb` applies to `:lib` and
`type: :model` specs only, you would write the following:
@@ -299,6 +317,14 @@ RSpec.configure do |config|
end
```
+If a config file only consists of `config.include`, you can add these
+`config.include` directly in `spec/spec_helper.rb`.
+
+For very generic helpers, consider including them in the `spec/support/rspec.rb`
+file which is used by the `spec/fast_spec_helper.rb` file. See
+[Fast unit tests](#fast-unit-tests) for more details about the
+`spec/fast_spec_helper.rb` file.
+
---
[Return to Testing documentation](index.md)
diff --git a/doc/development/testing_guide/testing_rake_tasks.md b/doc/development/testing_guide/testing_rake_tasks.md
index 60163f1a230..db8ca87e9f8 100644
--- a/doc/development/testing_guide/testing_rake_tasks.md
+++ b/doc/development/testing_guide/testing_rake_tasks.md
@@ -9,7 +9,7 @@ At a minimum, requiring the Rake helper will redirect `stdout`, include the
runtime task helpers, and include the `RakeHelpers` Spec support module.
The `RakeHelpers` module exposes a `run_rake_task(<task>)` method to make
-executing tasks simple. See `spec/support/rake_helpers.rb` for all available
+executing tasks simple. See `spec/support/helpers/rake_helpers.rb` for all available
methods.
Example:
diff --git a/doc/user/project/deploy_tokens/index.md b/doc/user/project/deploy_tokens/index.md
index 86fc58020e8..34154b69d2d 100644
--- a/doc/user/project/deploy_tokens/index.md
+++ b/doc/user/project/deploy_tokens/index.md
@@ -23,7 +23,7 @@ You can create as many deploy tokens as you like from the settings of your proje
![Personal access tokens page](img/deploy_tokens.png)
-## Revoking a personal access token
+## Revoking a deploy token
At any time, you can revoke any deploy token by just clicking the
respective **Revoke** button under the 'Active deploy tokens' area.
diff --git a/features/support/env.rb b/features/support/env.rb
index 15211995918..8fa2fcb6e3e 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -12,7 +12,11 @@ end
WebMock.enable!
-%w(select2_helper test_env repo_helpers wait_for_requests sidekiq project_forks_helper webmock).each do |f|
+%w(select2_helper test_env repo_helpers wait_for_requests project_forks_helper).each do |f|
+ require Rails.root.join('spec', 'support', 'helpers', f)
+end
+
+%w(sidekiq webmock).each do |f|
require Rails.root.join('spec', 'support', f)
end
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 073471b4c4d..5139e869c71 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -154,6 +154,7 @@ module API
mount ::API::ProjectHooks
mount ::API::Projects
mount ::API::ProjectMilestones
+ mount ::API::ProjectSnapshots
mount ::API::ProjectSnippets
mount ::API::ProtectedBranches
mount ::API::Repositories
diff --git a/lib/api/helpers/notes_helpers.rb b/lib/api/helpers/notes_helpers.rb
index cd91df1ecd8..b74b8149834 100644
--- a/lib/api/helpers/notes_helpers.rb
+++ b/lib/api/helpers/notes_helpers.rb
@@ -64,8 +64,10 @@ module API
authorize! :create_note, noteable
parent = noteable_parent(noteable)
+
if opts[:created_at]
- opts.delete(:created_at) unless current_user.admin? || parent.owner == current_user
+ opts.delete(:created_at) unless
+ current_user.admin? || parent.owned_by?(current_user)
end
project = parent if parent.is_a?(Project)
diff --git a/lib/api/helpers/project_snapshots_helpers.rb b/lib/api/helpers/project_snapshots_helpers.rb
new file mode 100644
index 00000000000..94798a8cb51
--- /dev/null
+++ b/lib/api/helpers/project_snapshots_helpers.rb
@@ -0,0 +1,25 @@
+module API
+ module Helpers
+ module ProjectSnapshotsHelpers
+ def authorize_read_git_snapshot!
+ authenticated_with_full_private_access!
+ end
+
+ def send_git_snapshot(repository)
+ header(*Gitlab::Workhorse.send_git_snapshot(repository))
+ end
+
+ def snapshot_project
+ user_project
+ end
+
+ def snapshot_repository
+ if to_boolean(params[:wiki])
+ snapshot_project.wiki.repository
+ else
+ snapshot_project.repository
+ end
+ end
+ end
+ end
+end
diff --git a/lib/api/project_snapshots.rb b/lib/api/project_snapshots.rb
new file mode 100644
index 00000000000..71005acc587
--- /dev/null
+++ b/lib/api/project_snapshots.rb
@@ -0,0 +1,19 @@
+module API
+ class ProjectSnapshots < Grape::API
+ helpers ::API::Helpers::ProjectSnapshotsHelpers
+
+ before { authorize_read_git_snapshot! }
+
+ resource :projects do
+ desc 'Download a (possibly inconsistent) snapshot of a repository' do
+ detail 'This feature was introduced in GitLab 10.7'
+ end
+ params do
+ optional :wiki, type: Boolean, desc: 'Set to true to receive the wiki repository'
+ end
+ get ':id/snapshot' do
+ send_git_snapshot(snapshot_repository)
+ end
+ end
+ end
+end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index 51b3b0459f3..8871792060b 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -74,6 +74,11 @@ module API
present options[:with].prepare_relation(projects, options), options
end
+
+ def translate_params_for_compatibility(params)
+ params[:builds_enabled] = params.delete(:jobs_enabled) if params.key?(:jobs_enabled)
+ params
+ end
end
resource :users, requirements: API::PROJECT_ENDPOINT_REQUIREMENTS do
@@ -123,7 +128,7 @@ module API
end
post do
attrs = declared_params(include_missing: false)
- attrs[:builds_enabled] = attrs.delete(:jobs_enabled) if attrs.key?(:jobs_enabled)
+ attrs = translate_params_for_compatibility(attrs)
project = ::Projects::CreateService.new(current_user, attrs).execute
if project.saved?
@@ -155,6 +160,7 @@ module API
not_found!('User') unless user
attrs = declared_params(include_missing: false)
+ attrs = translate_params_for_compatibility(attrs)
project = ::Projects::CreateService.new(user, attrs).execute
if project.saved?
@@ -276,7 +282,7 @@ module API
authorize! :rename_project, user_project if attrs[:name].present?
authorize! :change_visibility_level, user_project if attrs[:visibility].present?
- attrs[:builds_enabled] = attrs.delete(:jobs_enabled) if attrs.key?(:jobs_enabled)
+ attrs = translate_params_for_compatibility(attrs)
result = ::Projects::UpdateService.new(user_project, current_user, attrs).execute
diff --git a/lib/api/users.rb b/lib/api/users.rb
index 3920171205f..14b8a796c8e 100644
--- a/lib/api/users.rb
+++ b/lib/api/users.rb
@@ -77,7 +77,7 @@ module API
authenticated_as_admin! if params[:external].present? || (params[:extern_uid].present? && params[:provider].present?)
unless current_user&.admin?
- params.except!(:created_after, :created_before, :order_by, :sort)
+ params.except!(:created_after, :created_before, :order_by, :sort, :two_factor)
end
users = UsersFinder.new(current_user, params).execute
diff --git a/lib/gitlab.rb b/lib/gitlab.rb
index f6629982512..0a167104bf4 100644
--- a/lib/gitlab.rb
+++ b/lib/gitlab.rb
@@ -1,9 +1,20 @@
-require_dependency 'gitlab/git'
+require_dependency 'settings'
+require_dependency 'gitlab/popen'
module Gitlab
+ def self.root
+ Pathname.new(File.expand_path('..', __dir__))
+ end
+
+ def self.config
+ Settings
+ end
+
COM_URL = 'https://gitlab.com'.freeze
APP_DIRS_PATTERN = %r{^/?(app|config|ee|lib|spec|\(\w*\))}
SUBDOMAIN_REGEX = %r{\Ahttps://[a-z0-9]+\.gitlab\.com\z}
+ VERSION = File.read(root.join("VERSION")).strip.freeze
+ REVISION = Gitlab::Popen.popen(%W(#{config.git.bin_path} log --pretty=format:%h -n 1)).first.chomp.freeze
def self.com?
# Check `gl_subdomain?` as well to keep parity with gitlab.com
diff --git a/lib/gitlab/git.rb b/lib/gitlab/git.rb
index c9abea90d21..e85e87a54af 100644
--- a/lib/gitlab/git.rb
+++ b/lib/gitlab/git.rb
@@ -1,3 +1,5 @@
+require_dependency 'gitlab/encoding_helper'
+
module Gitlab
module Git
# The ID of empty tree.
diff --git a/lib/gitlab/wiki/committer_with_hooks.rb b/lib/gitlab/git/committer_with_hooks.rb
index 19f0b3814fd..a8a59f998cd 100644
--- a/lib/gitlab/wiki/committer_with_hooks.rb
+++ b/lib/gitlab/git/committer_with_hooks.rb
@@ -1,5 +1,5 @@
module Gitlab
- module Wiki
+ module Git
class CommitterWithHooks < Gollum::Committer
attr_reader :gl_wiki
@@ -9,6 +9,9 @@ module Gitlab
end
def commit
+ # TODO: Remove after 10.8
+ return super unless allowed_to_run_hooks?
+
result = Gitlab::Git::OperationService.new(git_user, gl_wiki.repository).with_branch(
@wiki.ref,
start_branch_name: @wiki.ref
@@ -24,6 +27,11 @@ module Gitlab
private
+ # TODO: Remove after 10.8
+ def allowed_to_run_hooks?
+ @options[:user_id] != 0 && @options[:username].present?
+ end
+
def git_user
@git_user ||= Gitlab::Git::User.new(@options[:username],
@options[:name],
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 3124c426f97..5a6e2e0b937 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -1258,6 +1258,10 @@ module Gitlab
true
end
+ def create_from_snapshot(url, auth)
+ gitaly_repository_client.create_from_snapshot(url, auth)
+ end
+
def rebase(user, rebase_id, branch:, branch_sha:, remote_repository:, remote_branch:)
gitaly_migrate(:rebase) do |is_enabled|
if is_enabled
diff --git a/lib/gitlab/git/wiki.rb b/lib/gitlab/git/wiki.rb
index 821436911ab..84a26fe4a6f 100644
--- a/lib/gitlab/git/wiki.rb
+++ b/lib/gitlab/git/wiki.rb
@@ -290,7 +290,7 @@ module Gitlab
end
def committer_with_hooks(commit_details)
- Gitlab::Wiki::CommitterWithHooks.new(self, commit_details.to_h)
+ Gitlab::Git::CommitterWithHooks.new(self, commit_details.to_h)
end
def with_committer_with_hooks(commit_details, &block)
diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb
index 39057beefba..bf5a491e28d 100644
--- a/lib/gitlab/gitaly_client/repository_service.rb
+++ b/lib/gitlab/gitaly_client/repository_service.rb
@@ -235,6 +235,22 @@ module Gitlab
)
end
+ def create_from_snapshot(http_url, http_auth)
+ request = Gitaly::CreateRepositoryFromSnapshotRequest.new(
+ repository: @gitaly_repo,
+ http_url: http_url,
+ http_auth: http_auth
+ )
+
+ GitalyClient.call(
+ @storage,
+ :repository_service,
+ :create_repository_from_snapshot,
+ request,
+ timeout: GitalyClient.default_timeout
+ )
+ end
+
def write_ref(ref_path, ref, old_ref, shell)
request = Gitaly::WriteRefRequest.new(
repository: @gitaly_repo,
diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml
index cd840bd5b01..ec91c02dbe7 100644
--- a/lib/gitlab/import_export/import_export.yml
+++ b/lib/gitlab/import_export/import_export.yml
@@ -27,8 +27,6 @@ project_tree:
- :releases
- project_members:
- :user
- - lfs_file_locks:
- - :user
- merge_requests:
- notes:
- :author
diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb
index 153cb2a8bb1..1f060de657d 100644
--- a/lib/gitlab/workhorse.rb
+++ b/lib/gitlab/workhorse.rb
@@ -81,6 +81,20 @@ module Gitlab
]
end
+ def send_git_snapshot(repository)
+ params = {
+ 'GitalyServer' => gitaly_server_hash(repository),
+ 'GetSnapshotRequest' => Gitaly::GetSnapshotRequest.new(
+ repository: repository.gitaly_repository
+ ).to_json
+ }
+
+ [
+ SEND_DATA_HEADER,
+ "git-snapshot:#{encode(params)}"
+ ]
+ end
+
def send_git_diff(repository, diff_refs)
params = if Gitlab::GitalyClient.feature_enabled?(:workhorse_send_git_diff, status: Gitlab::GitalyClient::MigrationStatus::OPT_OUT)
{
diff --git a/lib/settings.rb b/lib/settings.rb
new file mode 100644
index 00000000000..69d637761ea
--- /dev/null
+++ b/lib/settings.rb
@@ -0,0 +1,126 @@
+require 'settingslogic'
+
+class Settings < Settingslogic
+ source ENV.fetch('GITLAB_CONFIG') { Pathname.new(File.expand_path('..', __dir__)).join('config/gitlab.yml') }
+ namespace ENV.fetch('GITLAB_ENV') { Rails.env }
+
+ class << self
+ def gitlab_on_standard_port?
+ on_standard_port?(gitlab)
+ end
+
+ def host_without_www(url)
+ host(url).sub('www.', '')
+ end
+
+ def build_gitlab_ci_url
+ custom_port =
+ if on_standard_port?(gitlab)
+ nil
+ else
+ ":#{gitlab.port}"
+ end
+
+ [
+ gitlab.protocol,
+ "://",
+ gitlab.host,
+ custom_port,
+ gitlab.relative_url_root
+ ].join('')
+ end
+
+ def build_pages_url
+ base_url(pages).join('')
+ end
+
+ def build_gitlab_shell_ssh_path_prefix
+ user_host = "#{gitlab_shell.ssh_user}@#{gitlab_shell.ssh_host}"
+
+ if gitlab_shell.ssh_port != 22
+ "ssh://#{user_host}:#{gitlab_shell.ssh_port}/"
+ else
+ if gitlab_shell.ssh_host.include? ':'
+ "[#{user_host}]:"
+ else
+ "#{user_host}:"
+ end
+ end
+ end
+
+ def build_base_gitlab_url
+ base_url(gitlab).join('')
+ end
+
+ def build_gitlab_url
+ (base_url(gitlab) + [gitlab.relative_url_root]).join('')
+ end
+
+ # check that values in `current` (string or integer) is a contant in `modul`.
+ def verify_constant_array(modul, current, default)
+ values = default || []
+ unless current.nil?
+ values = []
+ current.each do |constant|
+ values.push(verify_constant(modul, constant, nil))
+ end
+ values.delete_if { |value| value.nil? }
+ end
+
+ values
+ end
+
+ # check that `current` (string or integer) is a contant in `modul`.
+ def verify_constant(modul, current, default)
+ constant = modul.constants.find { |name| modul.const_get(name) == current }
+ value = constant.nil? ? default : modul.const_get(constant)
+ if current.is_a? String
+ value = modul.const_get(current.upcase) rescue default
+ end
+
+ value
+ end
+
+ def absolute(path)
+ File.expand_path(path, Rails.root)
+ end
+
+ private
+
+ def base_url(config)
+ custom_port = on_standard_port?(config) ? nil : ":#{config.port}"
+
+ [
+ config.protocol,
+ "://",
+ config.host,
+ custom_port
+ ]
+ end
+
+ def on_standard_port?(config)
+ config.port.to_i == (config.https ? 443 : 80)
+ end
+
+ # Extract the host part of the given +url+.
+ def host(url)
+ url = url.downcase
+ url = "http://#{url}" unless url.start_with?('http')
+
+ # Get rid of the path so that we don't even have to encode it
+ url_without_path = url.sub(%r{(https?://[^/]+)/?.*}, '\1')
+
+ URI.parse(url_without_path).host
+ end
+
+ # Runs every minute in a random ten-minute period on Sundays, to balance the
+ # load on the server receiving these pings. The usage ping is safe to run
+ # multiple times because of a 24 hour exclusive lock.
+ def cron_for_usage_ping
+ hour = rand(24)
+ minute = rand(6)
+
+ "#{minute}0-#{minute}9 #{hour} * * 0"
+ end
+ end
+end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 0eec9793391..cd30783c274 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -1776,6 +1776,9 @@ msgstr ""
msgid "Failed to change the owner"
msgstr ""
+msgid "Failed to check related branches."
+msgstr ""
+
msgid "Failed to remove issue from board, please try again."
msgstr ""
diff --git a/rubocop/spec_helpers.rb b/rubocop/spec_helpers.rb
index 6c0f0193b1a..9bf5f1e3b18 100644
--- a/rubocop/spec_helpers.rb
+++ b/rubocop/spec_helpers.rb
@@ -1,6 +1,6 @@
module RuboCop
module SpecHelpers
- SPEC_HELPERS = %w[spec_helper.rb rails_helper.rb].freeze
+ SPEC_HELPERS = %w[fast_spec_helper.rb rails_helper.rb spec_helper.rb].freeze
# Returns true if the given node originated from the spec directory.
def in_spec?(node)
diff --git a/spec/controllers/import/bitbucket_controller_spec.rb b/spec/controllers/import/bitbucket_controller_spec.rb
index 2be46049aab..be49b92d23f 100644
--- a/spec/controllers/import/bitbucket_controller_spec.rb
+++ b/spec/controllers/import/bitbucket_controller_spec.rb
@@ -223,11 +223,12 @@ describe Import::BitbucketController do
end
context 'user has chosen an existing nested namespace and name for the project', :postgresql do
- let(:parent_namespace) { create(:group, name: 'foo', owner: user) }
+ let(:parent_namespace) { create(:group, name: 'foo') }
let(:nested_namespace) { create(:group, name: 'bar', parent: parent_namespace) }
let(:test_name) { 'test_name' }
before do
+ parent_namespace.add_owner(user)
nested_namespace.add_owner(user)
end
@@ -273,7 +274,7 @@ describe Import::BitbucketController do
context 'user has chosen existent and non-existent nested namespaces and name for the project', :postgresql do
let(:test_name) { 'test_name' }
- let!(:parent_namespace) { create(:group, name: 'foo', owner: user) }
+ let!(:parent_namespace) { create(:group, name: 'foo') }
before do
parent_namespace.add_owner(user)
diff --git a/spec/controllers/import/gitlab_controller_spec.rb b/spec/controllers/import/gitlab_controller_spec.rb
index e958be077c2..742f4787126 100644
--- a/spec/controllers/import/gitlab_controller_spec.rb
+++ b/spec/controllers/import/gitlab_controller_spec.rb
@@ -196,10 +196,11 @@ describe Import::GitlabController do
end
context 'user has chosen an existing nested namespace for the project', :postgresql do
- let(:parent_namespace) { create(:group, name: 'foo', owner: user) }
+ let(:parent_namespace) { create(:group, name: 'foo') }
let(:nested_namespace) { create(:group, name: 'bar', parent: parent_namespace) }
before do
+ parent_namespace.add_owner(user)
nested_namespace.add_owner(user)
end
@@ -245,7 +246,7 @@ describe Import::GitlabController do
context 'user has chosen existent and non-existent nested namespaces and name for the project', :postgresql do
let(:test_name) { 'test_name' }
- let!(:parent_namespace) { create(:group, name: 'foo', owner: user) }
+ let!(:parent_namespace) { create(:group, name: 'foo') }
before do
parent_namespace.add_owner(user)
diff --git a/spec/controllers/projects/forks_controller_spec.rb b/spec/controllers/projects/forks_controller_spec.rb
index c4b32dc3a09..e20623c0ac1 100644
--- a/spec/controllers/projects/forks_controller_spec.rb
+++ b/spec/controllers/projects/forks_controller_spec.rb
@@ -4,7 +4,11 @@ describe Projects::ForksController do
let(:user) { create(:user) }
let(:project) { create(:project, :public, :repository) }
let(:forked_project) { Projects::ForkService.new(project, user).execute }
- let(:group) { create(:group, owner: forked_project.creator) }
+ let(:group) { create(:group) }
+
+ before do
+ group.add_owner(user)
+ end
describe 'GET index' do
def get_forks
diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb
index f677cec3408..b9a979044fe 100644
--- a/spec/controllers/projects/jobs_controller_spec.rb
+++ b/spec/controllers/projects/jobs_controller_spec.rb
@@ -190,10 +190,7 @@ describe Projects::JobsController do
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['id']).to eq job.id
expect(json_response['status']).to eq job.status
- end
-
- it 'returns no job log message' do
- expect(json_response['html']).to eq('No job log')
+ expect(json_response['html']).to be_nil
end
end
diff --git a/spec/factories/commits.rb b/spec/factories/commits.rb
index d5d819d862a..818f7b046f6 100644
--- a/spec/factories/commits.rb
+++ b/spec/factories/commits.rb
@@ -1,4 +1,4 @@
-require_relative '../support/repo_helpers'
+require_relative '../support/helpers/repo_helpers'
FactoryBot.define do
factory :commit do
diff --git a/spec/factories/gpg_key_subkeys.rb b/spec/factories/gpg_key_subkeys.rb
index 57eaaee345f..6c7db5379a9 100644
--- a/spec/factories/gpg_key_subkeys.rb
+++ b/spec/factories/gpg_key_subkeys.rb
@@ -1,5 +1,3 @@
-require_relative '../support/gpg_helpers'
-
FactoryBot.define do
factory :gpg_key_subkey do
gpg_key
diff --git a/spec/factories/gpg_keys.rb b/spec/factories/gpg_keys.rb
index b8aabf74221..51b8ddc9934 100644
--- a/spec/factories/gpg_keys.rb
+++ b/spec/factories/gpg_keys.rb
@@ -1,4 +1,4 @@
-require_relative '../support/gpg_helpers'
+require_relative '../support/helpers/gpg_helpers'
FactoryBot.define do
factory :gpg_key do
diff --git a/spec/factories/gpg_signature.rb b/spec/factories/gpg_signature.rb
index 4620caff823..b89e6ffc4b3 100644
--- a/spec/factories/gpg_signature.rb
+++ b/spec/factories/gpg_signature.rb
@@ -1,5 +1,3 @@
-require_relative '../support/gpg_helpers'
-
FactoryBot.define do
factory :gpg_signature do
commit_sha { Digest::SHA1.hexdigest(SecureRandom.hex) }
diff --git a/spec/factories/groups.rb b/spec/factories/groups.rb
index 8c531cf5909..3b354c0d96b 100644
--- a/spec/factories/groups.rb
+++ b/spec/factories/groups.rb
@@ -5,6 +5,14 @@ FactoryBot.define do
type 'Group'
owner nil
+ after(:create) do |group|
+ if group.owner
+ # We could remove this after we have proper constraint:
+ # https://gitlab.com/gitlab-org/gitlab-ce/issues/43292
+ raise "Don't set owner for groups, use `group.add_owner(user)` instead"
+ end
+ end
+
trait :public do
visibility_level Gitlab::VisibilityLevel::PUBLIC
end
diff --git a/spec/factories/namespaces.rb b/spec/factories/namespaces.rb
index f94b09cff15..6feafa5ece9 100644
--- a/spec/factories/namespaces.rb
+++ b/spec/factories/namespaces.rb
@@ -2,6 +2,22 @@ FactoryBot.define do
factory :namespace do
sequence(:name) { |n| "namespace#{n}" }
path { name.downcase.gsub(/\s/, '_') }
- owner
+
+ # This is a workaround to avoid the user creating another namespace via
+ # User#ensure_namespace_correct. We should try to remove it and then
+ # we could remove this workaround
+ association :owner, factory: :user, strategy: :build
+ before(:create) do |namespace|
+ owner = namespace.owner
+
+ if owner
+ # We're changing the username here because we want to keep our path,
+ # and User#ensure_namespace_correct would change the path based on
+ # username, so we're forced to do this otherwise we'll need to change
+ # a lot of existing tests.
+ owner.username = namespace.path
+ owner.namespace = namespace
+ end
+ end
end
end
diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb
index 857333f222d..40f3fa7d69b 100644
--- a/spec/factories/notes.rb
+++ b/spec/factories/notes.rb
@@ -1,4 +1,4 @@
-require_relative '../support/repo_helpers'
+require_relative '../support/helpers/repo_helpers'
include ActionDispatch::TestProcess
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 1761b6e2a3b..1ae6152a1f0 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -1,4 +1,4 @@
-require_relative '../support/test_env'
+require_relative '../support/helpers/test_env'
FactoryBot.define do
# Project without repository
diff --git a/spec/fast_spec_helper.rb b/spec/fast_spec_helper.rb
new file mode 100644
index 00000000000..f28268b0754
--- /dev/null
+++ b/spec/fast_spec_helper.rb
@@ -0,0 +1,15 @@
+require 'bundler/setup'
+
+ENV['GITLAB_ENV'] = 'test'
+ENV['IN_MEMORY_APPLICATION_SETTINGS'] = 'true'
+
+unless Object.respond_to?(:require_dependency)
+ class Object
+ alias_method :require_dependency, :require
+ end
+end
+
+# Defines Gitlab and Gitlab.config which are at the center of the app
+require_relative '../lib/gitlab' unless defined?(Gitlab.config)
+
+require_relative 'support/rspec'
diff --git a/spec/features/projects/jobs/user_browses_jobs_spec.rb b/spec/features/projects/jobs/user_browses_jobs_spec.rb
index 36ebbeadd4a..786ec327b92 100644
--- a/spec/features/projects/jobs/user_browses_jobs_spec.rb
+++ b/spec/features/projects/jobs/user_browses_jobs_spec.rb
@@ -26,7 +26,7 @@ describe 'User browses jobs' do
page.within('.nav-controls') do
ci_lint_tool_link = page.find_link('CI lint')
- expect(ci_lint_tool_link[:href]).to end_with(ci_lint_path)
+ expect(ci_lint_tool_link[:href]).to end_with(project_ci_lint_path(project))
end
end
diff --git a/spec/features/projects/new_project_spec.rb b/spec/features/projects/new_project_spec.rb
index a5954fec54b..fee6287558e 100644
--- a/spec/features/projects/new_project_spec.rb
+++ b/spec/features/projects/new_project_spec.rb
@@ -64,7 +64,7 @@ feature 'New project' do
end
context 'with group namespace' do
- let(:group) { create(:group, :private, owner: user) }
+ let(:group) { create(:group, :private) }
before do
group.add_owner(user)
@@ -81,7 +81,7 @@ feature 'New project' do
end
context 'with subgroup namespace' do
- let(:group) { create(:group, owner: user) }
+ let(:group) { create(:group) }
let(:subgroup) { create(:group, parent: group) }
before do
diff --git a/spec/features/projects/settings/pipelines_settings_spec.rb b/spec/features/projects/settings/pipelines_settings_spec.rb
index d9020333f28..e875a88a52b 100644
--- a/spec/features/projects/settings/pipelines_settings_spec.rb
+++ b/spec/features/projects/settings/pipelines_settings_spec.rb
@@ -8,6 +8,7 @@ describe "Projects > Settings > Pipelines settings" do
before do
sign_in(user)
project.add_role(user, role)
+ create(:project_auto_devops, project: project)
end
context 'for developer' do
@@ -27,10 +28,17 @@ describe "Projects > Settings > Pipelines settings" do
visit project_settings_ci_cd_path(project)
fill_in('Test coverage parsing', with: 'coverage_regex')
- click_on 'Save changes'
+
+ page.within '#js-general-pipeline-settings' do
+ click_on 'Save changes'
+ end
expect(page.status_code).to eq(200)
- expect(page).to have_button('Save changes', disabled: false)
+
+ page.within '#js-general-pipeline-settings' do
+ expect(page).to have_button('Save changes', disabled: false)
+ end
+
expect(page).to have_field('Test coverage parsing', with: 'coverage_regex')
end
@@ -38,10 +46,15 @@ describe "Projects > Settings > Pipelines settings" do
visit project_settings_ci_cd_path(project)
page.check('Auto-cancel redundant, pending pipelines')
- click_on 'Save changes'
+ page.within '#js-general-pipeline-settings' do
+ click_on 'Save changes'
+ end
expect(page.status_code).to eq(200)
- expect(page).to have_button('Save changes', disabled: false)
+
+ page.within '#js-general-pipeline-settings' do
+ expect(page).to have_button('Save changes', disabled: false)
+ end
checkbox = find_field('project_auto_cancel_pending_pipelines')
expect(checkbox).to be_checked
@@ -51,13 +64,16 @@ describe "Projects > Settings > Pipelines settings" do
it 'update auto devops settings' do
visit project_settings_ci_cd_path(project)
- fill_in('project_auto_devops_attributes_domain', with: 'test.com')
- page.choose('project_auto_devops_attributes_enabled_false')
- click_on 'Save changes'
+ page.within '#autodevops-settings' do
+ fill_in('project_auto_devops_attributes_domain', with: 'test.com')
+ page.choose('project_auto_devops_attributes_enabled_false')
+ click_on 'Save changes'
+ end
expect(page.status_code).to eq(200)
expect(project.auto_devops).to be_present
expect(project.auto_devops).not_to be_enabled
+ expect(project.auto_devops.domain).to eq('test.com')
end
end
end
diff --git a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
index a906fa20233..e44361fbe26 100644
--- a/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
+++ b/spec/features/projects/show/user_sees_setup_shortcut_buttons_spec.rb
@@ -65,7 +65,7 @@ describe 'Projects > Show > User sees setup shortcut buttons' do
describe 'Auto DevOps button' do
it '"Enable Auto DevOps" button linked to settings page' do
page.within('.project-stats') do
- expect(page).to have_link('Enable Auto DevOps', href: project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings'))
+ expect(page).to have_link('Enable Auto DevOps', href: project_settings_ci_cd_path(project, anchor: 'autodevops-settings'))
end
end
@@ -75,7 +75,7 @@ describe 'Projects > Show > User sees setup shortcut buttons' do
visit project_path(project)
page.within('.project-stats') do
- expect(page).to have_link('Auto DevOps enabled', href: project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings'))
+ expect(page).to have_link('Auto DevOps enabled', href: project_settings_ci_cd_path(project, anchor: 'autodevops-settings'))
end
end
end
@@ -212,7 +212,7 @@ describe 'Projects > Show > User sees setup shortcut buttons' do
describe 'Auto DevOps button' do
it '"Enable Auto DevOps" button linked to settings page' do
page.within('.project-stats') do
- expect(page).to have_link('Enable Auto DevOps', href: project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings'))
+ expect(page).to have_link('Enable Auto DevOps', href: project_settings_ci_cd_path(project, anchor: 'autodevops-settings'))
end
end
@@ -222,7 +222,7 @@ describe 'Projects > Show > User sees setup shortcut buttons' do
visit project_path(project)
page.within('.project-stats') do
- expect(page).to have_link('Auto DevOps enabled', href: project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings'))
+ expect(page).to have_link('Auto DevOps enabled', href: project_settings_ci_cd_path(project, anchor: 'autodevops-settings'))
end
end
diff --git a/spec/javascripts/issue_spec.js b/spec/javascripts/issue_spec.js
index f37426a72d4..047ecab27db 100644
--- a/spec/javascripts/issue_spec.js
+++ b/spec/javascripts/issue_spec.js
@@ -92,6 +92,7 @@ describe('Issue', function() {
function mockCanCreateBranch(canCreateBranch) {
mock.onGet(/(.*)\/can_create_branch$/).reply(200, {
can_create_branch: canCreateBranch,
+ suggested_branch_name: 'foo-99',
});
}
diff --git a/spec/javascripts/pipelines/graph/action_component_spec.js b/spec/javascripts/pipelines/graph/action_component_spec.js
index 581209f215d..3de10392472 100644
--- a/spec/javascripts/pipelines/graph/action_component_spec.js
+++ b/spec/javascripts/pipelines/graph/action_component_spec.js
@@ -6,7 +6,7 @@ import mountComponent from '../../helpers/vue_mount_component_helper';
describe('pipeline graph action component', () => {
let component;
- beforeEach((done) => {
+ beforeEach(done => {
const ActionComponent = Vue.extend(actionComponent);
component = mountComponent(ActionComponent, {
tooltipText: 'bar',
@@ -22,7 +22,7 @@ describe('pipeline graph action component', () => {
});
it('should emit an event with the provided link', () => {
- eventHub.$on('graphAction', (link) => {
+ eventHub.$on('graphAction', link => {
expect(link).toEqual('foo');
});
});
@@ -31,7 +31,7 @@ describe('pipeline graph action component', () => {
expect(component.$el.getAttribute('data-original-title')).toEqual('bar');
});
- it('should update bootstrap tooltip when title changes', (done) => {
+ it('should update bootstrap tooltip when title changes', done => {
component.tooltipText = 'changed';
setTimeout(() => {
@@ -44,4 +44,45 @@ describe('pipeline graph action component', () => {
expect(component.$el.querySelector('.ci-action-icon-wrapper')).toBeDefined();
expect(component.$el.querySelector('svg')).toBeDefined();
});
+
+ it('disables the button when clicked', done => {
+ component.$el.click();
+
+ component.$nextTick(() => {
+ expect(component.$el.getAttribute('disabled')).toEqual('disabled');
+ done();
+ });
+ });
+
+ it('re-enabled the button when `requestFinishedFor` matches `linkRequested`', done => {
+ component.$el.click();
+
+ component
+ .$nextTick()
+ .then(() => {
+ expect(component.$el.getAttribute('disabled')).toEqual('disabled');
+ component.requestFinishedFor = 'foo';
+ })
+ .then(() => {
+ expect(component.$el.getAttribute('disabled')).toBeNull();
+ })
+ .then(done)
+ .catch(done.fail);
+ });
+
+ it('does not re-enable the button when `requestFinishedFor` does not matches `linkRequested`', done => {
+ component.$el.click();
+
+ component
+ .$nextTick()
+ .then(() => {
+ expect(component.$el.getAttribute('disabled')).toEqual('disabled');
+ component.requestFinishedFor = 'bar';
+ })
+ .then(() => {
+ expect(component.$el.getAttribute('disabled')).toEqual('disabled');
+ })
+ .then(done)
+ .catch(done.fail);
+ });
});
diff --git a/spec/javascripts/pipelines/graph/dropdown_action_component_spec.js b/spec/javascripts/pipelines/graph/dropdown_action_component_spec.js
deleted file mode 100644
index ba721bc53c6..00000000000
--- a/spec/javascripts/pipelines/graph/dropdown_action_component_spec.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import Vue from 'vue';
-import dropdownActionComponent from '~/pipelines/components/graph/dropdown_action_component.vue';
-
-describe('action component', () => {
- let component;
-
- beforeEach((done) => {
- const DropdownActionComponent = Vue.extend(dropdownActionComponent);
- component = new DropdownActionComponent({
- propsData: {
- tooltipText: 'bar',
- link: 'foo',
- actionMethod: 'post',
- actionIcon: 'cancel',
- },
- }).$mount();
-
- Vue.nextTick(done);
- });
-
- it('should render a link', () => {
- expect(component.$el.getAttribute('href')).toEqual('foo');
- });
-
- it('should render the provided title as a bootstrap tooltip', () => {
- expect(component.$el.getAttribute('data-original-title')).toEqual('bar');
- });
-
- it('should render an svg', () => {
- expect(component.$el.querySelector('svg')).toBeDefined();
- });
-});
diff --git a/spec/javascripts/pipelines/graph/job_component_spec.js b/spec/javascripts/pipelines/graph/job_component_spec.js
index c9677ae209a..073dae56c25 100644
--- a/spec/javascripts/pipelines/graph/job_component_spec.js
+++ b/spec/javascripts/pipelines/graph/job_component_spec.js
@@ -93,17 +93,6 @@ describe('pipeline graph job component', () => {
});
});
- describe('dropdown', () => {
- it('should render the dropdown action icon', () => {
- component = mountComponent(JobComponent, {
- job: mockJob,
- isDropdown: true,
- });
-
- expect(component.$el.querySelector('a.ci-action-icon-wrapper')).toBeDefined();
- });
- });
-
it('should render provided class name', () => {
component = mountComponent(JobComponent, {
job: mockJob,
diff --git a/spec/javascripts/settings_panels_spec.js b/spec/javascripts/settings_panels_spec.js
index d433f8c3e07..4fba36bd4de 100644
--- a/spec/javascripts/settings_panels_spec.js
+++ b/spec/javascripts/settings_panels_spec.js
@@ -13,9 +13,9 @@ describe('Settings Panels', () => {
});
it('should expand linked hash fragment panel', () => {
- location.hash = '#js-general-pipeline-settings';
+ location.hash = '#autodevops-settings';
- const pipelineSettingsPanel = document.querySelector('#js-general-pipeline-settings');
+ const pipelineSettingsPanel = document.querySelector('#autodevops-settings');
// Our test environment automatically expands everything so we need to clear that out first
pipelineSettingsPanel.classList.remove('expanded');
diff --git a/spec/javascripts/vue_shared/components/ci_icon_spec.js b/spec/javascripts/vue_shared/components/ci_icon_spec.js
index d8664408595..423bc746a22 100644
--- a/spec/javascripts/vue_shared/components/ci_icon_spec.js
+++ b/spec/javascripts/vue_shared/components/ci_icon_spec.js
@@ -1,139 +1,122 @@
import Vue from 'vue';
import ciIcon from '~/vue_shared/components/ci_icon.vue';
+import mountComponent from 'spec/helpers/vue_mount_component_helper';
describe('CI Icon component', () => {
- let CiIcon;
- beforeEach(() => {
- CiIcon = Vue.extend(ciIcon);
+ const Component = Vue.extend(ciIcon);
+ let vm;
+
+ afterEach(() => {
+ vm.$destroy();
});
it('should render a span element with an svg', () => {
- const component = new CiIcon({
- propsData: {
- status: {
- icon: 'icon_status_success',
- },
+ vm = mountComponent(Component, {
+ status: {
+ icon: 'icon_status_success',
},
- }).$mount();
+ });
- expect(component.$el.tagName).toEqual('SPAN');
- expect(component.$el.querySelector('span > svg')).toBeDefined();
+ expect(vm.$el.tagName).toEqual('SPAN');
+ expect(vm.$el.querySelector('span > svg')).toBeDefined();
});
it('should render a success status', () => {
- const component = new CiIcon({
- propsData: {
- status: {
- icon: 'icon_status_success',
- group: 'success',
- },
+ vm = mountComponent(Component, {
+ status: {
+ icon: 'icon_status_success',
+ group: 'success',
},
- }).$mount();
+ });
- expect(component.$el.classList.contains('ci-status-icon-success')).toEqual(true);
+ expect(vm.$el.classList.contains('ci-status-icon-success')).toEqual(true);
});
it('should render a failed status', () => {
- const component = new CiIcon({
- propsData: {
- status: {
- icon: 'icon_status_failed',
- group: 'failed',
- },
+ vm = mountComponent(Component, {
+ status: {
+ icon: 'icon_status_failed',
+ group: 'failed',
},
- }).$mount();
+ });
- expect(component.$el.classList.contains('ci-status-icon-failed')).toEqual(true);
+ expect(vm.$el.classList.contains('ci-status-icon-failed')).toEqual(true);
});
it('should render success with warnings status', () => {
- const component = new CiIcon({
- propsData: {
- status: {
- icon: 'icon_status_warning',
- group: 'warning',
- },
+ vm = mountComponent(Component, {
+ status: {
+ icon: 'icon_status_warning',
+ group: 'warning',
},
- }).$mount();
+ });
- expect(component.$el.classList.contains('ci-status-icon-warning')).toEqual(true);
+ expect(vm.$el.classList.contains('ci-status-icon-warning')).toEqual(true);
});
it('should render pending status', () => {
- const component = new CiIcon({
- propsData: {
- status: {
- icon: 'icon_status_pending',
- group: 'pending',
- },
+ vm = mountComponent(Component, {
+ status: {
+ icon: 'icon_status_pending',
+ group: 'pending',
},
- }).$mount();
+ });
- expect(component.$el.classList.contains('ci-status-icon-pending')).toEqual(true);
+ expect(vm.$el.classList.contains('ci-status-icon-pending')).toEqual(true);
});
it('should render running status', () => {
- const component = new CiIcon({
- propsData: {
- status: {
- icon: 'icon_status_running',
- group: 'running',
- },
+ vm = mountComponent(Component, {
+ status: {
+ icon: 'icon_status_running',
+ group: 'running',
},
- }).$mount();
+ });
- expect(component.$el.classList.contains('ci-status-icon-running')).toEqual(true);
+ expect(vm.$el.classList.contains('ci-status-icon-running')).toEqual(true);
});
it('should render created status', () => {
- const component = new CiIcon({
- propsData: {
- status: {
- icon: 'icon_status_created',
- group: 'created',
- },
+ vm = mountComponent(Component, {
+ status: {
+ icon: 'icon_status_created',
+ group: 'created',
},
- }).$mount();
+ });
- expect(component.$el.classList.contains('ci-status-icon-created')).toEqual(true);
+ expect(vm.$el.classList.contains('ci-status-icon-created')).toEqual(true);
});
it('should render skipped status', () => {
- const component = new CiIcon({
- propsData: {
- status: {
- icon: 'icon_status_skipped',
- group: 'skipped',
- },
+ vm = mountComponent(Component, {
+ status: {
+ icon: 'icon_status_skipped',
+ group: 'skipped',
},
- }).$mount();
+ });
- expect(component.$el.classList.contains('ci-status-icon-skipped')).toEqual(true);
+ expect(vm.$el.classList.contains('ci-status-icon-skipped')).toEqual(true);
});
it('should render canceled status', () => {
- const component = new CiIcon({
- propsData: {
- status: {
- icon: 'icon_status_canceled',
- group: 'canceled',
- },
+ vm = mountComponent(Component, {
+ status: {
+ icon: 'icon_status_canceled',
+ group: 'canceled',
},
- }).$mount();
+ });
- expect(component.$el.classList.contains('ci-status-icon-canceled')).toEqual(true);
+ expect(vm.$el.classList.contains('ci-status-icon-canceled')).toEqual(true);
});
it('should render status for manual action', () => {
- const component = new CiIcon({
- propsData: {
- status: {
- icon: 'icon_status_manual',
- group: 'manual',
- },
+ vm = mountComponent(Component, {
+ status: {
+ icon: 'icon_status_manual',
+ group: 'manual',
},
- }).$mount();
+ });
- expect(component.$el.classList.contains('ci-status-icon-manual')).toEqual(true);
+ expect(vm.$el.classList.contains('ci-status-icon-manual')).toEqual(true);
});
});
diff --git a/spec/javascripts/vue_shared/components/clipboard_button_spec.js b/spec/javascripts/vue_shared/components/clipboard_button_spec.js
index f598b1afa74..97f0fbb04db 100644
--- a/spec/javascripts/vue_shared/components/clipboard_button_spec.js
+++ b/spec/javascripts/vue_shared/components/clipboard_button_spec.js
@@ -3,10 +3,10 @@ import clipboardButton from '~/vue_shared/components/clipboard_button.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
describe('clipboard button', () => {
+ const Component = Vue.extend(clipboardButton);
let vm;
beforeEach(() => {
- const Component = Vue.extend(clipboardButton);
vm = mountComponent(Component, {
text: 'copy me',
title: 'Copy this value into Clipboard!',
diff --git a/spec/javascripts/vue_shared/components/commit_spec.js b/spec/javascripts/vue_shared/components/commit_spec.js
index ed66361bfc3..7189e8cfcfa 100644
--- a/spec/javascripts/vue_shared/components/commit_spec.js
+++ b/spec/javascripts/vue_shared/components/commit_spec.js
@@ -55,7 +55,6 @@ describe('Commit component', () => {
path: '/jschatz1',
username: 'jschatz1',
},
- commitIconSvg: '<svg></svg>',
};
component = mountComponent(CommitComponent, props);
@@ -82,8 +81,10 @@ describe('Commit component', () => {
expect(component.$el.querySelector('.commit-sha').textContent).toContain(props.shortSha);
});
- it('should render the given commitIconSvg', () => {
- expect(component.$el.querySelector('.js-commit-icon').children).toContain('svg');
+ it('should render icon for commit', () => {
+ expect(
+ component.$el.querySelector('.js-commit-icon use').getAttribute('xlink:href'),
+ ).toContain('commit');
});
describe('Given commit title and author props', () => {
diff --git a/spec/javascripts/vue_shared/components/expand_button_spec.js b/spec/javascripts/vue_shared/components/expand_button_spec.js
index f19589d3b75..af9693c48fd 100644
--- a/spec/javascripts/vue_shared/components/expand_button_spec.js
+++ b/spec/javascripts/vue_shared/components/expand_button_spec.js
@@ -3,10 +3,10 @@ import expandButton from '~/vue_shared/components/expand_button.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
describe('expand button', () => {
+ const Component = Vue.extend(expandButton);
let vm;
beforeEach(() => {
- const Component = Vue.extend(expandButton);
vm = mountComponent(Component, {
slots: {
expanded: '<p>Expanded!</p>',
@@ -22,7 +22,7 @@ describe('expand button', () => {
expect(vm.$el.textContent.trim()).toEqual('...');
});
- it('hides expander on click', (done) => {
+ it('hides expander on click', done => {
vm.$el.querySelector('button').click();
vm.$nextTick(() => {
expect(vm.$el.querySelector('button').getAttribute('style')).toEqual('display: none;');
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/base_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/base_spec.js
index 6fe95153204..e8685ab48be 100644
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/base_spec.js
+++ b/spec/javascripts/vue_shared/components/sidebar/labels_select/base_spec.js
@@ -73,6 +73,22 @@ describe('BaseComponent', () => {
expect(vm.$emit).toHaveBeenCalledWith('onLabelClick', mockLabels[0]);
});
});
+
+ describe('handleCollapsedValueClick', () => {
+ it('emits toggleCollapse event on component', () => {
+ spyOn(vm, '$emit');
+ vm.handleCollapsedValueClick();
+ expect(vm.$emit).toHaveBeenCalledWith('toggleCollapse');
+ });
+ });
+
+ describe('handleDropdownHidden', () => {
+ it('emits onDropdownClose event on component', () => {
+ spyOn(vm, '$emit');
+ vm.handleDropdownHidden();
+ expect(vm.$emit).toHaveBeenCalledWith('onDropdownClose');
+ });
+ });
});
describe('mounted', () => {
diff --git a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
index 39040670a87..da74595bcdc 100644
--- a/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
+++ b/spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
@@ -56,6 +56,16 @@ describe('DropdownValueCollapsedComponent', () => {
});
});
+ describe('methods', () => {
+ describe('handleClick', () => {
+ it('emits onValueClick event on component', () => {
+ spyOn(vm, '$emit');
+ vm.handleClick();
+ expect(vm.$emit).toHaveBeenCalledWith('onValueClick');
+ });
+ });
+ });
+
describe('template', () => {
it('renders component container element with tooltip`', () => {
expect(vm.$el.dataset.placement).toBe('left');
diff --git a/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb b/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb
index ae5b31dc12d..c3f528dd6fc 100644
--- a/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb
+++ b/spec/lib/gitlab/bitbucket_import/project_creator_spec.rb
@@ -15,7 +15,7 @@ describe Gitlab::BitbucketImport::ProjectCreator do
has_wiki?: false)
end
- let(:namespace) { create(:group, owner: user) }
+ let(:namespace) { create(:group) }
let(:token) { "asdasd12345" }
let(:secret) { "sekrettt" }
let(:access_params) { { bitbucket_access_token: token, bitbucket_access_token_secret: secret } }
diff --git a/spec/lib/gitlab/wiki/committer_with_hooks_spec.rb b/spec/lib/gitlab/git/committer_with_hooks_spec.rb
index 830fb8a8598..267056b96e6 100644
--- a/spec/lib/gitlab/wiki/committer_with_hooks_spec.rb
+++ b/spec/lib/gitlab/git/committer_with_hooks_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe Gitlab::Wiki::CommitterWithHooks, seed_helper: true do
+describe Gitlab::Git::CommitterWithHooks, seed_helper: true do
shared_examples 'calling wiki hooks' do
let(:project) { create(:project) }
let(:user) { project.owner }
diff --git a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
index 074323d47d2..ecd8657c406 100644
--- a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
@@ -156,4 +156,15 @@ describe Gitlab::GitalyClient::RepositoryService do
client.calculate_checksum
end
end
+
+ describe '#create_from_snapshot' do
+ it 'sends a create_repository_from_snapshot message' do
+ expect_any_instance_of(Gitaly::RepositoryService::Stub)
+ .to receive(:create_repository_from_snapshot)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
+ .and_return(double)
+
+ client.create_from_snapshot('http://example.com?wiki=1', 'Custom xyz')
+ end
+ end
end
diff --git a/spec/lib/gitlab/gitlab_import/project_creator_spec.rb b/spec/lib/gitlab/gitlab_import/project_creator_spec.rb
index 82548c7fd31..5ea086e4abd 100644
--- a/spec/lib/gitlab/gitlab_import/project_creator_spec.rb
+++ b/spec/lib/gitlab/gitlab_import/project_creator_spec.rb
@@ -12,7 +12,7 @@ describe Gitlab::GitlabImport::ProjectCreator do
owner: { name: "john" }
}.with_indifferent_access
end
- let(:namespace) { create(:group, owner: user) }
+ let(:namespace) { create(:group) }
let(:token) { "asdffg" }
let(:access_params) { { gitlab_access_token: token } }
diff --git a/spec/lib/gitlab/google_code_import/project_creator_spec.rb b/spec/lib/gitlab/google_code_import/project_creator_spec.rb
index 8d5b60d50de..24cd518c77b 100644
--- a/spec/lib/gitlab/google_code_import/project_creator_spec.rb
+++ b/spec/lib/gitlab/google_code_import/project_creator_spec.rb
@@ -9,7 +9,7 @@ describe Gitlab::GoogleCodeImport::ProjectCreator do
"repositoryUrls" => ["https://vim.googlecode.com/git/"]
)
end
- let(:namespace) { create(:group, owner: user) }
+ let(:namespace) { create(:group) }
before do
namespace.add_owner(user)
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index f84a777a27f..05790bb5fe1 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -537,12 +537,6 @@ ProjectCustomAttribute:
- project_id
- key
- value
-LfsFileLock:
-- id
-- path
-- user_id
-- project_id
-- created_at
Badge:
- id
- link_url
diff --git a/spec/lib/gitlab/legacy_github_import/project_creator_spec.rb b/spec/lib/gitlab/legacy_github_import/project_creator_spec.rb
index 737c9a624e0..eb1b13704ea 100644
--- a/spec/lib/gitlab/legacy_github_import/project_creator_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/project_creator_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
describe Gitlab::LegacyGithubImport::ProjectCreator do
let(:user) { create(:user) }
- let(:namespace) { create(:group, owner: user) }
+ let(:namespace) { create(:group) }
let(:repo) do
OpenStruct.new(
diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb
index d64ea72e346..e732b089d44 100644
--- a/spec/lib/gitlab/workhorse_spec.rb
+++ b/spec/lib/gitlab/workhorse_spec.rb
@@ -482,4 +482,26 @@ describe Gitlab::Workhorse do
}.deep_stringify_keys)
end
end
+
+ describe '.send_git_snapshot' do
+ let(:url) { 'http://example.com' }
+
+ subject(:request) { described_class.send_git_snapshot(repository) }
+
+ it 'sets the header correctly' do
+ key, command, params = decode_workhorse_header(request)
+
+ expect(key).to eq("Gitlab-Workhorse-Send-Data")
+ expect(command).to eq('git-snapshot')
+ expect(params).to eq(
+ 'GitalyServer' => {
+ 'address' => Gitlab::GitalyClient.address(project.repository_storage),
+ 'token' => Gitlab::GitalyClient.token(project.repository_storage)
+ },
+ 'GetSnapshotRequest' => Gitaly::GetSnapshotRequest.new(
+ repository: repository.gitaly_repository
+ ).to_json
+ )
+ end
+ end
end
diff --git a/spec/lib/gitlab_spec.rb b/spec/lib/gitlab_spec.rb
index bd443a5d9e7..da146e24893 100644
--- a/spec/lib/gitlab_spec.rb
+++ b/spec/lib/gitlab_spec.rb
@@ -1,6 +1,14 @@
-require 'rails_helper'
+require 'fast_spec_helper'
+
+require_dependency 'gitlab'
describe Gitlab do
+ describe '.root' do
+ it 'returns the root path of the app' do
+ expect(described_class.root).to eq(Pathname.new(File.expand_path('../..', __dir__)))
+ end
+ end
+
describe '.com?' do
it 'is true when on GitLab.com' do
stub_config_setting(url: 'https://gitlab.com')
diff --git a/spec/migrations/create_missing_namespace_for_internal_users_spec.rb b/spec/migrations/create_missing_namespace_for_internal_users_spec.rb
new file mode 100644
index 00000000000..ac3a4b1f68f
--- /dev/null
+++ b/spec/migrations/create_missing_namespace_for_internal_users_spec.rb
@@ -0,0 +1,42 @@
+require 'spec_helper'
+require Rails.root.join('db', 'migrate', '20180413022611_create_missing_namespace_for_internal_users.rb')
+
+describe CreateMissingNamespaceForInternalUsers, :migration do
+ let(:users) { table(:users) }
+ let(:namespaces) { table(:namespaces) }
+ let(:routes) { table(:routes) }
+
+ internal_user_types = [:ghost]
+ internal_user_types << :support_bot if ActiveRecord::Base.connection.column_exists?(:users, :support_bot)
+
+ internal_user_types.each do |attr|
+ context "for #{attr} user" do
+ let(:internal_user) do
+ users.create!(email: 'test@example.com', projects_limit: 100, username: 'test', attr => true)
+ end
+
+ it 'creates the missing namespace' do
+ expect(namespaces.find_by(owner_id: internal_user.id)).to be_nil
+
+ migrate!
+
+ namespace = Namespace.find_by(type: nil, owner_id: internal_user.id)
+ route = namespace.route
+
+ expect(namespace.path).to eq(route.path)
+ expect(namespace.name).to eq(route.name)
+ end
+
+ it 'sets notification email' do
+ users.update(internal_user.id, notification_email: nil)
+
+ expect(users.find(internal_user.id).notification_email).to be_nil
+
+ migrate!
+
+ user = users.find(internal_user.id)
+ expect(user.notification_email).to eq(user.email)
+ end
+ end
+ end
+end
diff --git a/spec/models/concerns/avatarable_spec.rb b/spec/models/concerns/avatarable_spec.rb
index 3696e6f62fd..9faf21bfbbd 100644
--- a/spec/models/concerns/avatarable_spec.rb
+++ b/spec/models/concerns/avatarable_spec.rb
@@ -1,7 +1,7 @@
require 'spec_helper'
describe Avatarable do
- set(:project) { create(:project, avatar: fixture_file_upload(File.join(Rails.root, 'spec/fixtures/dk.png'))) }
+ let(:project) { create(:project, :with_avatar) }
let(:gitlab_host) { "https://gitlab.example.com" }
let(:relative_url_root) { "/gitlab" }
@@ -37,11 +37,23 @@ describe Avatarable do
project.visibility_level = visibility_level
end
- let(:avatar_path) { (avatar_path_prefix + [project.avatar.url]).join }
+ let(:avatar_path) { (avatar_path_prefix + [project.avatar.local_url]).join }
it 'returns the expected avatar path' do
expect(project.avatar_path(only_path: only_path)).to eq(avatar_path)
end
+
+ context "when avatar is stored remotely" do
+ before do
+ stub_uploads_object_storage(AvatarUploader)
+
+ project.avatar.migrate!(ObjectStorage::Store::REMOTE)
+ end
+
+ it 'returns the expected avatar path' do
+ expect(project.avatar_url(only_path: only_path)).to eq(avatar_path)
+ end
+ end
end
end
end
diff --git a/spec/models/concerns/uniquify_spec.rb b/spec/models/concerns/uniquify_spec.rb
index 914730718e7..6cd2de6dcce 100644
--- a/spec/models/concerns/uniquify_spec.rb
+++ b/spec/models/concerns/uniquify_spec.rb
@@ -22,6 +22,15 @@ describe Uniquify do
expect(result).to eq('test_string2')
end
+ it 'allows to pass an initial value for the counter' do
+ start_counting_from = 2
+ uniquify = described_class.new(start_counting_from)
+
+ result = uniquify.string('test_string') { |s| s == 'test_string' }
+
+ expect(result).to eq('test_string2')
+ end
+
it 'allows passing in a base function that defines the location of the counter' do
result = uniquify.string(-> (counter) { "test_#{counter}_string" }) do |s|
s == 'test__string'
diff --git a/spec/models/deployment_spec.rb b/spec/models/deployment_spec.rb
index ac30cd27e0c..aee70bcfb29 100644
--- a/spec/models/deployment_spec.rb
+++ b/spec/models/deployment_spec.rb
@@ -16,6 +16,15 @@ describe Deployment do
it { is_expected.to validate_presence_of(:ref) }
it { is_expected.to validate_presence_of(:sha) }
+ describe 'modules' do
+ it_behaves_like 'AtomicInternalId' do
+ let(:internal_id_attribute) { :iid }
+ let(:instance) { build(:deployment) }
+ let(:scope_attrs) { { project: instance.project } }
+ let(:usage) { :deployments }
+ end
+ end
+
describe 'after_create callbacks' do
let(:environment) { create(:environment) }
let(:store) { Gitlab::EtagCaching::Store.new }
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index 11154291368..128acf83686 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -376,6 +376,48 @@ describe Issue do
end
end
+ describe '#suggested_branch_name' do
+ let(:repository) { double }
+
+ subject { build(:issue) }
+
+ before do
+ allow(subject.project).to receive(:repository).and_return(repository)
+ end
+
+ context '#to_branch_name does not exists' do
+ before do
+ allow(repository).to receive(:branch_exists?).and_return(false)
+ end
+
+ it 'returns #to_branch_name' do
+ expect(subject.suggested_branch_name).to eq(subject.to_branch_name)
+ end
+ end
+
+ context '#to_branch_name exists not ending with -index' do
+ before do
+ allow(repository).to receive(:branch_exists?).and_return(true)
+ allow(repository).to receive(:branch_exists?).with(/#{subject.to_branch_name}-\d/).and_return(false)
+ end
+
+ it 'returns #to_branch_name ending with -2' do
+ expect(subject.suggested_branch_name).to eq("#{subject.to_branch_name}-2")
+ end
+ end
+
+ context '#to_branch_name exists ending with -index' do
+ before do
+ allow(repository).to receive(:branch_exists?).and_return(true)
+ allow(repository).to receive(:branch_exists?).with("#{subject.to_branch_name}-3").and_return(false)
+ end
+
+ it 'returns #to_branch_name ending with max index + 1' do
+ expect(subject.suggested_branch_name).to eq("#{subject.to_branch_name}-3")
+ end
+ end
+ end
+
describe '#has_related_branch?' do
let(:issue) { create(:issue, title: "Blue Bell Knoll") }
subject { issue.has_related_branch? }
@@ -425,6 +467,27 @@ describe Issue do
end
end
+ describe '#can_be_worked_on?' do
+ let(:project) { build(:project) }
+ subject { build(:issue, :opened, project: project) }
+
+ context 'is closed' do
+ subject { build(:issue, :closed) }
+
+ it { is_expected.not_to be_can_be_worked_on }
+ end
+
+ context 'project is forked' do
+ before do
+ allow(project).to receive(:forked?).and_return(true)
+ end
+
+ it { is_expected.not_to be_can_be_worked_on }
+ end
+
+ it { is_expected.to be_can_be_worked_on }
+ end
+
describe '#participants' do
context 'using a public project' do
let(:project) { create(:project, :public) }
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index f73f44ca0ad..becb146422e 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -17,11 +17,17 @@ describe MergeRequest do
describe 'modules' do
subject { described_class }
- it { is_expected.to include_module(NonatomicInternalId) }
it { is_expected.to include_module(Issuable) }
it { is_expected.to include_module(Referable) }
it { is_expected.to include_module(Sortable) }
it { is_expected.to include_module(Taskable) }
+
+ it_behaves_like 'AtomicInternalId' do
+ let(:internal_id_attribute) { :iid }
+ let(:instance) { build(:merge_request) }
+ let(:scope_attrs) { { project: instance.target_project } }
+ let(:usage) { :merge_requests }
+ end
end
describe 'validation' do
diff --git a/spec/models/milestone_spec.rb b/spec/models/milestone_spec.rb
index c7460981a32..4bb9717d33e 100644
--- a/spec/models/milestone_spec.rb
+++ b/spec/models/milestone_spec.rb
@@ -1,6 +1,26 @@
require 'spec_helper'
describe Milestone do
+ describe 'modules' do
+ context 'with a project' do
+ it_behaves_like 'AtomicInternalId' do
+ let(:internal_id_attribute) { :iid }
+ let(:instance) { build(:milestone, project: build(:project), group: nil) }
+ let(:scope_attrs) { { project: instance.project } }
+ let(:usage) { :milestones }
+ end
+ end
+
+ context 'with a group' do
+ it_behaves_like 'AtomicInternalId' do
+ let(:internal_id_attribute) { :iid }
+ let(:instance) { build(:milestone, project: nil, group: build(:group)) }
+ let(:scope_attrs) { { namespace: instance.group } }
+ let(:usage) { :milestones }
+ end
+ end
+ end
+
describe "Validation" do
before do
allow(subject).to receive(:set_iid).and_return(false)
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 2675c2f52c1..4002722e358 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -325,7 +325,7 @@ describe Project do
let(:owner) { create(:user, name: 'Gitlab') }
let(:namespace) { create(:namespace, path: 'sample-namespace', owner: owner) }
let(:project) { create(:project, path: 'sample-project', namespace: namespace) }
- let(:group) { create(:group, name: 'Group', path: 'sample-group', owner: owner) }
+ let(:group) { create(:group, name: 'Group', path: 'sample-group') }
context 'when nil argument' do
it 'returns nil' do
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 35db7616efb..3f2eb58f009 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -1164,8 +1164,12 @@ describe User do
end
context 'with a group route matching the given path' do
+ let!(:group) { create(:group, path: 'group_path') }
+
context 'when the group namespace has an owner_id (legacy data)' do
- let!(:group) { create(:group, path: 'group_path', owner: user) }
+ before do
+ group.update!(owner_id: user.id)
+ end
it 'returns nil' do
expect(described_class.find_by_full_path('group_path')).to eq(nil)
@@ -1173,8 +1177,6 @@ describe User do
end
context 'when the group namespace does not have an owner_id' do
- let!(:group) { create(:group, path: 'group_path') }
-
it 'returns nil' do
expect(described_class.find_by_full_path('group_path')).to eq(nil)
end
diff --git a/spec/presenters/project_presenter_spec.rb b/spec/presenters/project_presenter_spec.rb
index 55962f345d4..0a130c59037 100644
--- a/spec/presenters/project_presenter_spec.rb
+++ b/spec/presenters/project_presenter_spec.rb
@@ -321,7 +321,7 @@ describe ProjectPresenter do
expect(presenter.autodevops_anchor_data).to eq(OpenStruct.new(enabled: false,
label: 'Enable Auto DevOps',
- link: presenter.project_settings_ci_cd_path(project, anchor: 'js-general-pipeline-settings')))
+ link: presenter.project_settings_ci_cd_path(project, anchor: 'autodevops-settings')))
end
end
end
diff --git a/spec/requests/api/project_snapshots_spec.rb b/spec/requests/api/project_snapshots_spec.rb
new file mode 100644
index 00000000000..07a920f8d28
--- /dev/null
+++ b/spec/requests/api/project_snapshots_spec.rb
@@ -0,0 +1,51 @@
+require 'spec_helper'
+
+describe API::ProjectSnapshots do
+ include WorkhorseHelpers
+
+ let(:project) { create(:project) }
+ let(:admin) { create(:admin) }
+
+ describe 'GET /projects/:id/snapshot' do
+ def expect_snapshot_response_for(repository)
+ type, params = workhorse_send_data
+
+ expect(type).to eq('git-snapshot')
+ expect(params).to eq(
+ 'GitalyServer' => {
+ 'address' => Gitlab::GitalyClient.address(repository.project.repository_storage),
+ 'token' => Gitlab::GitalyClient.token(repository.project.repository_storage)
+ },
+ 'GetSnapshotRequest' => Gitaly::GetSnapshotRequest.new(
+ repository: repository.gitaly_repository
+ ).to_json
+ )
+ end
+
+ it 'returns authentication error as project owner' do
+ get api("/projects/#{project.id}/snapshot", project.owner)
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+
+ it 'returns authentication error as unauthenticated user' do
+ get api("/projects/#{project.id}/snapshot", nil)
+
+ expect(response).to have_gitlab_http_status(401)
+ end
+
+ it 'requests project repository raw archive as administrator' do
+ get api("/projects/#{project.id}/snapshot", admin), wiki: '0'
+
+ expect(response).to have_gitlab_http_status(200)
+ expect_snapshot_response_for(project.repository)
+ end
+
+ it 'requests wiki repository raw archive as administrator' do
+ get api("/projects/#{project.id}/snapshot", admin), wiki: '1'
+
+ expect(response).to have_gitlab_http_status(200)
+ expect_snapshot_response_for(project.wiki.repository)
+ end
+ end
+end
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 17272cb00e5..85a571b8f0e 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -685,7 +685,8 @@ describe API::Projects do
issues_enabled: false,
merge_requests_enabled: false,
wiki_enabled: false,
- request_access_enabled: true
+ request_access_enabled: true,
+ jobs_enabled: true
})
post api("/projects/user/#{user.id}", admin), project
diff --git a/spec/requests/api/users_spec.rb b/spec/requests/api/users_spec.rb
index f406d2ffb22..e8196980a8c 100644
--- a/spec/requests/api/users_spec.rb
+++ b/spec/requests/api/users_spec.rb
@@ -212,6 +212,18 @@ describe API::Users do
expect(json_response.last['id']).to eq(user.id)
end
+ it 'returns users with 2fa enabled' do
+ admin
+ user
+ user_with_2fa = create(:user, :two_factor_via_otp)
+
+ get api('/users', admin), { two_factor: 'enabled' }
+
+ expect(response).to match_response_schema('public_api/v4/user/admins')
+ expect(json_response.size).to eq(1)
+ expect(json_response.first['id']).to eq(user_with_2fa.id)
+ end
+
it 'returns 400 when provided incorrect sort params' do
get api('/users', admin), { order_by: 'magic', sort: 'asc' }
diff --git a/spec/services/groups/nested_create_service_spec.rb b/spec/services/groups/nested_create_service_spec.rb
index 6491fb34777..86fdd43c1e5 100644
--- a/spec/services/groups/nested_create_service_spec.rb
+++ b/spec/services/groups/nested_create_service_spec.rb
@@ -59,8 +59,11 @@ describe Groups::NestedCreateService do
describe "#execute" do
it 'returns the group if it already existed' do
- parent = create(:group, path: 'a-group', owner: user)
- child = create(:group, path: 'a-sub-group', parent: parent, owner: user)
+ parent = create(:group, path: 'a-group')
+ child = create(:group, path: 'a-sub-group', parent: parent)
+
+ parent.add_owner(user)
+ child.add_owner(user)
expect(service.execute).to eq(child)
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 83664bae046..53045815a6a 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -32,42 +32,19 @@ require 'rainbow/ext/string'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
+# Requires helpers, and shared contexts/examples first since they're used in other support files
+Dir[Rails.root.join("spec/support/helpers/*.rb")].each { |f| require f }
+Dir[Rails.root.join("spec/support/shared_contexts/*.rb")].each { |f| require f }
+Dir[Rails.root.join("spec/support/shared_examples/*.rb")].each { |f| require f }
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
RSpec.configure do |config|
config.use_transactional_fixtures = false
config.use_instantiated_fixtures = false
- config.mock_with :rspec
config.verbose_retry = true
config.display_try_failure_messages = true
- config.include Devise::Test::ControllerHelpers, type: :controller
- config.include Devise::Test::ControllerHelpers, type: :view
- config.include Devise::Test::IntegrationHelpers, type: :feature
- config.include Warden::Test::Helpers, type: :request
- config.include LoginHelpers, type: :feature
- config.include SearchHelpers, type: :feature
- config.include CookieHelper, :js
- config.include InputHelper, :js
- config.include SelectionHelper, :js
- config.include InspectRequests, :js
- config.include WaitForRequests, :js
- config.include LiveDebugger, :js
- config.include StubConfiguration
- config.include EmailHelpers, :mailer, type: :mailer
- config.include TestEnv
- config.include ActiveJob::TestHelper
- config.include ActiveSupport::Testing::TimeHelpers
- config.include StubGitlabCalls
- config.include StubGitlabData
- config.include ApiHelpers, :api
- config.include Gitlab::Routing, type: :routing
- config.include MigrationsHelpers, :migration
- config.include StubFeatureFlags
- config.include StubENV
- config.include ExpectOffense
-
config.infer_spec_type_from_file_location!
config.define_derived_metadata(file_path: %r{/spec/}) do |metadata|
@@ -82,7 +59,33 @@ RSpec.configure do |config|
metadata[:type] = match[1].singularize.to_sym if match
end
- config.raise_errors_for_deprecations!
+ config.include ActiveJob::TestHelper
+ config.include ActiveSupport::Testing::TimeHelpers
+ config.include CycleAnalyticsHelpers
+ config.include ExpectOffense
+ config.include FactoryBot::Syntax::Methods
+ config.include FixtureHelpers
+ config.include GitlabRoutingHelper
+ config.include StubFeatureFlags
+ config.include StubGitlabCalls
+ config.include StubGitlabData
+ config.include TestEnv
+ config.include Devise::Test::ControllerHelpers, type: :controller
+ config.include Devise::Test::IntegrationHelpers, type: :feature
+ config.include LoginHelpers, type: :feature
+ config.include SearchHelpers, type: :feature
+ config.include EmailHelpers, :mailer, type: :mailer
+ config.include Warden::Test::Helpers, type: :request
+ config.include Gitlab::Routing, type: :routing
+ config.include Devise::Test::ControllerHelpers, type: :view
+ config.include ApiHelpers, :api
+ config.include CookieHelper, :js
+ config.include InputHelper, :js
+ config.include SelectionHelper, :js
+ config.include InspectRequests, :js
+ config.include WaitForRequests, :js
+ config.include LiveDebugger, :js
+ config.include MigrationsHelpers, :migration
if ENV['CI']
# This includes the first try, i.e. tests will be run 4 times before failing.
diff --git a/spec/support/capybara.rb b/spec/support/capybara.rb
index 9ddcc5f2fbf..c0ceb0f6605 100644
--- a/spec/support/capybara.rb
+++ b/spec/support/capybara.rb
@@ -60,6 +60,8 @@ Capybara::Screenshot.register_driver(:chrome) do |driver, path|
end
RSpec.configure do |config|
+ config.include CapybaraHelpers, type: :feature
+
config.before(:context, :js) do
next if $capybara_server_already_started
diff --git a/spec/support/controllers/githubish_import_controller_shared_examples.rb b/spec/support/controllers/githubish_import_controller_shared_examples.rb
index 3321f920666..368439aa5b0 100644
--- a/spec/support/controllers/githubish_import_controller_shared_examples.rb
+++ b/spec/support/controllers/githubish_import_controller_shared_examples.rb
@@ -56,7 +56,7 @@ shared_examples 'a GitHub-ish import controller: GET status' do
end
it "assigns variables" do
- project = create(:project, import_type: provider, creator_id: user.id)
+ project = create(:project, import_type: provider, namespace: user.namespace)
stub_client(repos: [repo, org_repo], orgs: [org], org_repos: [org_repo])
get :status
@@ -69,7 +69,7 @@ shared_examples 'a GitHub-ish import controller: GET status' do
end
it "does not show already added project" do
- project = create(:project, import_type: provider, creator_id: user.id, import_source: 'asd/vim')
+ project = create(:project, import_type: provider, namespace: user.namespace, import_source: 'asd/vim')
stub_client(repos: [repo], orgs: [])
get :status
@@ -257,11 +257,12 @@ shared_examples 'a GitHub-ish import controller: POST create' do
end
context 'user has chosen an existing nested namespace and name for the project', :postgresql do
- let(:parent_namespace) { create(:group, name: 'foo', owner: user) }
+ let(:parent_namespace) { create(:group, name: 'foo') }
let(:nested_namespace) { create(:group, name: 'bar', parent: parent_namespace) }
let(:test_name) { 'test_name' }
before do
+ parent_namespace.add_owner(user)
nested_namespace.add_owner(user)
end
@@ -307,7 +308,7 @@ shared_examples 'a GitHub-ish import controller: POST create' do
context 'user has chosen existent and non-existent nested namespaces and name for the project', :postgresql do
let(:test_name) { 'test_name' }
- let!(:parent_namespace) { create(:group, name: 'foo', owner: user) }
+ let!(:parent_namespace) { create(:group, name: 'foo') }
before do
parent_namespace.add_owner(user)
diff --git a/spec/support/factory_bot.rb b/spec/support/factory_bot.rb
deleted file mode 100644
index c7890e49c66..00000000000
--- a/spec/support/factory_bot.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-RSpec.configure do |config|
- config.include FactoryBot::Syntax::Methods
-end
diff --git a/spec/support/generate-seed-repo-rb b/spec/support/generate-seed-repo-rb
index 876b3b8242d..44b3de23b99 100755
--- a/spec/support/generate-seed-repo-rb
+++ b/spec/support/generate-seed-repo-rb
@@ -8,7 +8,7 @@
#
# Usage:
#
-# ./spec/support/generate-seed-repo-rb > spec/support/seed_repo.rb
+# ./spec/support/generate-seed-repo-rb > spec/support/helpers/seed_repo.rb
#
#
diff --git a/spec/support/gitlab-git-test.git/README.md b/spec/support/gitlab-git-test.git/README.md
index f072cd421be..f757e613ee6 100644
--- a/spec/support/gitlab-git-test.git/README.md
+++ b/spec/support/gitlab-git-test.git/README.md
@@ -12,5 +12,5 @@ inflate the size of the gitlab-ce repository.
- make changes in your local clone of gitlab-git-test
- run `git push` which will push to your local source `gitlab-ce/spec/support/gitlab-git-test.git`
- in gitlab-ce: run `spec/support/prepare-gitlab-git-test-for-commit`
-- in gitlab-ce: `git add spec/support/seed_repo.rb spec/support/gitlab-git-test.git`
+- in gitlab-ce: `git add spec/support/helpers/seed_repo.rb spec/support/gitlab-git-test.git`
- commit your changes in gitlab-ce
diff --git a/spec/support/api_helpers.rb b/spec/support/helpers/api_helpers.rb
index ac0c7a9b493..ac0c7a9b493 100644
--- a/spec/support/api_helpers.rb
+++ b/spec/support/helpers/api_helpers.rb
diff --git a/spec/support/bare_repo_operations.rb b/spec/support/helpers/bare_repo_operations.rb
index 3f4a4243cb6..3f4a4243cb6 100644
--- a/spec/support/bare_repo_operations.rb
+++ b/spec/support/helpers/bare_repo_operations.rb
diff --git a/spec/support/board_helpers.rb b/spec/support/helpers/board_helpers.rb
index 507d0432d7f..507d0432d7f 100644
--- a/spec/support/board_helpers.rb
+++ b/spec/support/helpers/board_helpers.rb
diff --git a/spec/support/capybara_helpers.rb b/spec/support/helpers/capybara_helpers.rb
index 868233416bf..bcc2df44708 100644
--- a/spec/support/capybara_helpers.rb
+++ b/spec/support/helpers/capybara_helpers.rb
@@ -41,7 +41,3 @@ module CapybaraHelpers
page.driver.browser.manage.delete_cookie('_gitlab_session')
end
end
-
-RSpec.configure do |config|
- config.include CapybaraHelpers, type: :feature
-end
diff --git a/spec/support/cookie_helper.rb b/spec/support/helpers/cookie_helper.rb
index 5ff7b0b68c9..5ff7b0b68c9 100644
--- a/spec/support/cookie_helper.rb
+++ b/spec/support/helpers/cookie_helper.rb
diff --git a/spec/support/cycle_analytics_helpers.rb b/spec/support/helpers/cycle_analytics_helpers.rb
index 73cc64c0b74..55359d36597 100644
--- a/spec/support/cycle_analytics_helpers.rb
+++ b/spec/support/helpers/cycle_analytics_helpers.rb
@@ -135,7 +135,3 @@ module CycleAnalyticsHelpers
end
end
end
-
-RSpec.configure do |config|
- config.include CycleAnalyticsHelpers
-end
diff --git a/spec/support/database_connection_helpers.rb b/spec/support/helpers/database_connection_helpers.rb
index 763329499f0..763329499f0 100644
--- a/spec/support/database_connection_helpers.rb
+++ b/spec/support/helpers/database_connection_helpers.rb
diff --git a/spec/support/devise_helpers.rb b/spec/support/helpers/devise_helpers.rb
index 66874e10f38..66874e10f38 100644
--- a/spec/support/devise_helpers.rb
+++ b/spec/support/helpers/devise_helpers.rb
diff --git a/spec/support/drag_to_helper.rb b/spec/support/helpers/drag_to_helper.rb
index ae149631ed9..ae149631ed9 100644
--- a/spec/support/drag_to_helper.rb
+++ b/spec/support/helpers/drag_to_helper.rb
diff --git a/spec/support/dropzone_helper.rb b/spec/support/helpers/dropzone_helper.rb
index fe72d320fcf..fe72d320fcf 100644
--- a/spec/support/dropzone_helper.rb
+++ b/spec/support/helpers/dropzone_helper.rb
diff --git a/spec/support/email_helpers.rb b/spec/support/helpers/email_helpers.rb
index 1fb8252459f..1fb8252459f 100644
--- a/spec/support/email_helpers.rb
+++ b/spec/support/helpers/email_helpers.rb
diff --git a/spec/support/fake_migration_classes.rb b/spec/support/helpers/fake_migration_classes.rb
index b0fc8422857..b0fc8422857 100644
--- a/spec/support/fake_migration_classes.rb
+++ b/spec/support/helpers/fake_migration_classes.rb
diff --git a/spec/support/fake_u2f_device.rb b/spec/support/helpers/fake_u2f_device.rb
index a7605cd483a..a7605cd483a 100644
--- a/spec/support/fake_u2f_device.rb
+++ b/spec/support/helpers/fake_u2f_device.rb
diff --git a/spec/support/filter_item_select_helper.rb b/spec/support/helpers/filter_item_select_helper.rb
index 519e84d359e..519e84d359e 100644
--- a/spec/support/filter_item_select_helper.rb
+++ b/spec/support/helpers/filter_item_select_helper.rb
diff --git a/spec/support/filter_spec_helper.rb b/spec/support/helpers/filter_spec_helper.rb
index 721d359c2ee..721d359c2ee 100644
--- a/spec/support/filter_spec_helper.rb
+++ b/spec/support/helpers/filter_spec_helper.rb
diff --git a/spec/support/filtered_search_helpers.rb b/spec/support/helpers/filtered_search_helpers.rb
index 5f42ff77fb2..5f42ff77fb2 100644
--- a/spec/support/filtered_search_helpers.rb
+++ b/spec/support/helpers/filtered_search_helpers.rb
diff --git a/spec/support/fixture_helpers.rb b/spec/support/helpers/fixture_helpers.rb
index 8854382dc6b..611d19f36a0 100644
--- a/spec/support/fixture_helpers.rb
+++ b/spec/support/helpers/fixture_helpers.rb
@@ -9,7 +9,3 @@ module FixtureHelpers
File.expand_path(Rails.root.join(dir, 'spec', 'fixtures', filename))
end
end
-
-RSpec.configure do |config|
- config.include FixtureHelpers
-end
diff --git a/spec/support/git_http_helpers.rb b/spec/support/helpers/git_http_helpers.rb
index b8289e6c5f1..b8289e6c5f1 100644
--- a/spec/support/git_http_helpers.rb
+++ b/spec/support/helpers/git_http_helpers.rb
diff --git a/spec/support/helpers/gitlab_verify_helpers.rb b/spec/support/helpers/gitlab_verify_helpers.rb
new file mode 100644
index 00000000000..5df4bf24ec2
--- /dev/null
+++ b/spec/support/helpers/gitlab_verify_helpers.rb
@@ -0,0 +1,25 @@
+module GitlabVerifyHelpers
+ def collect_ranges(args = {})
+ verifier = described_class.new(args.merge(batch_size: 1))
+
+ collect_results(verifier).map { |range, _| range }
+ end
+
+ def collect_failures
+ verifier = described_class.new(batch_size: 1)
+
+ out = {}
+
+ collect_results(verifier).map { |_, failures| out.merge!(failures) }
+
+ out
+ end
+
+ def collect_results(verifier)
+ out = []
+
+ verifier.run_batches { |*args| out << args }
+
+ out
+ end
+end
diff --git a/spec/support/gpg_helpers.rb b/spec/support/helpers/gpg_helpers.rb
index 3f7279a50e0..3f7279a50e0 100644
--- a/spec/support/gpg_helpers.rb
+++ b/spec/support/helpers/gpg_helpers.rb
diff --git a/spec/support/import_spec_helper.rb b/spec/support/helpers/import_spec_helper.rb
index d4eced724fa..d4eced724fa 100644
--- a/spec/support/import_spec_helper.rb
+++ b/spec/support/helpers/import_spec_helper.rb
diff --git a/spec/support/input_helper.rb b/spec/support/helpers/input_helper.rb
index acbb42274ec..acbb42274ec 100644
--- a/spec/support/input_helper.rb
+++ b/spec/support/helpers/input_helper.rb
diff --git a/spec/support/inspect_requests.rb b/spec/support/helpers/inspect_requests.rb
index 88ddc5c7f6c..88ddc5c7f6c 100644
--- a/spec/support/inspect_requests.rb
+++ b/spec/support/helpers/inspect_requests.rb
diff --git a/spec/support/issue_helpers.rb b/spec/support/helpers/issue_helpers.rb
index ffd72515f37..ffd72515f37 100644
--- a/spec/support/issue_helpers.rb
+++ b/spec/support/helpers/issue_helpers.rb
diff --git a/spec/support/javascript_fixtures_helpers.rb b/spec/support/helpers/javascript_fixtures_helpers.rb
index 2197bc9d853..2197bc9d853 100644
--- a/spec/support/javascript_fixtures_helpers.rb
+++ b/spec/support/helpers/javascript_fixtures_helpers.rb
diff --git a/spec/support/jira_service_helper.rb b/spec/support/helpers/jira_service_helper.rb
index 88a7aeba461..88a7aeba461 100644
--- a/spec/support/jira_service_helper.rb
+++ b/spec/support/helpers/jira_service_helper.rb
diff --git a/spec/support/kubernetes_helpers.rb b/spec/support/helpers/kubernetes_helpers.rb
index e46b61b6461..e46b61b6461 100644
--- a/spec/support/kubernetes_helpers.rb
+++ b/spec/support/helpers/kubernetes_helpers.rb
diff --git a/spec/support/ldap_helpers.rb b/spec/support/helpers/ldap_helpers.rb
index 0e87b3d359d..0e87b3d359d 100644
--- a/spec/support/ldap_helpers.rb
+++ b/spec/support/helpers/ldap_helpers.rb
diff --git a/spec/support/live_debugger.rb b/spec/support/helpers/live_debugger.rb
index 911eb48a8ca..911eb48a8ca 100644
--- a/spec/support/live_debugger.rb
+++ b/spec/support/helpers/live_debugger.rb
diff --git a/spec/support/login_helpers.rb b/spec/support/helpers/login_helpers.rb
index db34090e971..db34090e971 100644
--- a/spec/support/login_helpers.rb
+++ b/spec/support/helpers/login_helpers.rb
diff --git a/spec/support/markdown_feature.rb b/spec/support/helpers/markdown_feature.rb
index 39e94ad53de..39e94ad53de 100644
--- a/spec/support/markdown_feature.rb
+++ b/spec/support/helpers/markdown_feature.rb
diff --git a/spec/support/merge_request_helpers.rb b/spec/support/helpers/merge_request_helpers.rb
index 772adff4626..772adff4626 100644
--- a/spec/support/merge_request_helpers.rb
+++ b/spec/support/helpers/merge_request_helpers.rb
diff --git a/spec/support/migrations_helpers.rb b/spec/support/helpers/migrations_helpers.rb
index 5d6f662e8fe..5d6f662e8fe 100644
--- a/spec/support/migrations_helpers.rb
+++ b/spec/support/helpers/migrations_helpers.rb
diff --git a/spec/support/mobile_helpers.rb b/spec/support/helpers/mobile_helpers.rb
index 3b9eb84e824..3b9eb84e824 100644
--- a/spec/support/mobile_helpers.rb
+++ b/spec/support/helpers/mobile_helpers.rb
diff --git a/spec/support/project_forks_helper.rb b/spec/support/helpers/project_forks_helper.rb
index 2c501a2a27c..2c501a2a27c 100644
--- a/spec/support/project_forks_helper.rb
+++ b/spec/support/helpers/project_forks_helper.rb
diff --git a/spec/support/prometheus_helpers.rb b/spec/support/helpers/prometheus_helpers.rb
index 4212be2cc88..4212be2cc88 100644
--- a/spec/support/prometheus_helpers.rb
+++ b/spec/support/helpers/prometheus_helpers.rb
diff --git a/spec/support/helpers/query_recorder.rb b/spec/support/helpers/query_recorder.rb
new file mode 100644
index 00000000000..28536bbef5e
--- /dev/null
+++ b/spec/support/helpers/query_recorder.rb
@@ -0,0 +1,38 @@
+module ActiveRecord
+ class QueryRecorder
+ attr_reader :log, :cached
+
+ def initialize(&block)
+ @log = []
+ @cached = []
+ ActiveSupport::Notifications.subscribed(method(:callback), 'sql.active_record', &block)
+ end
+
+ def show_backtrace(values)
+ Rails.logger.debug("QueryRecorder SQL: #{values[:sql]}")
+ caller.each { |line| Rails.logger.debug(" --> #{line}") }
+ end
+
+ def callback(name, start, finish, message_id, values)
+ show_backtrace(values) if ENV['QUERY_RECORDER_DEBUG']
+
+ if values[:name]&.include?("CACHE")
+ @cached << values[:sql]
+ elsif !values[:name]&.include?("SCHEMA")
+ @log << values[:sql]
+ end
+ end
+
+ def count
+ @log.count
+ end
+
+ def cached_count
+ @cached.count
+ end
+
+ def log_message
+ @log.join("\n\n")
+ end
+ end
+end
diff --git a/spec/support/helpers/quick_actions_helpers.rb b/spec/support/helpers/quick_actions_helpers.rb
new file mode 100644
index 00000000000..361190aa352
--- /dev/null
+++ b/spec/support/helpers/quick_actions_helpers.rb
@@ -0,0 +1,10 @@
+module QuickActionsHelpers
+ def write_note(text)
+ Sidekiq::Testing.fake! do
+ page.within('.js-main-target-form') do
+ fill_in 'note[note]', with: text
+ find('.js-comment-submit-button').click
+ end
+ end
+ end
+end
diff --git a/spec/support/rake_helpers.rb b/spec/support/helpers/rake_helpers.rb
index 86bfeed107c..86bfeed107c 100644
--- a/spec/support/rake_helpers.rb
+++ b/spec/support/helpers/rake_helpers.rb
diff --git a/spec/support/reactive_caching_helpers.rb b/spec/support/helpers/reactive_caching_helpers.rb
index e22dd974c6a..e22dd974c6a 100644
--- a/spec/support/reactive_caching_helpers.rb
+++ b/spec/support/helpers/reactive_caching_helpers.rb
diff --git a/spec/support/redis_without_keys.rb b/spec/support/helpers/redis_without_keys.rb
index 6220167dee6..6220167dee6 100644
--- a/spec/support/redis_without_keys.rb
+++ b/spec/support/helpers/redis_without_keys.rb
diff --git a/spec/support/reference_parser_helpers.rb b/spec/support/helpers/reference_parser_helpers.rb
index c01897ed1a1..c01897ed1a1 100644
--- a/spec/support/reference_parser_helpers.rb
+++ b/spec/support/helpers/reference_parser_helpers.rb
diff --git a/spec/support/repo_helpers.rb b/spec/support/helpers/repo_helpers.rb
index 3c6956cf5e0..3c6956cf5e0 100644
--- a/spec/support/repo_helpers.rb
+++ b/spec/support/helpers/repo_helpers.rb
diff --git a/spec/support/search_helpers.rb b/spec/support/helpers/search_helpers.rb
index abbbb636d66..abbbb636d66 100644
--- a/spec/support/search_helpers.rb
+++ b/spec/support/helpers/search_helpers.rb
diff --git a/spec/support/seed_helper.rb b/spec/support/helpers/seed_helper.rb
index 11ef1fc477f..8fd107260cc 100644
--- a/spec/support/seed_helper.rb
+++ b/spec/support/helpers/seed_helper.rb
@@ -9,7 +9,7 @@ TEST_MUTABLE_REPO_PATH = 'mutable-repo.git'.freeze
TEST_BROKEN_REPO_PATH = 'broken-repo.git'.freeze
module SeedHelper
- GITLAB_GIT_TEST_REPO_URL = File.expand_path('../gitlab-git-test.git', __FILE__).freeze
+ GITLAB_GIT_TEST_REPO_URL = File.expand_path('../gitlab-git-test.git', __dir__).freeze
def ensure_seeds
if File.exist?(SEED_STORAGE_PATH)
@@ -108,11 +108,3 @@ bla/bla.txt
{ 'GIT_TEMPLATE_DIR' => '' }
end
end
-
-RSpec.configure do |config|
- config.include SeedHelper, :seed_helper
-
- config.before(:all, :seed_helper) do
- ensure_seeds
- end
-end
diff --git a/spec/support/seed_repo.rb b/spec/support/helpers/seed_repo.rb
index b4868e82cd7..b4868e82cd7 100644
--- a/spec/support/seed_repo.rb
+++ b/spec/support/helpers/seed_repo.rb
diff --git a/spec/support/select2_helper.rb b/spec/support/helpers/select2_helper.rb
index 90618ba5b19..90618ba5b19 100644
--- a/spec/support/select2_helper.rb
+++ b/spec/support/helpers/select2_helper.rb
diff --git a/spec/support/selection_helper.rb b/spec/support/helpers/selection_helper.rb
index b4725b137b2..b4725b137b2 100644
--- a/spec/support/selection_helper.rb
+++ b/spec/support/helpers/selection_helper.rb
diff --git a/spec/support/helpers/sorting_helper.rb b/spec/support/helpers/sorting_helper.rb
new file mode 100644
index 00000000000..577518d726c
--- /dev/null
+++ b/spec/support/helpers/sorting_helper.rb
@@ -0,0 +1,18 @@
+# Helper allows you to sort items
+#
+# Params
+# value - value for sorting
+#
+# Usage:
+# include SortingHelper
+#
+# sorting_by('Oldest updated')
+#
+module SortingHelper
+ def sorting_by(value)
+ find('button.dropdown-toggle').click
+ page.within('.content ul.dropdown-menu.dropdown-menu-align-right li') do
+ click_link value
+ end
+ end
+end
diff --git a/spec/support/stub_configuration.rb b/spec/support/helpers/stub_configuration.rb
index a75a3eaefcb..1823099dd9c 100644
--- a/spec/support/stub_configuration.rb
+++ b/spec/support/helpers/stub_configuration.rb
@@ -1,3 +1,6 @@
+require 'active_support/core_ext/hash/transform_values'
+require 'active_support/hash_with_indifferent_access'
+
module StubConfiguration
def stub_application_setting(messages)
add_predicates(messages)
diff --git a/spec/support/stub_env.rb b/spec/support/helpers/stub_env.rb
index 36b90fc68d6..36b90fc68d6 100644
--- a/spec/support/stub_env.rb
+++ b/spec/support/helpers/stub_env.rb
diff --git a/spec/support/stub_feature_flags.rb b/spec/support/helpers/stub_feature_flags.rb
index b96338bf548..b96338bf548 100644
--- a/spec/support/stub_feature_flags.rb
+++ b/spec/support/helpers/stub_feature_flags.rb
diff --git a/spec/support/stub_gitlab_calls.rb b/spec/support/helpers/stub_gitlab_calls.rb
index c1618f5086c..c1618f5086c 100644
--- a/spec/support/stub_gitlab_calls.rb
+++ b/spec/support/helpers/stub_gitlab_calls.rb
diff --git a/spec/support/stub_gitlab_data.rb b/spec/support/helpers/stub_gitlab_data.rb
index fa402f35b95..fa402f35b95 100644
--- a/spec/support/stub_gitlab_data.rb
+++ b/spec/support/helpers/stub_gitlab_data.rb
diff --git a/spec/support/stub_object_storage.rb b/spec/support/helpers/stub_object_storage.rb
index 6e88641da42..19d744b959a 100644
--- a/spec/support/stub_object_storage.rb
+++ b/spec/support/helpers/stub_object_storage.rb
@@ -1,4 +1,4 @@
-module StubConfiguration
+module StubObjectStorage
def stub_object_storage_uploader(
config:,
uploader:,
diff --git a/spec/support/test_env.rb b/spec/support/helpers/test_env.rb
index d87f265cdf0..d87f265cdf0 100644
--- a/spec/support/test_env.rb
+++ b/spec/support/helpers/test_env.rb
diff --git a/spec/support/upload_helpers.rb b/spec/support/helpers/upload_helpers.rb
index 5eead80c935..5eead80c935 100644
--- a/spec/support/upload_helpers.rb
+++ b/spec/support/helpers/upload_helpers.rb
diff --git a/spec/support/user_activities_helpers.rb b/spec/support/helpers/user_activities_helpers.rb
index 44feb104644..44feb104644 100644
--- a/spec/support/user_activities_helpers.rb
+++ b/spec/support/helpers/user_activities_helpers.rb
diff --git a/spec/support/wait_for_requests.rb b/spec/support/helpers/wait_for_requests.rb
index fda0e29f983..fda0e29f983 100644
--- a/spec/support/wait_for_requests.rb
+++ b/spec/support/helpers/wait_for_requests.rb
diff --git a/spec/support/workhorse_helpers.rb b/spec/support/helpers/workhorse_helpers.rb
index ef1f9f68671..ef1f9f68671 100644
--- a/spec/support/workhorse_helpers.rb
+++ b/spec/support/helpers/workhorse_helpers.rb
diff --git a/spec/support/json_response_helpers.rb b/spec/support/json_response.rb
index aa235529c56..210b0e6d867 100644
--- a/spec/support/json_response_helpers.rb
+++ b/spec/support/json_response.rb
@@ -1,7 +1,3 @@
-shared_context 'JSON response' do
- let(:json_response) { JSON.parse(response.body) }
-end
-
RSpec.configure do |config|
config.include_context 'JSON response'
config.include_context 'JSON response', type: :request
diff --git a/spec/support/background_migrations_matchers.rb b/spec/support/matchers/background_migrations_matchers.rb
index f4127efc6ae..f4127efc6ae 100644
--- a/spec/support/background_migrations_matchers.rb
+++ b/spec/support/matchers/background_migrations_matchers.rb
diff --git a/spec/support/query_recorder.rb b/spec/support/matchers/exceed_query_limit.rb
index 8cf8f45a8b2..88d22a3ddd9 100644
--- a/spec/support/query_recorder.rb
+++ b/spec/support/matchers/exceed_query_limit.rb
@@ -1,42 +1,3 @@
-module ActiveRecord
- class QueryRecorder
- attr_reader :log, :cached
-
- def initialize(&block)
- @log = []
- @cached = []
- ActiveSupport::Notifications.subscribed(method(:callback), 'sql.active_record', &block)
- end
-
- def show_backtrace(values)
- Rails.logger.debug("QueryRecorder SQL: #{values[:sql]}")
- caller.each { |line| Rails.logger.debug(" --> #{line}") }
- end
-
- def callback(name, start, finish, message_id, values)
- show_backtrace(values) if ENV['QUERY_RECORDER_DEBUG']
-
- if values[:name]&.include?("CACHE")
- @cached << values[:sql]
- elsif !values[:name]&.include?("SCHEMA")
- @log << values[:sql]
- end
- end
-
- def count
- @log.count
- end
-
- def cached_count
- @cached.count
- end
-
- def log_message
- @log.join("\n\n")
- end
- end
-end
-
RSpec::Matchers.define :exceed_query_limit do |expected|
supports_block_expectations
diff --git a/spec/support/prepare-gitlab-git-test-for-commit b/spec/support/prepare-gitlab-git-test-for-commit
index 3047786a599..d08e3ba5481 100755
--- a/spec/support/prepare-gitlab-git-test-for-commit
+++ b/spec/support/prepare-gitlab-git-test-for-commit
@@ -1,7 +1,7 @@
#!/usr/bin/env ruby
abort unless [
- system('spec/support/generate-seed-repo-rb', out: 'spec/support/seed_repo.rb'),
+ system('spec/support/generate-seed-repo-rb', out: 'spec/support/helpers/seed_repo.rb'),
system('spec/support/unpack-gitlab-git-test')
].all?
diff --git a/spec/support/routing_helpers.rb b/spec/support/routing_helpers.rb
deleted file mode 100644
index af1f4760804..00000000000
--- a/spec/support/routing_helpers.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-RSpec.configure do |config|
- config.include GitlabRoutingHelper
-end
diff --git a/spec/support/rspec.rb b/spec/support/rspec.rb
new file mode 100644
index 00000000000..dffab22d8b5
--- /dev/null
+++ b/spec/support/rspec.rb
@@ -0,0 +1,12 @@
+require_relative "helpers/stub_configuration"
+require_relative "helpers/stub_object_storage"
+require_relative "helpers/stub_env"
+
+RSpec.configure do |config|
+ config.mock_with :rspec
+ config.raise_errors_for_deprecations!
+
+ config.include StubConfiguration
+ config.include StubObjectStorage
+ config.include StubENV
+end
diff --git a/spec/support/seed.rb b/spec/support/seed.rb
new file mode 100644
index 00000000000..bea2e9c3044
--- /dev/null
+++ b/spec/support/seed.rb
@@ -0,0 +1,7 @@
+RSpec.configure do |config|
+ config.include SeedHelper, :seed_helper
+
+ config.before(:all, :seed_helper) do
+ ensure_seeds
+ end
+end
diff --git a/spec/support/shared_contexts/json_response_shared_context.rb b/spec/support/shared_contexts/json_response_shared_context.rb
new file mode 100644
index 00000000000..df5fc288089
--- /dev/null
+++ b/spec/support/shared_contexts/json_response_shared_context.rb
@@ -0,0 +1,3 @@
+shared_context 'JSON response' do
+ let(:json_response) { JSON.parse(response.body) }
+end
diff --git a/spec/support/services_shared_context.rb b/spec/support/shared_contexts/services_shared_context.rb
index 23f9b46ae0c..23f9b46ae0c 100644
--- a/spec/support/services_shared_context.rb
+++ b/spec/support/shared_contexts/services_shared_context.rb
diff --git a/spec/support/chat_slash_commands_shared_examples.rb b/spec/support/shared_examples/chat_slash_commands_shared_examples.rb
index dc97a39f051..dc97a39f051 100644
--- a/spec/support/chat_slash_commands_shared_examples.rb
+++ b/spec/support/shared_examples/chat_slash_commands_shared_examples.rb
diff --git a/spec/support/email_format_shared_examples.rb b/spec/support/shared_examples/email_format_shared_examples.rb
index b924a208e71..b924a208e71 100644
--- a/spec/support/email_format_shared_examples.rb
+++ b/spec/support/shared_examples/email_format_shared_examples.rb
diff --git a/spec/support/gitlab_verify.rb b/spec/support/shared_examples/gitlab_verify.rb
index 13e2e37624d..560913ca92f 100644
--- a/spec/support/gitlab_verify.rb
+++ b/spec/support/shared_examples/gitlab_verify.rb
@@ -17,29 +17,3 @@ RSpec.shared_examples 'Gitlab::Verify::BatchVerifier subclass' do
end
end
end
-
-module GitlabVerifyHelpers
- def collect_ranges(args = {})
- verifier = described_class.new(args.merge(batch_size: 1))
-
- collect_results(verifier).map { |range, _| range }
- end
-
- def collect_failures
- verifier = described_class.new(batch_size: 1)
-
- out = {}
-
- collect_results(verifier).map { |_, failures| out.merge!(failures) }
-
- out
- end
-
- def collect_results(verifier)
- out = []
-
- verifier.run_batches { |*args| out << args }
-
- out
- end
-end
diff --git a/spec/support/group_members_shared_example.rb b/spec/support/shared_examples/group_members_shared_example.rb
index 547c83c7955..547c83c7955 100644
--- a/spec/support/group_members_shared_example.rb
+++ b/spec/support/shared_examples/group_members_shared_example.rb
diff --git a/spec/support/issuable_shared_examples.rb b/spec/support/shared_examples/issuable_shared_examples.rb
index 42f3b4db23c..42f3b4db23c 100644
--- a/spec/support/issuable_shared_examples.rb
+++ b/spec/support/shared_examples/issuable_shared_examples.rb
diff --git a/spec/support/issuables_list_metadata_shared_examples.rb b/spec/support/shared_examples/issuables_list_metadata_shared_examples.rb
index e61983c60b4..e61983c60b4 100644
--- a/spec/support/issuables_list_metadata_shared_examples.rb
+++ b/spec/support/shared_examples/issuables_list_metadata_shared_examples.rb
diff --git a/spec/support/issue_tracker_service_shared_example.rb b/spec/support/shared_examples/issue_tracker_service_shared_example.rb
index a6ab03cb808..a6ab03cb808 100644
--- a/spec/support/issue_tracker_service_shared_example.rb
+++ b/spec/support/shared_examples/issue_tracker_service_shared_example.rb
diff --git a/spec/support/ldap_shared_examples.rb b/spec/support/shared_examples/ldap_shared_examples.rb
index 52c34e78965..52c34e78965 100644
--- a/spec/support/ldap_shared_examples.rb
+++ b/spec/support/shared_examples/ldap_shared_examples.rb
diff --git a/spec/support/legacy_path_redirect_shared_examples.rb b/spec/support/shared_examples/legacy_path_redirect_shared_examples.rb
index f300bdd48b1..f300bdd48b1 100644
--- a/spec/support/legacy_path_redirect_shared_examples.rb
+++ b/spec/support/shared_examples/legacy_path_redirect_shared_examples.rb
diff --git a/spec/support/malicious_regexp_shared_examples.rb b/spec/support/shared_examples/malicious_regexp_shared_examples.rb
index ac5d22298bb..ac5d22298bb 100644
--- a/spec/support/malicious_regexp_shared_examples.rb
+++ b/spec/support/shared_examples/malicious_regexp_shared_examples.rb
diff --git a/spec/support/mentionable_shared_examples.rb b/spec/support/shared_examples/mentionable_shared_examples.rb
index 1685decbe94..1685decbe94 100644
--- a/spec/support/mentionable_shared_examples.rb
+++ b/spec/support/shared_examples/mentionable_shared_examples.rb
diff --git a/spec/support/milestone_tabs_examples.rb b/spec/support/shared_examples/milestone_tabs_examples.rb
index 70b499198bf..70b499198bf 100644
--- a/spec/support/milestone_tabs_examples.rb
+++ b/spec/support/shared_examples/milestone_tabs_examples.rb
diff --git a/spec/support/shared_examples/models/atomic_internal_id_spec.rb b/spec/support/shared_examples/models/atomic_internal_id_spec.rb
index 144af4fc475..6a6e13418a9 100644
--- a/spec/support/shared_examples/models/atomic_internal_id_spec.rb
+++ b/spec/support/shared_examples/models/atomic_internal_id_spec.rb
@@ -19,6 +19,14 @@ shared_examples_for 'AtomicInternalId' do
it { is_expected.to validate_numericality_of(internal_id_attribute) }
end
+ describe 'Creating an instance' do
+ subject { instance.save! }
+
+ it 'saves a new instance properly' do
+ expect { subject }.not_to raise_error
+ end
+ end
+
describe 'internal id generation' do
subject { instance.save! }
diff --git a/spec/support/notify_shared_examples.rb b/spec/support/shared_examples/notify_shared_examples.rb
index e2c23607406..e2c23607406 100644
--- a/spec/support/notify_shared_examples.rb
+++ b/spec/support/shared_examples/notify_shared_examples.rb
diff --git a/spec/support/reference_parser_shared_examples.rb b/spec/support/shared_examples/reference_parser_shared_examples.rb
index baf8bcc04b8..baf8bcc04b8 100644
--- a/spec/support/reference_parser_shared_examples.rb
+++ b/spec/support/shared_examples/reference_parser_shared_examples.rb
diff --git a/spec/support/slack_mattermost_notifications_shared_examples.rb b/spec/support/shared_examples/slack_mattermost_notifications_shared_examples.rb
index 07bc3a51fd8..07bc3a51fd8 100644
--- a/spec/support/slack_mattermost_notifications_shared_examples.rb
+++ b/spec/support/shared_examples/slack_mattermost_notifications_shared_examples.rb
diff --git a/spec/support/snippet_visibility.rb b/spec/support/shared_examples/snippet_visibility.rb
index 3a7c69b7877..3a7c69b7877 100644
--- a/spec/support/snippet_visibility.rb
+++ b/spec/support/shared_examples/snippet_visibility.rb
diff --git a/spec/support/snippets_shared_examples.rb b/spec/support/shared_examples/snippets_shared_examples.rb
index 85f0facd5c3..85f0facd5c3 100644
--- a/spec/support/snippets_shared_examples.rb
+++ b/spec/support/shared_examples/snippets_shared_examples.rb
diff --git a/spec/support/taskable_shared_examples.rb b/spec/support/shared_examples/taskable_shared_examples.rb
index 4056ff06b84..4056ff06b84 100644
--- a/spec/support/taskable_shared_examples.rb
+++ b/spec/support/shared_examples/taskable_shared_examples.rb
diff --git a/spec/support/time_tracking_shared_examples.rb b/spec/support/shared_examples/time_tracking_shared_examples.rb
index 909d4e2ee8d..909d4e2ee8d 100644
--- a/spec/support/time_tracking_shared_examples.rb
+++ b/spec/support/shared_examples/time_tracking_shared_examples.rb
diff --git a/spec/support/unique_ip_check_shared_examples.rb b/spec/support/shared_examples/unique_ip_check_shared_examples.rb
index e5c8ac6a004..e5c8ac6a004 100644
--- a/spec/support/unique_ip_check_shared_examples.rb
+++ b/spec/support/shared_examples/unique_ip_check_shared_examples.rb
diff --git a/spec/support/update_invalid_issuable.rb b/spec/support/shared_examples/update_invalid_issuable.rb
index 1490287681b..1490287681b 100644
--- a/spec/support/update_invalid_issuable.rb
+++ b/spec/support/shared_examples/update_invalid_issuable.rb
diff --git a/spec/support/updating_mentions_shared_examples.rb b/spec/support/shared_examples/updating_mentions_shared_examples.rb
index 5e3f19ba19e..5e3f19ba19e 100644
--- a/spec/support/updating_mentions_shared_examples.rb
+++ b/spec/support/shared_examples/updating_mentions_shared_examples.rb
diff --git a/spec/views/projects/settings/ci_cd/_form.html.haml_spec.rb b/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb
index be9a4d9c57c..d15391911c1 100644
--- a/spec/views/projects/settings/ci_cd/_form.html.haml_spec.rb
+++ b/spec/views/projects/settings/ci_cd/_autodevops_form.html.haml_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe 'projects/settings/ci_cd/_form' do
+describe 'projects/settings/ci_cd/_autodevops_form' do
let(:project) { create(:project, :repository) }
before do
diff --git a/spec/workers/issue_due_scheduler_worker_spec.rb b/spec/workers/issue_due_scheduler_worker_spec.rb
index 7b60835fd26..2710267d384 100644
--- a/spec/workers/issue_due_scheduler_worker_spec.rb
+++ b/spec/workers/issue_due_scheduler_worker_spec.rb
@@ -14,7 +14,9 @@ describe IssueDueSchedulerWorker do
create(:issue, :closed, project: project_closed_issue, due_date: Date.tomorrow)
create(:issue, :opened, project: project_issue_due_another_day, due_date: Date.today)
- expect(MailScheduler::IssueDueWorker).to receive(:bulk_perform_async).with([[project1.id], [project2.id]])
+ expect(MailScheduler::IssueDueWorker).to receive(:bulk_perform_async) do |args|
+ expect(args).to match_array([[project1.id], [project2.id]])
+ end
described_class.new.perform
end
diff --git a/yarn.lock b/yarn.lock
index 55a86a9a577..f05278cfde5 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -77,14 +77,7 @@ abbrev@1.0.x:
version "1.0.9"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135"
-accepts@~1.3.3:
- version "1.3.3"
- resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.3.tgz#c3ca7434938648c3e0d9c1e328dd68b622c284ca"
- dependencies:
- mime-types "~2.1.11"
- negotiator "0.6.1"
-
-accepts@~1.3.4:
+accepts@~1.3.3, accepts@~1.3.4:
version "1.3.4"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.4.tgz#86246758c7dd6d21a6474ff084a4740ec05eb21f"
dependencies:
@@ -118,11 +111,7 @@ acorn@^4.0.3:
version "4.0.13"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787"
-acorn@^5.0.0, acorn@^5.1.1:
- version "5.1.1"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.1.tgz#53fe161111f912ab999ee887a90a0bc52822fd75"
-
-acorn@^5.2.1, acorn@^5.3.0, acorn@^5.4.1:
+acorn@^5.0.0, acorn@^5.2.1, acorn@^5.3.0, acorn@^5.4.1:
version "5.4.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.4.1.tgz#fdc58d9d17f4a4e98d102ded826a9b9759125102"
@@ -160,16 +149,7 @@ ajv@^4.7.0, ajv@^4.9.1:
co "^4.6.0"
json-stable-stringify "^1.0.1"
-ajv@^5.0.0:
- version "5.2.2"
- resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.2.tgz#47c68d69e86f5d953103b0074a9430dc63da5e39"
- dependencies:
- co "^4.6.0"
- fast-deep-equal "^1.0.0"
- json-schema-traverse "^0.3.0"
- json-stable-stringify "^1.0.1"
-
-ajv@^5.1.0:
+ajv@^5.0.0, ajv@^5.1.0:
version "5.5.2"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965"
dependencies:
@@ -242,7 +222,7 @@ ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
-ansi-styles@^3.1.0, ansi-styles@^3.2.0:
+ansi-styles@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88"
dependencies:
@@ -420,13 +400,7 @@ async@1.x, async@^1.4.0, async@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
-async@^2.1.2, async@^2.1.4:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/async/-/async-2.4.1.tgz#62a56b279c98a11d0987096a01cc3eeb8eb7bbd7"
- dependencies:
- lodash "^4.14.0"
-
-async@^2.4.1:
+async@^2.1.2, async@^2.1.4, async@^2.4.1:
version "2.6.0"
resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4"
dependencies:
@@ -1196,11 +1170,7 @@ block-stream@*:
dependencies:
inherits "~2.0.0"
-bluebird@^3.1.1:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c"
-
-bluebird@^3.3.0, bluebird@^3.4.6, bluebird@^3.5.1:
+bluebird@^3.1.1, bluebird@^3.3.0, bluebird@^3.4.6, bluebird@^3.5.1:
version "3.5.1"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9"
@@ -1268,14 +1238,7 @@ boxen@^1.2.1:
term-size "^1.2.0"
widest-line "^2.0.0"
-brace-expansion@^1.0.0, brace-expansion@^1.1.8:
- version "1.1.8"
- resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
- dependencies:
- balanced-match "^1.0.0"
- concat-map "0.0.1"
-
-brace-expansion@^1.1.7:
+brace-expansion@^1.0.0, brace-expansion@^1.1.7, brace-expansion@^1.1.8:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
dependencies:
@@ -1621,15 +1584,7 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
-chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba"
- dependencies:
- ansi-styles "^3.1.0"
- escape-string-regexp "^1.0.5"
- supports-color "^4.0.0"
-
-chalk@^2.3.1:
+chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.0, chalk@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.1.tgz#523fe2678aec7b04e8041909292fe8b17059b796"
dependencies:
@@ -2027,18 +1982,10 @@ copy-webpack-plugin@^4.4.1:
p-limit "^1.0.0"
serialize-javascript "^1.4.0"
-core-js@^2.2.0:
+core-js@^2.2.0, core-js@^2.4.0, core-js@^2.4.1, core-js@^2.5.0:
version "2.5.3"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.3.tgz#8acc38345824f16d8365b7c9b4259168e8ed603e"
-core-js@^2.4.0, core-js@^2.5.0:
- version "2.5.1"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.1.tgz#ae6874dc66937789b80754ff5428df66819ca50b"
-
-core-js@^2.4.1:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e"
-
core-js@~2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.3.0.tgz#fab83fbb0b2d8dc85fa636c4b9d34c75420c6d65"
@@ -2117,7 +2064,7 @@ cryptiles@3.x.x:
dependencies:
boom "5.x.x"
-crypto-browserify@^3.0.0:
+crypto-browserify@^3.0.0, crypto-browserify@^3.11.0:
version "3.12.0"
resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec"
dependencies:
@@ -2133,21 +2080,6 @@ crypto-browserify@^3.0.0:
randombytes "^2.0.0"
randomfill "^1.0.3"
-crypto-browserify@^3.11.0:
- version "3.11.0"
- resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.11.0.tgz#3652a0906ab9b2a7e0c3ce66a408e957a2485522"
- dependencies:
- browserify-cipher "^1.0.0"
- browserify-sign "^4.0.0"
- create-ecdh "^4.0.0"
- create-hash "^1.1.0"
- create-hmac "^1.1.0"
- diffie-hellman "^5.0.0"
- inherits "^2.0.1"
- pbkdf2 "^3.0.3"
- public-encrypt "^4.0.0"
- randombytes "^2.0.0"
-
crypto-random-string@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e"
@@ -2401,7 +2333,7 @@ de-indent@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
-debug@2, debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@~2.6.4, debug@~2.6.6:
+debug@2, debug@2.6.9, debug@^2.1.1, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.6, debug@^2.6.8, debug@~2.6.4, debug@~2.6.6:
version "2.6.9"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
dependencies:
@@ -2413,7 +2345,7 @@ debug@2.2.0, debug@~2.2.0:
dependencies:
ms "0.7.1"
-debug@2.6.8, debug@^2.1.1, debug@^2.6.6, debug@^2.6.8:
+debug@2.6.8:
version "2.6.8"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
dependencies:
@@ -2764,13 +2696,7 @@ encodeurl@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
-end-of-stream@^1.0.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206"
- dependencies:
- once "^1.4.0"
-
-end-of-stream@^1.1.0:
+end-of-stream@^1.0.0, end-of-stream@^1.1.0:
version "1.4.1"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
dependencies:
@@ -3095,14 +3021,7 @@ eslint@^3.18.0:
text-table "~0.2.0"
user-home "^2.0.0"
-espree@^3.4.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.0.tgz#98358625bdd055861ea27e2867ea729faf463d8d"
- dependencies:
- acorn "^5.1.1"
- acorn-jsx "^3.0.0"
-
-espree@^3.5.2:
+espree@^3.4.0, espree@^3.5.2:
version "3.5.2"
resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.2.tgz#756ada8b979e9dcfcdb30aad8d1a9304a905e1ca"
dependencies:
@@ -3730,18 +3649,7 @@ glob@^5.0.15:
once "^1.3.0"
path-is-absolute "^1.0.0"
-glob@^7.0.0, glob@^7.0.3:
- version "7.1.1"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
- dependencies:
- fs.realpath "^1.0.0"
- inflight "^1.0.4"
- inherits "2"
- minimatch "^3.0.2"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
-glob@^7.0.5, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2:
+glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.0, glob@^7.1.1, glob@^7.1.2:
version "7.1.2"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
dependencies:
@@ -4228,11 +4136,7 @@ ignore-by-default@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
-ignore@^3.2.0:
- version "3.3.3"
- resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d"
-
-ignore@^3.3.5, ignore@^3.3.7:
+ignore@^3.2.0, ignore@^3.3.5, ignore@^3.3.7:
version "3.3.7"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021"
@@ -4424,14 +4328,10 @@ is-binary-path@^1.0.0:
dependencies:
binary-extensions "^1.0.0"
-is-buffer@^1.1.0:
+is-buffer@^1.1.0, is-buffer@^1.1.5:
version "1.1.6"
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
-is-buffer@^1.1.5:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.5.tgz#1f3b26ef613b214b88cbca23cc6c01d87961eecc"
-
is-builtin-module@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe"
@@ -4547,16 +4447,7 @@ is-my-ip-valid@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824"
-is-my-json-valid@^2.10.0:
- version "2.16.0"
- resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693"
- dependencies:
- generate-function "^2.0.0"
- generate-object-property "^1.1.0"
- jsonpointer "^4.0.0"
- xtend "^4.0.0"
-
-is-my-json-valid@^2.12.4:
+is-my-json-valid@^2.10.0, is-my-json-valid@^2.12.4:
version "2.17.2"
resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz#6b2103a288e94ef3de5cf15d29dd85fc4b78d65c"
dependencies:
@@ -4732,10 +4623,6 @@ isbinaryfile@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/isbinaryfile/-/isbinaryfile-3.0.2.tgz#4a3e974ec0cba9004d3fc6cde7209ea69368a621"
-isexe@^1.1.1:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0"
-
isexe@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
@@ -5298,7 +5185,7 @@ lodash.words@^4.0.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/lodash.words/-/lodash.words-4.2.0.tgz#5ecfeaf8ecf8acaa8e0c8386295f1993c9cf4036"
-lodash@4.17.4, lodash@^4.11.1, lodash@^4.17.2, lodash@^4.2.0, lodash@^4.3.0:
+lodash@4.17.4:
version "4.17.4"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
@@ -5306,7 +5193,7 @@ lodash@^3.8.0:
version "3.10.1"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6"
-lodash@^4.0.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.4, lodash@^4.5.0:
+lodash@^4.0.0, lodash@^4.11.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.2, lodash@^4.17.4, lodash@^4.2.0, lodash@^4.3.0, lodash@^4.5.0:
version "4.17.5"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511"
@@ -5534,15 +5421,11 @@ miller-rabin@^4.0.0:
bn.js "^4.0.0"
brorand "^1.0.1"
-"mime-db@>= 1.29.0 < 2":
- version "1.29.0"
- resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.29.0.tgz#48d26d235589651704ac5916ca06001914266878"
-
-mime-db@~1.33.0:
+"mime-db@>= 1.29.0 < 2", mime-db@~1.33.0:
version "1.33.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db"
-mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.7:
+mime-types@^2.1.11, mime-types@^2.1.12, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.7:
version "2.1.18"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8"
dependencies:
@@ -6100,16 +5983,12 @@ p-finally@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae"
-p-limit@^1.0.0:
+p-limit@^1.0.0, p-limit@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.2.0.tgz#0e92b6bedcb59f022c13d0f1949dc82d15909f1c"
dependencies:
p-try "^1.0.0"
-p-limit@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc"
-
p-locate@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
@@ -6167,11 +6046,7 @@ pako@~0.2.0:
version "0.2.9"
resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
-pako@~1.0.2:
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.5.tgz#d2205dfe5b9da8af797e7c163db4d1f84e4600bc"
-
-pako@~1.0.5:
+pako@~1.0.2, pako@~1.0.5:
version "1.0.6"
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258"
@@ -6649,7 +6524,7 @@ postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0.13, postcss@^5.0
source-map "^0.5.6"
supports-color "^3.2.3"
-postcss@^6.0.1:
+postcss@^6.0.1, postcss@^6.0.14, postcss@^6.0.8:
version "6.0.19"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.19.tgz#76a78386f670b9d9494a655bf23ac012effd1555"
dependencies:
@@ -6657,22 +6532,6 @@ postcss@^6.0.1:
source-map "^0.6.1"
supports-color "^5.2.0"
-postcss@^6.0.14:
- version "6.0.15"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.15.tgz#f460cd6269fede0d1bf6defff0b934a9845d974d"
- dependencies:
- chalk "^2.3.0"
- source-map "^0.6.1"
- supports-color "^5.1.0"
-
-postcss@^6.0.8:
- version "6.0.14"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.14.tgz#5534c72114739e75d0afcf017db853099f562885"
- dependencies:
- chalk "^2.3.0"
- source-map "^0.6.1"
- supports-color "^4.4.0"
-
prelude-ls@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
@@ -6685,14 +6544,10 @@ preserve@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b"
-prettier@1.11.1:
+prettier@1.11.1, prettier@^1.7.0:
version "1.11.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.11.1.tgz#61e43fc4cd44e68f2b0dfc2c38cd4bb0fccdcc75"
-prettier@^1.7.0:
- version "1.8.2"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.8.2.tgz#bff83e7fd573933c607875e5ba3abbdffb96aeb8"
-
prismjs@^1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.6.0.tgz#118d95fb7a66dba2272e343b345f5236659db365"
@@ -6711,11 +6566,7 @@ process-nextick-args@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa"
-process@^0.11.0:
- version "0.11.9"
- resolved "https://registry.yarnpkg.com/process/-/process-0.11.9.tgz#7bd5ad21aa6253e7da8682264f1e11d11c0318c1"
-
-process@~0.11.0:
+process@^0.11.0, process@~0.11.0:
version "0.11.10"
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
@@ -6894,16 +6745,7 @@ raw-loader@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-0.5.1.tgz#0c3d0beaed8a01c966d9787bf778281252a979aa"
-rc@^1.0.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95"
- dependencies:
- deep-extend "~0.4.0"
- ini "~1.3.0"
- minimist "^1.2.0"
- strip-json-comments "~2.0.1"
-
-rc@^1.1.6, rc@^1.1.7:
+rc@^1.0.1, rc@^1.1.6, rc@^1.1.7:
version "1.2.5"
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.5.tgz#275cd687f6e3b36cc756baa26dfee80a790301fd"
dependencies:
@@ -6975,7 +6817,7 @@ read-pkg@^2.0.0:
normalize-package-data "^2.3.2"
path-type "^2.0.0"
-"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.3.0, readable-stream@^2.3.3:
+"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3:
version "2.3.4"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.4.tgz#c946c3f47fa7d8eabc0b6150f4a12f69a4574071"
dependencies:
@@ -6996,19 +6838,7 @@ readable-stream@1.1.x, "readable-stream@1.x >=1.1.9":
isarray "0.0.1"
string_decoder "~0.10.x"
-readable-stream@^2.0.0, readable-stream@^2.1.0, readable-stream@^2.2.2, readable-stream@^2.2.9:
- version "2.3.3"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
- dependencies:
- core-util-is "~1.0.0"
- inherits "~2.0.3"
- isarray "~1.0.0"
- process-nextick-args "~1.0.6"
- safe-buffer "~5.1.1"
- string_decoder "~1.0.3"
- util-deprecate "~1.0.1"
-
-readable-stream@^2.0.1, readable-stream@^2.0.5, readable-stream@~2.0.0, readable-stream@~2.0.5, readable-stream@~2.0.6:
+readable-stream@~2.0.0, readable-stream@~2.0.5, readable-stream@~2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.0.6.tgz#8f90341e68a53ccc928788dacfcd11b36eb9b78e"
dependencies:
@@ -7350,18 +7180,12 @@ right-align@^0.1.1:
dependencies:
align-text "^0.1.1"
-rimraf@2, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1, rimraf@^2.6.2:
+rimraf@2, rimraf@^2.2.8, rimraf@^2.5.1, rimraf@^2.5.4, rimraf@^2.6.0, rimraf@^2.6.1, rimraf@^2.6.2:
version "2.6.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36"
dependencies:
glob "^7.0.5"
-rimraf@^2.2.8:
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
- dependencies:
- glob "^7.0.5"
-
ripemd160@^2.0.0, ripemd160@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.1.tgz#0f4584295c53a3628af7e6d79aca21ce57d1c6e7"
@@ -7464,11 +7288,7 @@ semver-diff@^2.0.0:
dependencies:
semver "^5.0.3"
-"semver@2 || 3 || 4 || 5", semver@^5.0.3:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
-
-semver@^5.1.0, semver@^5.3.0, semver@^5.4.1:
+"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1:
version "5.5.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
@@ -7937,7 +7757,7 @@ stream-each@^1.1.0:
end-of-stream "^1.1.0"
stream-shift "^1.0.0"
-stream-http@^2.0.0:
+stream-http@^2.0.0, stream-http@^2.3.1:
version "2.8.0"
resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.0.tgz#fd86546dac9b1c91aff8fc5d287b98fafb41bc10"
dependencies:
@@ -7947,16 +7767,6 @@ stream-http@^2.0.0:
to-arraybuffer "^1.0.0"
xtend "^4.0.0"
-stream-http@^2.3.1:
- version "2.6.3"
- resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.6.3.tgz#4c3ddbf9635968ea2cfd4e48d43de5def2625ac3"
- dependencies:
- builtin-status-codes "^3.0.0"
- inherits "^2.0.1"
- readable-stream "^2.1.0"
- to-arraybuffer "^1.0.0"
- xtend "^4.0.0"
-
stream-shift@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952"
@@ -7989,14 +7799,7 @@ string-width@^1.0.1, string-width@^1.0.2:
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
-string-width@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.0.0.tgz#635c5436cc72a6e0c387ceca278d4e2eec52687e"
- dependencies:
- is-fullwidth-code-point "^2.0.0"
- strip-ansi "^3.0.0"
-
-string-width@^2.1.0, string-width@^2.1.1:
+string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
dependencies:
@@ -8076,25 +7879,13 @@ supports-color@^3.1.0, supports-color@^3.1.2, supports-color@^3.2.3:
dependencies:
has-flag "^1.0.0"
-supports-color@^4.0.0, supports-color@^4.4.0:
+supports-color@^4.2.1:
version "4.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b"
dependencies:
has-flag "^2.0.0"
-supports-color@^4.2.1:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.2.1.tgz#65a4bb2631e90e02420dba5554c375a4754bb836"
- dependencies:
- has-flag "^2.0.0"
-
-supports-color@^5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.1.0.tgz#058a021d1b619f7ddf3980d712ea3590ce7de3d5"
- dependencies:
- has-flag "^2.0.0"
-
-supports-color@^5.2.0:
+supports-color@^5.1.0, supports-color@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.2.0.tgz#b0d5333b1184dd3666cbe5aa0b45c5ac7ac17a4a"
dependencies:
@@ -8828,13 +8619,7 @@ which-module@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
-which@^1.1.1, which@^1.2.1, which@^1.2.9:
- version "1.2.12"
- resolved "https://registry.yarnpkg.com/which/-/which-1.2.12.tgz#de67b5e450269f194909ef23ece4ebe416fa1192"
- dependencies:
- isexe "^1.1.1"
-
-which@^1.2.14:
+which@^1.1.1, which@^1.2.1, which@^1.2.14, which@^1.2.9:
version "1.3.0"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a"
dependencies: